Skip to content

Commit 67e122f

Browse files
committed
[bootloader/uart_driver] Adding uart watchdog to recover uart it receive
This commit is about adding uart watchdog. The TIM1 is used to clear the uart periodically, when the uart is inactive. It might be the case that some bytes are received (less than 256). If that happens, uart will still wait for the rest of the bytes until it receives 256, in order to parse them. This can create a permanent issue in uart communication. After a period of inactivity, uart is reinitialized to expect again 256 bytes. Signed-off-by: George Pappas <pappasgeorge12@gmail.com>
1 parent 13da90c commit 67e122f

File tree

4 files changed

+87
-3
lines changed

4 files changed

+87
-3
lines changed

projects/bootloader/boards/stm32f401re/Src/stm32f4xx_it.c

+13
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
#include "uart_driver.h"
2323
#include "stm32f4xx_hal.h"
2424
#include "stm32f4xx_it.h"
25+
#include "stm32f401xe.h"
26+
#include <stdio.h>
2527

2628
/* External variables --------------------------------------------------------*/
2729
extern UART_HandleTypeDef huart2;
@@ -128,4 +130,15 @@ void
128130
USART2_IRQHandler(void)
129131
{
130132
HAL_UART_IRQHandler(&huart2);
133+
uart_driver_feed_wdg();
131134
}
135+
136+
void
137+
TIM1_UP_TIM10_IRQHandler(void)
138+
{
139+
if (TIM1->SR & TIM_SR_UIF) // If update interrupt flag is set
140+
{
141+
TIM1->SR &= ~TIM_SR_UIF; // Clear the interrupt flag
142+
uart_driver_rx_recover();
143+
}
144+
}

projects/bootloader/src/drivers/uart/uart_driver.c

+67-1
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,12 @@
1414
#include <stdio.h>
1515
#include <stdint.h>
1616
#include "stm32f4xx_hal.h"
17+
#include "stm32f401xe.h" // stm32f401re
1718
#include "sys_init.h"
1819

20+
// --- defines ---------------------------------------------------------------------------------------------------------
21+
#define TIM1_COUNTDOWN_SEC 15 // 15 seconds timeout for the uart reception watchdog
22+
1923
// --- static variable definitions -------------------------------------------------------------------------------------
2024
// This is the structure that will store the received buffer and the size of it. This will be used by the upper layers
2125
// to receive the data.
@@ -27,9 +31,43 @@ static process_rx_data data_rx_cb = NULL;
2731
UART_HandleTypeDef huart2;
2832

2933
// --- static function declarations ------------------------------------------------------------------------------------
34+
static void uart_recv_it_init_wdg(void);
3035
static void MX_USART2_UART_Init(void);
3136

