diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..9792498 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "editor.formatOnSave": false +} \ No newline at end of file diff --git a/Core/Src/main.c b/Core/Src/main.c index 05a9506..2dea81a 100644 --- a/Core/Src/main.c +++ b/Core/Src/main.c @@ -22,6 +22,8 @@ /* Private includes ----------------------------------------------------------*/ /* USER CODE BEGIN Includes */ #include +#include +#include /* USER CODE END Includes */ @@ -45,8 +47,9 @@ UART_HandleTypeDef huart1; UART_HandleTypeDef huart2; /* USER CODE BEGIN PV */ -static uint8_t rx_buf[16]; -static volatile uint8_t rx_complete = 0; +static uint8_t rx_buf[64]; +static bool rx_complete = false; +static volatile uint16_t rx_length = 0; /* USER CODE END PV */ /* Private function prototypes -----------------------------------------------*/ @@ -55,13 +58,65 @@ static void MX_GPIO_Init(void); static void MX_USART1_UART_Init(void); static void MX_USART2_UART_Init(void); /* USER CODE BEGIN PFP */ - +static void hex_dump(const uint8_t *data, uint16_t len); /* USER CODE END PFP */ /* Private user code ---------------------------------------------------------*/ /* USER CODE BEGIN 0 */ static char heartbeat_buf[64]; +/** + * @brief Print hex dump in ESP-IDF style + * @param data: pointer to data buffer + * @param len: length of data + * @retval None + */ +static void hex_dump(const uint8_t *data, uint16_t len) +{ + char line_buf[80]; + + for (uint16_t i = 0; i < len; i += 16) { + // Print address + int pos = snprintf(line_buf, sizeof(line_buf), "0x%08lx ", (unsigned long)(data + i)); + + // Print hex values (first 8 bytes) + for (int j = 0; j < 8; j++) { + if (i + j < len) { + pos += snprintf(line_buf + pos, sizeof(line_buf) - pos, "%02x ", data[i + j]); + } else { + pos += snprintf(line_buf + pos, sizeof(line_buf) - pos, " "); + } + } + + // Space between two groups + pos += snprintf(line_buf + pos, sizeof(line_buf) - pos, " "); + + // Print hex values (second 8 bytes) + for (int j = 8; j < 16; j++) { + if (i + j < len) { + pos += snprintf(line_buf + pos, sizeof(line_buf) - pos, "%02x ", data[i + j]); + } else { + pos += snprintf(line_buf + pos, sizeof(line_buf) - pos, " "); + } + } + + // Print ASCII representation + pos += snprintf(line_buf + pos, sizeof(line_buf) - pos, " |"); + for (int j = 0; j < 16 && (i + j) < len; j++) { + uint8_t c = data[i + j]; + if (c >= 32 && c <= 126) { + pos += snprintf(line_buf + pos, sizeof(line_buf) - pos, "%c", c); + } else { + pos += snprintf(line_buf + pos, sizeof(line_buf) - pos, "."); + } + } + pos += snprintf(line_buf + pos, sizeof(line_buf) - pos, "|\r\n"); + + // Send line to UART1 + HAL_UART_Transmit(&huart1, (uint8_t *)line_buf, (uint16_t)pos, HAL_MAX_DELAY); + } +} + /* USER CODE END 0 */ /** @@ -96,6 +151,8 @@ int main(void) MX_USART1_UART_Init(); MX_USART2_UART_Init(); /* USER CODE BEGIN 2 */ + /* Enable UART IDLE interrupt */ + __HAL_UART_ENABLE_IT(&huart2, UART_IT_IDLE); /* Start UART2 reception in interrupt mode */ HAL_UART_Receive_IT(&huart2, rx_buf, sizeof(rx_buf)); /* USER CODE END 2 */ @@ -121,16 +178,19 @@ int main(void) /* Check if data received from UART2 */ if (rx_complete) { - rx_complete = 0; + rx_complete = false; + uint16_t len = rx_length; - /* Print received buffer as hex to UART1 */ - char hex_buf[64]; - int hex_len = snprintf(hex_buf, sizeof(hex_buf), "RX: "); - for (int i = 0; i < (int)sizeof(rx_buf) && hex_len < (int)sizeof(hex_buf) - 4; i++) { - hex_len += snprintf(hex_buf + hex_len, sizeof(hex_buf) - hex_len, "%02X ", rx_buf[i]); - } - hex_len += snprintf(hex_buf + hex_len, sizeof(hex_buf) - hex_len, "\r\n"); - HAL_UART_Transmit(&huart1, (uint8_t *)hex_buf, (uint16_t)hex_len, HAL_MAX_DELAY); + /* Print header */ + char header[32]; + int header_len = snprintf(header, sizeof(header), "RX[%u]:\r\n", len); + HAL_UART_Transmit(&huart1, (uint8_t *)header, (uint16_t)header_len, HAL_MAX_DELAY); + + /* Print received buffer as hex dump */ + hex_dump(rx_buf, len); + + /* Clear buffer before re-arming */ + memset(rx_buf, 0, sizeof(rx_buf)); /* Re-arm UART2 reception */ HAL_UART_Receive_IT(&huart2, rx_buf, sizeof(rx_buf)); @@ -297,14 +357,34 @@ static void MX_GPIO_Init(void) /* USER CODE BEGIN 4 */ /** - * @brief Rx Transfer completed callback - * @param huart: UART handle + * @brief UART IDLE line detected callback + * @note This is called from USART2_IRQHandler when IDLE interrupt occurs * @retval None */ -void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) +void UART_IDLE_Callback(UART_HandleTypeDef *huart) { if (huart->Instance == USART2) { - rx_complete = 1; + if (huart->RxState != HAL_UART_STATE_BUSY_RX) { + /* Not in reception state, ignore */ + return; + } + /* Calculate how many bytes were actually received */ + + /** + * RxXferCount is a countdown timer maintained by the HAL library that + * decrements with each byte received. Subtracting it from the total + * gives you the actual number of bytes that made it into the buffer. + */ + rx_length = sizeof(rx_buf) - huart->RxXferCount; + + /* Only process if we actually received data */ + if (rx_length > 0) { + /* Abort the ongoing reception */ + HAL_UART_AbortReceive_IT(&huart2); + + /* Signal that data is ready */ + rx_complete = true; + } } } diff --git a/Core/Src/stm32f4xx_it.c b/Core/Src/stm32f4xx_it.c index c024f77..5ef6d18 100644 --- a/Core/Src/stm32f4xx_it.c +++ b/Core/Src/stm32f4xx_it.c @@ -219,7 +219,15 @@ void USART1_IRQHandler(void) void USART2_IRQHandler(void) { /* USER CODE BEGIN USART2_IRQn 0 */ - + /* Check for IDLE line detection */ + if (__HAL_UART_GET_FLAG(&huart2, UART_FLAG_IDLE)) { + /* Clear IDLE flag by reading SR and DR */ + __HAL_UART_CLEAR_IDLEFLAG(&huart2); + + /* Call custom IDLE callback */ + extern void UART_IDLE_Callback(UART_HandleTypeDef *huart); + UART_IDLE_Callback(&huart2); + } /* USER CODE END USART2_IRQn 0 */ HAL_UART_IRQHandler(&huart2); /* USER CODE BEGIN USART2_IRQn 1 */