diff options
Diffstat (limited to 'libraries')
| -rw-r--r-- | libraries/fifo.c | 66 | ||||
| -rw-r--r-- | libraries/fifo.h | 62 | ||||
| -rw-r--r-- | libraries/usart.c | 127 | ||||
| -rw-r--r-- | libraries/usart.h | 47 | 
4 files changed, 302 insertions, 0 deletions
| diff --git a/libraries/fifo.c b/libraries/fifo.c new file mode 100644 index 0000000..faa9fc4 --- /dev/null +++ b/libraries/fifo.c @@ -0,0 +1,66 @@ + + +#include "fifo.h" + + +void fifo_init(FIFO *fifo, uint16_t bufferlength) +{ +    fifo->buffer_ptr = calloc(bufferlength, sizeof(uint8_t)); +    fifo->read_index = 0; +    fifo->write_index = 0; +    fifo->bufferlength = bufferlength; +} + +void fifo_deinit(FIFO *fifo) +{ +    free(fifo->buffer_ptr); +} + +uint16_t fifo_get_buffersize(FIFO *fifo) +{ +    return fifo->bufferlength; +} + +uint16_t fifo_bytes_available(FIFO *fifo) +{ +    if (fifo->write_index > fifo->read_index){ +        return (fifo->write_index - fifo->read_index); +    } +    else if (fifo->write_index < fifo->read_index){ +        return (fifo_get_buffersize(fifo) - (fifo->read_index - fifo->write_index)); +    } +    else {  // read_index == write_index +        return 0; +    } +} + +//uint16_t fifo_lines_available(FIFO *fifo){} + +void fifo_move_read_index(FIFO *fifo) +{ +    fifo->read_index++; +    fifo->read_index %= fifo_get_buffersize(fifo); +} + +void fifo_move_write_index(FIFO *fifo) +{ +    fifo->write_index++; +    fifo->write_index %= fifo_get_buffersize(fifo); +} + +void fifo_get_byte(FIFO *fifo, uint8_t *data_sink) +{ +    if(fifo_bytes_available(fifo)){ +        *data_sink = fifo->buffer_ptr[fifo->read_index]; +        fifo_move_read_index(fifo); +    } +} + +void fifo_put_byte(FIFO *fifo, uint8_t *data_source) +{ +    fifo->buffer_ptr[fifo->write_index] = *data_source; +    fifo_move_write_index(fifo); +    if(fifo->read_index == fifo->write_index){  // buffer overflow case +        fifo_move_read_index(fifo); +    } +} diff --git a/libraries/fifo.h b/libraries/fifo.h new file mode 100644 index 0000000..c56d410 --- /dev/null +++ b/libraries/fifo.h @@ -0,0 +1,62 @@ + + +/*  +    FIFO Ring Buffer uint8_t array ring_buffer (example length is 8)  +       with data (x) and read and write index: + +     --- --- --- --- --- --- --- --- +    |   |   | x | x | x |   |   |   | +     --- --- --- --- --- --- --- --- +              ^           ^ +              |           | +          read_index      | +                     write_index + +     --- --- --- --- --- --- --- --- +    | x | x |   |   |   | x | x | x | +     --- --- --- --- --- --- --- --- +              ^           ^ +              |           | +         write_index      | +                      read_index + +    - input data goes to position of write_index +    - output data comes from read_index position +    - after input/output operation the according index has to be modified +    - according to the idea of ring buffers the write_index could be  +      smaller than the read_index +*/ + + +#ifndef FIFO_H +#define FIFO_H + + +#include <stdint.h> +#include <stdlib.h> + + +typedef struct FIFO{ +    uint8_t *buffer_ptr; +    uint16_t read_index; +    uint16_t write_index; +    uint16_t bufferlength; +} FIFO; + + +void fifo_init(FIFO *fifo, uint16_t bufferlength); +void fifo_deinit(FIFO *fifo); + +uint16_t fifo_get_buffersize(FIFO *fifo); + +uint16_t fifo_bytes_available(FIFO *fifo); +uint16_t fifo_lines_available(FIFO *fifo); + +void fifo_move_read_index(FIFO *fifo); +void fifo_move_write_index(FIFO *fifo); + +void fifo_get_byte(FIFO *fifo, uint8_t *data_sink); +void fifo_put_byte(FIFO *fifo, uint8_t *data_source); + + +#endif /* FIFO_H */ diff --git a/libraries/usart.c b/libraries/usart.c new file mode 100644 index 0000000..61de99c --- /dev/null +++ b/libraries/usart.c @@ -0,0 +1,127 @@ + + +#include "usart.h" + + +extern USART usart3; + + +// init functions + +void usart_init(USART *usart) +{ +    // clock config +    rcc_periph_clock_enable(RCC_GPIOB);  // for USART3 +    rcc_periph_clock_enable(RCC_USART3);  // for USART3 + +    // gpio config +    gpio_set_mode(GPIOB, GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, GPIO_USART3_TX);  // TX setup +    gpio_set_mode(GPIOB, GPIO_MODE_INPUT, GPIO_CNF_INPUT_FLOAT, GPIO_USART3_RX);  // RX setup + +    // nvic config +    nvic_enable_irq(NVIC_USART3_IRQ); +    usart_enable_rx_interrupt(USART3); + +    // usart config +    usart_set_baudrate(USART3, 9600); +    usart_set_databits(USART3, 8); +    usart_set_flow_control(USART3, USART_FLOWCONTROL_NONE); +    usart_set_mode(USART3, USART_MODE_TX_RX); +    usart_set_parity(USART3, USART_PARITY_NONE); +    usart_set_stopbits(USART3, USART_STOPBITS_1); +    usart_enable(USART3); + +    // fifo init +    fifo_init(&usart->rx_fifo, USART_BUFFER_SIZE); +    fifo_init(&usart->tx_fifo, USART_BUFFER_SIZE); +} + +void usart_deinit(USART *usart) +{ +    fifo_deinit(&usart->rx_fifo); +    fifo_deinit(&usart->tx_fifo); +} + + +// write functions + +uint16_t usart_write_bytes(USART *usart, uint8_t *data_source, uint16_t data_length){ +    if ((data_length + fifo_bytes_available(&usart->tx_fifo)) <= fifo_get_buffersize(&usart->tx_fifo)){ +        for (int i=0; i<data_length; i++){ +            fifo_put_byte(&usart->tx_fifo, &data_source[i]); +        } +        usart_enable_tx_interrupt(USART3); +        return data_length; +    } +    else{ +        return 0; +    } +} + +uint16_t usart_write(USART *usart, char *str) +{ +    for (uint16_t i=0; i<(uint16_t)strlen(str); i++){ +        usart_write_bytes(usart, (uint8_t *)&str[i], 1); +    } +    return (uint16_t)strlen(str); +} +//uint16_t usart_writeln(USART *usart, char *str); + + +// read functions + +uint16_t usart_read_bytes(USART *usart, uint8_t *data_sink, uint16_t data_length) +{ +    if (data_length <= fifo_bytes_available(&usart->rx_fifo)){ +        for (int i=0; i<data_length; i++){ +            fifo_get_byte(&usart->rx_fifo, &data_sink[i]); +        } +        return data_length; +    } +    else{ +        return 0; +    } +} +//uint16_t usart_read(USART *usart, char *data_sink, uint16_t data_length); +//uint16_t usart_readln(USART *usart, char *data_sink); + + +// usart isr + +void usart3_isr(void) +{ + +	/* Check if we were called because of RXNE. */ +	if (((USART_CR1(USART3) & USART_CR1_RXNEIE) != 0) && +		((USART_SR(USART3) & USART_SR_RXNE) != 0)) { + +		/* Retrieve the data from the peripheral. */ +		uint8_t data = usart_recv(USART3); +        fifo_put_byte(&usart3.rx_fifo, &data); + +		/* Enable transmit interrupt so it sends back the data. */ +		//USART_CR1(USART3) |= USART_CR1_TXEIE; +	} + +	/* Check if we were called because of TXE. */ +	if (((USART_CR1(USART3) & USART_CR1_TXEIE) != 0) && +		((USART_SR(USART3) & USART_SR_TXE) != 0)) { + +		/* Put data into the transmit register. */ +        if (fifo_bytes_available(&usart3.tx_fifo)){ +            uint8_t data; +            fifo_get_byte(&usart3.tx_fifo, &data); +            usart_send(USART3, data); +            if(data == '\r'){ +                uint8_t nl = (uint8_t)'\n'; +                usart_write_bytes(&usart3, &nl, 1); +            } +            if (fifo_bytes_available(&usart3.tx_fifo)){ +                usart_enable_tx_interrupt(USART3); +            } +            else{ +                usart_disable_tx_interrupt(USART3); +            } +        } +    } +} diff --git a/libraries/usart.h b/libraries/usart.h new file mode 100644 index 0000000..cac971b --- /dev/null +++ b/libraries/usart.h @@ -0,0 +1,47 @@ + + +#ifndef USART_H +#define USART_H + + +#include <string.h> + +#include <libopencm3/stm32/rcc.h> +#include <libopencm3/stm32/gpio.h> +#include <libopencm3/stm32/usart.h> +#include <libopencm3/cm3/nvic.h> + +#include "fifo.h" + +#define USART_BUFFER_SIZE 30 + + +typedef struct USART{ + +    FIFO rx_fifo; +    FIFO tx_fifo; + +} USART; + + +// init functions + +void usart_init(USART *usart); +void usart_deinit(USART *usart); + + +// write functions + +uint16_t usart_write_bytes(USART *usart, uint8_t *data_source, uint16_t data_length); +uint16_t usart_write(USART *usart, char *str); +//uint16_t usart_writeln(USART *usart, char *str); + + +// read functions + +uint16_t usart_read_bytes(USART *usart, uint8_t *data_sink, uint16_t data_length); +//uint16_t usart_read(USART *usart, char *data_sink, uint16_t data_length); +//uint16_t usart_readln(USART *usart, char *data_sink); + + +#endif /* USART_H */ | 