3237
// --- static function definitions -------------------------------------------------------------------------------------
38+
/**
39+
* @brief This function initializes the timer1 peripheral to be used as a watchdog for the uart reception.
40+
* TODO: GPA: We can set the timer to one-pulse mode, so that it will stop after the timeout. The timer can be
41+
* re-enabled by the uart isr, only when needed.
42+
*
43+
*/
44+
static void
45+
uart_recv_it_init_wdg(void)
46+
{
47+
// Enable the TIM1 clock
48+
RCC->APB2ENR |= RCC_APB2ENR_TIM1EN;
49+
50+
TIM1->SMCR = 0;
51+
TIM1->DIER = TIM_DIER_UIE; // Enable update interrupt
52+
TIM1->SR = 0; // Clear status register
53+
TIM1->EGR = TIM_EGR_UG; // Generate an update event to reload the prescaler
54+
// Configure the prescaler such is to generate 1ms ticks. The systemclock is 84mhz
55+
TIM1->PSC = 21000 - 1; // this means 1ms -> 4000 ticks
56+
57+
// Set the auto-reload value for a 15-second countdown
58+
TIM1->ARR = TIM1_COUNTDOWN_SEC * 4000 - 1;
59+
TIM1->CNT = TIM1->ARR; // Set the counter to the auto-reload value
60+
TIM1->CR2 = 0;
61+
// CR1 config: URS = 1, DIR = 1, CEN = 1
62+
TIM1->CR1 = (TIM_CR1_URS | TIM_CR1_DIR | TIM_CR1_CEN);
63+
64+
// Clear any pending update interrupt flags
65+
TIM1->SR &= ~TIM_SR_UIF;
66+
// Enable the update interrupt for TIM1 in NVIC
67+
NVIC_SetPriority(TIM1_UP_TIM10_IRQn, 0); // Set interrupt priority
68+
NVIC_EnableIRQ(TIM1_UP_TIM10_IRQn);
69+
}
70+
3371
/**
3472
* @brief USART2 Initialization Function
3573
* @param None
@@ -68,6 +106,8 @@ MX_USART2_UART_Init(void) // Change from MX_USART1_UART_Init to MX_USART2_UART_I
68106
#endif
69107
}
70108
HAL_UART_Receive_IT(&huart2, uart_buf.data_buffer, uart_buf.len); // Start reception
109+
// Init the uart watchdog
110+
uart_recv_it_init_wdg();
71111
}
72112

73113
// --- function definitions --------------------------------------------------------------------------------------------
@@ -124,7 +164,8 @@ HAL_UART_ErrorCallback(UART_HandleTypeDef *huart)
124164
{
125165
if (huart->Instance == USART2)
126166
{
127-
// TODO: GPA: Handle the possible errors and restart the reception
167+
HAL_UART_DeInit(&huart2);
168+
HAL_UART_Init(&huart2);
128169
HAL_UART_Receive_IT(&huart2, uart_buf.data_buffer, uart_buf.len);
129170
}
130171
}
@@ -139,6 +180,31 @@ uart_driver_init(void)
139180
MX_USART2_UART_Init();
140181
}
141182

183+
/**
184+
* @brief Function to feed the uart watchdog. Will be called by the uart isr, every time something is being received.
185+
*
186+
*/
187+
void
188+
uart_driver_feed_wdg(void)
189+
{
190+
// Reset the uart wdg timer to not trigger the buffer reset.
191+
TIM1->CNT = TIM1->ARR;
192+
}
193+
194+
/**
195+
* @brief Function to recover the uart reception.
196+
*
197+
*/
198+
void
199+
uart_driver_rx_recover(void)
200+
{
201+
HAL_UART_DeInit(&huart2);
202+
HAL_UART_Init(&huart2);
203+
// Restart the reception
204+
HAL_UART_Receive_IT(&huart2, uart_buf.data_buffer, uart_buf.len);
205+
printf("Recovering uart reception\r\n");
206+
}
207+
142208
/**
143209
* @brief Function to register an rx callback function. This will be used by the com_protocol to register a callback
144210
* function and process the received message.

projects/bootloader/src/drivers/uart/uart_driver.h

+3-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
// --- defines ---------------------------------------------------------------------------------------------------------
1515
#define USART_TX_Pin GPIO_PIN_2
1616
#define USART_RX_Pin GPIO_PIN_3
17-
#define RX_CHUNK_SIZE_BYTES 256
17+
#define RX_CHUNK_SIZE_BYTES 256 // TODO: GPA: Right now, we need to send a buffer of 256 bytes, even if the effective payload is smaller.
1818

1919
// --- structs ---------------------------------------------------------------------------------------------------------
2020
struct uart_driver_data_s
@@ -28,5 +28,7 @@ typedef void (*process_rx_data)(struct uart_driver_data_s * const rx_data);
2828

2929
// --- function declarations -------------------------------------------------------------------------------------------
3030
void uart_driver_init(void);
31+
void uart_driver_feed_wdg(void);
32+
void uart_driver_rx_recover(void);
3133
void uart_driver_register_rx_callback(process_rx_data rx_cb);
3234
void uart_tx_data(uint8_t *buffer, uint16_t length);

scripts/firmware_update_tools/bootloader_tool.py

+4-1
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,10 @@ def perform_firmware_update(self):
157157
print("FWUG_START Message:", start_msg)
158158
response = send_message_via_serial(start_msg, self.com_port, self.baud_rate, 5, 10)
159159
if not self.parse_fwug_response(response, packet_number):
160-
print("Firmware update failed. Exiting...")
160+
# If firmware update start failed, send a cancel message and return
161+
cancel_msg = self.create_fwug_cancel_msg()
162+
send_message_via_serial(cancel_msg, self.com_port, self.baud_rate)
163+
print("Firmware update failed. Attempting to cancel... (and exiting)")
161164
return
162165
else:
163166
packet_number += 1

0 commit comments

Comments
 (0)