From 866bc49412e23012b583a12158e3febfffcb0455 Mon Sep 17 00:00:00 2001 From: xychen Date: Thu, 12 May 2022 16:10:40 +0800 Subject: [PATCH] [nanokit] Pulls nRESET and GPIO_B_01 with DTR and RTS of CDC ACM --- source/hic_hal/stm32/stm32f103xb/uart.c | 197 +++++++++++++++++++++++- 1 file changed, 193 insertions(+), 4 deletions(-) diff --git a/source/hic_hal/stm32/stm32f103xb/uart.c b/source/hic_hal/stm32/stm32f103xb/uart.c index d982be84f..7b155a005 100644 --- a/source/hic_hal/stm32/stm32f103xb/uart.c +++ b/source/hic_hal/stm32/stm32f103xb/uart.c @@ -27,6 +27,7 @@ #include "util.h" #include "circ_buf.h" #include "IO_Config.h" +#include "cmsis_os2.h" // For usart #define CDC_UART USART2 @@ -38,6 +39,16 @@ #define UART_PINS_PORT_ENABLE() __HAL_RCC_GPIOA_CLK_ENABLE() #define UART_PINS_PORT_DISABLE() __HAL_RCC_GPIOA_CLK_DISABLE() +// For CSK update +#define CDC_UART2 USART3 +#define CDC_UART2_ENABLE() __HAL_RCC_USART3_CLK_ENABLE() +#define CDC_UART2_DISABLE() __HAL_RCC_USART3_CLK_DISABLE() +#define CDC_UART2_IRQn USART3_IRQn +#define CDC_UART2_IRQn_Handler USART3_IRQHandler + +#define UART2_PINS_PORT_ENABLE() __HAL_RCC_GPIOB_CLK_ENABLE() +#define UART2_PINS_PORT_DISABLE() __HAL_RCC_GPIOB_CLK_DISABLE() + #define UART_TX_PORT GPIOA #define UART_TX_PIN GPIO_PIN_2 @@ -47,14 +58,36 @@ #define UART_CTS_PORT GPIOA #define UART_CTS_PIN GPIO_PIN_0 -#define UART_RTS_PORT GPIOA -#define UART_RTS_PIN GPIO_PIN_1 +#define UART_RTS_PORT GPIOB +#define UART_RTS_PIN GPIO_PIN_3 + +#define UART_DTR_PORT GPIOB +#define UART_DTR_PIN GPIO_PIN_4 + +// For CSK update +#define CSK_BOOT_PORT GPIOA +#define CSK_BOOT_PIN GPIO_PIN_6 + +#define CSK_RESET_PORT GPIOB +#define CSK_RESET_PIN GPIO_PIN_0 + +#define UART2_TX_PORT GPIOB +#define UART2_TX_PIN GPIO_PIN_10 + +#define UART2_RX_PORT GPIOB +#define UART2_RX_PIN GPIO_PIN_11 #define RX_OVRF_MSG "\n" #define RX_OVRF_MSG_SIZE (sizeof(RX_OVRF_MSG) - 1) #define BUFFER_SIZE (512) +#define CTRL_DTR_BIT (1 << 0) +#define CTRL_RTS_BIT (1 << 1) + +uint8_t update_mode = 0; +uint8_t last_dtr = 0; + circ_buf_t write_buffer; uint8_t write_buffer_data[BUFFER_SIZE]; circ_buf_t read_buffer; @@ -78,15 +111,88 @@ static void clear_buffers(void) circ_buf_init(&read_buffer, read_buffer_data, sizeof(read_buffer_data)); } +void uart2_set_configuration(uint32_t baud_rate) +{ + UART_HandleTypeDef uart_handle; + + memset(&uart_handle, 0, sizeof(uart_handle)); + uart_handle.Instance = CDC_UART2; + uart_handle.Init.Parity = HAL_UART_PARITY_NONE; + uart_handle.Init.StopBits = UART_STOPBITS_1; + uart_handle.Init.WordLength = UART_WORDLENGTH_8B; + uart_handle.Init.HwFlowCtl = UART_HWCONTROL_NONE; + uart_handle.Init.BaudRate = baud_rate; + uart_handle.Init.Mode = UART_MODE_TX_RX; + + // Disable uart and tx/rx interrupt + CDC_UART2->CR1 &= ~(USART_IT_TXE | USART_IT_RXNE); + + HAL_UART_DeInit(&uart_handle); + HAL_UART_Init(&uart_handle); + + CDC_UART2->CR1 |= USART_IT_RXNE; +} + +void uart2_enable(void) +{ + CDC_UART->CR1 &= ~(USART_IT_TXE | USART_IT_RXNE); + NVIC_DisableIRQ(CDC_UART_IRQn); + + CDC_UART2->CR1 &= ~(USART_IT_TXE | USART_IT_RXNE); + + GPIO_InitTypeDef GPIO_InitStructure; + GPIO_InitStructure.Pin = UART2_TX_PIN; + GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH; + GPIO_InitStructure.Mode = GPIO_MODE_AF_PP; + GPIO_InitStructure.Pull = GPIO_NOPULL; + HAL_GPIO_Init(UART2_TX_PORT, &GPIO_InitStructure); + GPIO_InitStructure.Pin = UART2_RX_PIN; + GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH; + GPIO_InitStructure.Mode = GPIO_MODE_INPUT; + GPIO_InitStructure.Pull = GPIO_PULLUP; + HAL_GPIO_Init(UART2_RX_PORT, &GPIO_InitStructure); + + NVIC_EnableIRQ(CDC_UART2_IRQn); + + uart2_set_configuration(115200); +} + +void uart2_disable(void) +{ + CDC_UART2->CR1 &= ~(USART_IT_TXE | USART_IT_RXNE); + NVIC_DisableIRQ(CDC_UART2_IRQn); + + UART_HandleTypeDef uart_handle; + memset(&uart_handle, 0, sizeof(uart_handle)); + uart_handle.Instance = CDC_UART2; + HAL_UART_DeInit(&uart_handle); + + GPIO_InitTypeDef GPIO_InitStructure; + GPIO_InitStructure.Pin = UART2_TX_PIN; + GPIO_InitStructure.Mode = GPIO_MODE_INPUT; + GPIO_InitStructure.Pull = GPIO_NOPULL; + HAL_GPIO_Init(UART2_TX_PORT, &GPIO_InitStructure); + GPIO_InitStructure.Pin = UART2_RX_PIN; + GPIO_InitStructure.Mode = GPIO_MODE_INPUT; + GPIO_InitStructure.Pull = GPIO_NOPULL; + HAL_GPIO_Init(UART2_RX_PORT, &GPIO_InitStructure); + + CDC_UART->CR1 &= ~USART_IT_TXE; + NVIC_EnableIRQ(CDC_UART_IRQn); +} + int32_t uart_initialize(void) { GPIO_InitTypeDef GPIO_InitStructure; CDC_UART->CR1 &= ~(USART_IT_TXE | USART_IT_RXNE); + CDC_UART2->CR1 &= ~(USART_IT_TXE | USART_IT_RXNE); clear_buffers(); CDC_UART_ENABLE(); UART_PINS_PORT_ENABLE(); + CDC_UART2_ENABLE(); + UART2_PINS_PORT_ENABLE(); //TX pin GPIO_InitStructure.Pin = UART_TX_PIN; @@ -106,11 +212,30 @@ int32_t uart_initialize(void) GPIO_InitStructure.Pull = GPIO_PULLUP; HAL_GPIO_Init(UART_CTS_PORT, &GPIO_InitStructure); //RTS pin, output low - HAL_GPIO_WritePin(UART_RTS_PORT, UART_RTS_PIN, GPIO_PIN_RESET); + HAL_GPIO_WritePin(UART_RTS_PORT, UART_RTS_PIN, GPIO_PIN_SET); GPIO_InitStructure.Pin = UART_RTS_PIN; GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH; GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP; HAL_GPIO_Init(UART_RTS_PORT, &GPIO_InitStructure); + //DTR pin, output low + HAL_GPIO_WritePin(UART_DTR_PORT, UART_DTR_PIN, GPIO_PIN_SET); + GPIO_InitStructure.Pin = UART_DTR_PIN; + GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH; + GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP; + HAL_GPIO_Init(UART_DTR_PORT, &GPIO_InitStructure); + + // CSK BOOT pin, open-drain low + HAL_GPIO_WritePin(CSK_BOOT_PORT, CSK_BOOT_PIN, GPIO_PIN_SET); + GPIO_InitStructure.Pin = CSK_BOOT_PIN; + GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_OD; + GPIO_InitStructure.Pull = GPIO_NOPULL; + HAL_GPIO_Init(CSK_BOOT_PORT, &GPIO_InitStructure); + // CSK RESET pin, open-drain low + HAL_GPIO_WritePin(CSK_RESET_PORT, CSK_RESET_PIN, GPIO_PIN_SET); + GPIO_InitStructure.Pin = CSK_RESET_PIN; + GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_OD; + GPIO_InitStructure.Pull = GPIO_NOPULL; + HAL_GPIO_Init(CSK_RESET_PORT, &GPIO_InitStructure); NVIC_EnableIRQ(CDC_UART_IRQn); @@ -120,6 +245,7 @@ int32_t uart_initialize(void) int32_t uart_uninitialize(void) { CDC_UART->CR1 &= ~(USART_IT_TXE | USART_IT_RXNE); + CDC_UART2->CR1 &= ~(USART_IT_TXE | USART_IT_RXNE); clear_buffers(); return 1; } @@ -127,9 +253,12 @@ int32_t uart_uninitialize(void) int32_t uart_reset(void) { const uint32_t cr1 = CDC_UART->CR1; + const uint32_t cr21 = CDC_UART2->CR1; CDC_UART->CR1 = cr1 & ~(USART_IT_TXE | USART_IT_RXNE); + CDC_UART2->CR1 = cr21 & ~(USART_IT_TXE | USART_IT_RXNE); clear_buffers(); CDC_UART->CR1 = cr1 & ~USART_IT_TXE; + CDC_UART2->CR1 = cr21 & ~USART_IT_TXE; return 1; } @@ -138,6 +267,11 @@ int32_t uart_set_configuration(UART_Configuration *config) UART_HandleTypeDef uart_handle; HAL_StatusTypeDef status; + if (update_mode) { + uart2_set_configuration(config->Baudrate); + return 1; + } + memset(&uart_handle, 0, sizeof(uart_handle)); uart_handle.Instance = CDC_UART; @@ -216,6 +350,32 @@ int32_t uart_get_configuration(UART_Configuration *config) void uart_set_control_line_state(uint16_t ctrl_bmp) { + uint8_t rts = ctrl_bmp & CTRL_RTS_BIT; + uint8_t dtr = ctrl_bmp & CTRL_DTR_BIT; + HAL_GPIO_WritePin(UART_RTS_PORT, UART_RTS_PIN, rts ? GPIO_PIN_RESET : GPIO_PIN_SET); + HAL_GPIO_WritePin(UART_DTR_PORT, UART_DTR_PIN, dtr ? GPIO_PIN_RESET : GPIO_PIN_SET); + + // Boot pin and USART3 (for update_mode) are controlled by RTS + // Some host may pull both RTS and DTR down by default. Thus only trust the + // level when RTS and DTR are different. + uint8_t boot = rts && !dtr; + HAL_GPIO_WritePin(CSK_BOOT_PORT, CSK_BOOT_PIN, boot ? GPIO_PIN_RESET : GPIO_PIN_SET); + if (update_mode && !boot) { + uart2_disable(); + } else if (!update_mode && boot) { + uart2_enable(); + } + update_mode = boot; + + // Reset pin is controlled by DTR + // Some host may pull DTR down by default, so we need to perform the reset + // only when a rising edge is detected. + if (last_dtr && !dtr) { + HAL_GPIO_WritePin(CSK_RESET_PORT, CSK_RESET_PIN, GPIO_PIN_RESET); + osDelay(2); + HAL_GPIO_WritePin(CSK_RESET_PORT, CSK_RESET_PIN, GPIO_PIN_SET); + } + last_dtr = dtr; } int32_t uart_write_free(void) @@ -226,7 +386,11 @@ int32_t uart_write_free(void) int32_t uart_write_data(uint8_t *data, uint16_t size) { uint32_t cnt = circ_buf_write(&write_buffer, data, size); - CDC_UART->CR1 |= USART_IT_TXE; + if (update_mode) { + CDC_UART2->CR1 |= USART_IT_TXE; + } else { + CDC_UART->CR1 |= USART_IT_TXE; + } return cnt; } @@ -260,3 +424,28 @@ void CDC_UART_IRQn_Handler(void) } } } + +void CDC_UART2_IRQn_Handler(void) +{ + const uint32_t sr = CDC_UART2->SR; + + if (sr & USART_SR_RXNE) { + uint8_t dat = CDC_UART2->DR; + uint32_t free = circ_buf_count_free(&read_buffer); + if (free > RX_OVRF_MSG_SIZE) { + circ_buf_push(&read_buffer, dat); + } else if (RX_OVRF_MSG_SIZE == free) { + circ_buf_write(&read_buffer, (uint8_t*)RX_OVRF_MSG, RX_OVRF_MSG_SIZE); + } else { + // Drop character + } + } + + if (sr & USART_SR_TXE) { + if (circ_buf_count_used(&write_buffer) > 0) { + CDC_UART2->DR = circ_buf_pop(&write_buffer); + } else { + CDC_UART2->CR1 &= ~USART_IT_TXE; + } + } +}