#include "uart_declarations.h" // IRQs: USART2, USART3, UART5 // ***************************** Definitions ***************************** #define UART_BUFFER(x, size_rx, size_tx, uart_ptr, callback_ptr, overwrite_mode) \ static uint8_t elems_rx_##x[size_rx]; \ static uint8_t elems_tx_##x[size_tx]; \ extern uart_ring uart_ring_##x; \ uart_ring uart_ring_##x = { \ .w_ptr_tx = 0, \ .r_ptr_tx = 0, \ .elems_tx = ((uint8_t *)&(elems_tx_##x)), \ .tx_fifo_size = (size_tx), \ .w_ptr_rx = 0, \ .r_ptr_rx = 0, \ .elems_rx = ((uint8_t *)&(elems_rx_##x)), \ .rx_fifo_size = (size_rx), \ .uart = (uart_ptr), \ .callback = (callback_ptr), \ .overwrite = (overwrite_mode) \ }; // ******************************** UART buffers ******************************** // debug = USART2 UART_BUFFER(debug, FIFO_SIZE_INT, FIFO_SIZE_INT, USART2, debug_ring_callback, true) // SOM debug = UART7 #ifdef STM32H7 UART_BUFFER(som_debug, FIFO_SIZE_INT, FIFO_SIZE_INT, UART7, NULL, true) #else // UART7 is not available on F4 UART_BUFFER(som_debug, 1U, 1U, NULL, NULL, true) #endif uart_ring *get_ring_by_number(int a) { uart_ring *ring = NULL; switch(a) { case 0: ring = &uart_ring_debug; break; case 4: ring = &uart_ring_som_debug; break; default: ring = NULL; break; } return ring; } // ************************* Low-level buffer functions ************************* bool get_char(uart_ring *q, char *elem) { bool ret = false; ENTER_CRITICAL(); if (q->w_ptr_rx != q->r_ptr_rx) { if (elem != NULL) *elem = q->elems_rx[q->r_ptr_rx]; q->r_ptr_rx = (q->r_ptr_rx + 1U) % q->rx_fifo_size; ret = true; } EXIT_CRITICAL(); return ret; } bool injectc(uart_ring *q, char elem) { int ret = false; uint16_t next_w_ptr; ENTER_CRITICAL(); next_w_ptr = (q->w_ptr_rx + 1U) % q->rx_fifo_size; if ((next_w_ptr == q->r_ptr_rx) && q->overwrite) { // overwrite mode: drop oldest byte q->r_ptr_rx = (q->r_ptr_rx + 1U) % q->rx_fifo_size; } if (next_w_ptr != q->r_ptr_rx) { q->elems_rx[q->w_ptr_rx] = elem; q->w_ptr_rx = next_w_ptr; ret = true; } EXIT_CRITICAL(); return ret; } bool put_char(uart_ring *q, char elem) { bool ret = false; uint16_t next_w_ptr; ENTER_CRITICAL(); next_w_ptr = (q->w_ptr_tx + 1U) % q->tx_fifo_size; if ((next_w_ptr == q->r_ptr_tx) && q->overwrite) { // overwrite mode: drop oldest byte q->r_ptr_tx = (q->r_ptr_tx + 1U) % q->tx_fifo_size; } if (next_w_ptr != q->r_ptr_tx) { q->elems_tx[q->w_ptr_tx] = elem; q->w_ptr_tx = next_w_ptr; ret = true; } EXIT_CRITICAL(); uart_tx_ring(q); return ret; } void clear_uart_buff(uart_ring *q) { ENTER_CRITICAL(); q->w_ptr_tx = 0; q->r_ptr_tx = 0; q->w_ptr_rx = 0; q->r_ptr_rx = 0; EXIT_CRITICAL(); } // ************************ High-level debug functions ********************** void putch(const char a) { // misra-c2012-17.7: serial debug function, ok to ignore output (void)injectc(&uart_ring_debug, a); } void print(const char *a) { for (const char *in = a; *in; in++) { if (*in == '\n') putch('\r'); putch(*in); } } void puthx(uint32_t i, uint8_t len) { const char c[] = "0123456789abcdef"; for (int pos = ((int)len * 4) - 4; pos > -4; pos -= 4) { putch(c[(i >> (unsigned int)(pos)) & 0xFU]); } } void puth(unsigned int i) { puthx(i, 8U); } #if defined(ENABLE_SPI) || defined(BOOTSTUB) || defined(DEBUG) void puth4(unsigned int i) { puthx(i, 4U); } #endif #if defined(ENABLE_SPI) || defined(BOOTSTUB) || defined(DEBUG_USB) || defined(DEBUG_COMMS) void hexdump(const void *a, int l) { if (a != NULL) { for (int i=0; i < l; i++) { if ((i != 0) && ((i & 0xf) == 0)) print("\n"); puthx(((const unsigned char*)a)[i], 2U); print(" "); } } print("\n"); } #endif