Browse Source

[uart]add config uart4, uart5 (use in ds18b20 module)

balbekova 5 years ago
parent
commit
e398cf980c
1 changed files with 264 additions and 236 deletions
  1. 264 236
      peripheral_modules/src/usart.c

+ 264 - 236
peripheral_modules/src/usart.c

@@ -10,7 +10,7 @@
  *******************************************************************************
  */
 
-#include "stm32f4xx.h"  
+#include "stm32f4xx.h"
 #include "usart.h"
 //#include "port_microrl.h"
 #include "main.h"
@@ -27,15 +27,14 @@
 #endif
 
 #ifdef __ICCARM__
-  #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)    
+#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
 
 
-PUTCHAR_PROTOTYPE   
-{   
-  USART_SendData(USER_USART, (u8) ch);   
-  while(USART_GetFlagStatus(USER_USART, USART_FLAG_TXE) == RESET) {}   
-  return ch;   
-}   
+PUTCHAR_PROTOTYPE {
+    USART_SendData(USER_USART, (u8) ch);
+    while (USART_GetFlagStatus(USER_USART, USART_FLAG_TXE) == RESET) {}
+    return ch;
+}
 #endif
 
 #define RS485_RBUF_SIZE 512
@@ -58,42 +57,45 @@ SemaphoreHandle_t xSem_user_rx_buf;
 
 USART_InitTypeDef USART_InitStructure;
 
-void uart_hw_init(USART_TypeDef *uart, uint32_t baud, uint16_t wordlen, uint16_t parity, uint16_t stop) {
-	uint16_t wordlen_tmp;
-
-	if (wordlen == 8)
-		wordlen_tmp = USART_WordLength_8b;
-	if (wordlen == 9)
-		wordlen_tmp = USART_WordLength_9b;
-
-	USART_InitStructure.USART_BaudRate = baud;
-	USART_InitStructure.USART_WordLength = wordlen_tmp;
-	USART_InitStructure.USART_StopBits = stop;
-	USART_InitStructure.USART_Parity = parity;
-	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
-	USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
-
-	USART_DeInit(uart);
-
-	if (uart == USART1) {
-		RCC->APB2ENR |= RCC_APB2Periph_USART1;
-		NVIC_SetPriority(USART1_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 0x05, 0));
-		NVIC_EnableIRQ(USART1_IRQn);
-		USART_Init(USART1, &USART_InitStructure);
-		USART_Cmd(USART1, ENABLE);
-		USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
-		USART_ITConfig(USART1, USART_IT_TXE, DISABLE);
-	}
-
-	if (uart == USART2) {
-		RCC->APB1ENR |= RCC_APB1Periph_USART2;
-		NVIC_SetPriority(USART2_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 0x05, 0));
-		NVIC_EnableIRQ(USART2_IRQn);
-		USART_Init(USART2, &USART_InitStructure);
-		USART_Cmd(USART2, ENABLE);
-		USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);
-		USART_ITConfig(USART2, USART_IT_TXE, DISABLE);
-	}
+void uart_hw_init(USART_TypeDef *uart, uint32_t baud, uint16_t wordlen, uint16_t parity, uint16_t stop)
+{
+    uint16_t wordlen_tmp;
+
+    if (wordlen == 8) {
+        wordlen_tmp = USART_WordLength_8b;
+    }
+    if (wordlen == 9) {
+        wordlen_tmp = USART_WordLength_9b;
+    }
+
+    USART_InitStructure.USART_BaudRate = baud;
+    USART_InitStructure.USART_WordLength = wordlen_tmp;
+    USART_InitStructure.USART_StopBits = stop;
+    USART_InitStructure.USART_Parity = parity;
+    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
+    USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
+
+    USART_DeInit(uart);
+
+    if (uart == USART1) {
+        RCC->APB2ENR |= RCC_APB2Periph_USART1;
+        NVIC_SetPriority(USART1_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 0x05, 0));
+        NVIC_EnableIRQ(USART1_IRQn);
+        USART_Init(USART1, &USART_InitStructure);
+        USART_Cmd(USART1, ENABLE);
+        USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
+        USART_ITConfig(USART1, USART_IT_TXE, DISABLE);
+    }
+
+    if (uart == USART2) {
+        RCC->APB1ENR |= RCC_APB1Periph_USART2;
+        NVIC_SetPriority(USART2_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 0x05, 0));
+        NVIC_EnableIRQ(USART2_IRQn);
+        USART_Init(USART2, &USART_InitStructure);
+        USART_Cmd(USART2, ENABLE);
+        USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);
+        USART_ITConfig(USART2, USART_IT_TXE, DISABLE);
+    }
 
     if (uart == USART3) {
         RCC->APB1ENR |= RCC_APB1Periph_USART3;
@@ -101,253 +103,279 @@ void uart_hw_init(USART_TypeDef *uart, uint32_t baud, uint16_t wordlen, uint16_t
         NVIC_EnableIRQ(USART3_IRQn);
         USART_Init(USART3, &USART_InitStructure);
         USART_Cmd(USART3, ENABLE);
-    USART_ITConfig(USART3, USART_IT_RXNE, ENABLE);
-    USART_ITConfig(USART3, USART_IT_TXE, DISABLE);
+        USART_ITConfig(USART3, USART_IT_RXNE, ENABLE);
+        USART_ITConfig(USART3, USART_IT_TXE, DISABLE);
+    }
+
+    if (uart == UART4) {
+        RCC->APB1ENR |= RCC_APB1Periph_UART4;
+        USART_Init(UART4, &USART_InitStructure);
+        USART_Cmd(UART4, ENABLE);
+        USART_HalfDuplexCmd(UART4, ENABLE);
+    }
+
+    if (uart == UART5) {
+        RCC->APB1ENR |= RCC_APB1Periph_UART5;
+        USART_Init(UART5, &USART_InitStructure);
+        USART_Cmd(UART5, ENABLE);
+        USART_HalfDuplexCmd(UART5, ENABLE);
     }
 }
 
 void init_ups_rbuf(void)
 {
-	rbuf32_init(&ups_tx_rbuf, ups_tx_fifo, UPS_RBUF_SIZE);
-	rbuf32_init(&ups_rx_rbuf, ups_rx_fifo, UPS_RBUF_SIZE);
+    rbuf32_init(&ups_tx_rbuf, ups_tx_fifo, UPS_RBUF_SIZE);
+    rbuf32_init(&ups_rx_rbuf, ups_rx_fifo, UPS_RBUF_SIZE);
 }
 
-void InitUSART(void) {
-	xSem_rx_buf = xSemaphoreCreateCounting( UPS_RBUF_SIZE, 0 );
-	rbuf32_init(&ups_tx_rbuf, ups_tx_fifo, UPS_RBUF_SIZE);
-	rbuf32_init(&ups_rx_rbuf, ups_rx_fifo, UPS_RBUF_SIZE);
-	uart_hw_init(UPS_USART, UPS_USART_BAUD, UPS_USART_WORD_LEN, UPS_USART_PARITY, UPS_USART_STOP_BIT);
+void InitUSART(void)
+{
+    xSem_rx_buf = xSemaphoreCreateCounting( UPS_RBUF_SIZE, 0 );
+    rbuf32_init(&ups_tx_rbuf, ups_tx_fifo, UPS_RBUF_SIZE);
+    rbuf32_init(&ups_rx_rbuf, ups_rx_fifo, UPS_RBUF_SIZE);
+    uart_hw_init(UPS_USART, UPS_USART_BAUD, UPS_USART_WORD_LEN, UPS_USART_PARITY, UPS_USART_STOP_BIT);
 
-	xSem_user_rx_buf = xSemaphoreCreateCounting( USER_RBUF_SIZE, 0 );
-	rbuf32_init(&user_tx_rbuf, user_tx_fifo, USER_RBUF_SIZE);
-	rbuf32_init(&user_rx_rbuf, user_rx_fifo, USER_RBUF_SIZE);
-	uart_hw_init(USER_USART, USER_USART_BAUD, USER_USART_WORD_LEN, USER_USART_PARITY, USER_USART_STOP_BIT);
+    xSem_user_rx_buf = xSemaphoreCreateCounting( USER_RBUF_SIZE, 0 );
+    rbuf32_init(&user_tx_rbuf, user_tx_fifo, USER_RBUF_SIZE);
+    rbuf32_init(&user_rx_rbuf, user_rx_fifo, USER_RBUF_SIZE);
+    uart_hw_init(USER_USART, USER_USART_BAUD, USER_USART_WORD_LEN, USER_USART_PARITY, USER_USART_STOP_BIT);
 
 #ifdef RS485_USART
     rs485TxQ = xQueueCreate(RS485_RBUF_SIZE, 1);
     rs485RxQ = xQueueCreate(RS485_RBUF_SIZE, 1);
-	rs485mutex = xSemaphoreCreateMutex();
-	/* Initial configuration. Port will be reconfigured later according to settings */
-	uart_hw_init(RS485_USART, RS485_USART_BAUD, RS485_USART_WORD_LEN, RS485_USART_PARITY, RS485_USART_STOP_BIT);
+    rs485mutex = xSemaphoreCreateMutex();
+    /* Initial configuration. Port will be reconfigured later according to settings */
+    uart_hw_init(RS485_USART, RS485_USART_BAUD, RS485_USART_WORD_LEN, RS485_USART_PARITY, RS485_USART_STOP_BIT);
 #endif
 
-#ifdef PRINTF_CUSTOM    
-	init_printf(NULL, putc_);
+#ifdef PRINTF_CUSTOM
+    init_printf(NULL, putc_);
 #endif
 }
 
-void ups_putchar(uint16_t byte) {
-	UPS_USART->CR1 &= ~USART_CR1_TXEIE;
-	if (!rbuf_isfull(&ups_tx_rbuf)) {
-		rbuf32_put(&ups_tx_rbuf, (uint32_t)(byte));
-	}
-	UPS_USART->CR1 |= USART_CR1_TXEIE;
+void ups_putchar(uint16_t byte)
+{
+    UPS_USART->CR1 &= ~USART_CR1_TXEIE;
+    if (!rbuf_isfull(&ups_tx_rbuf)) {
+        rbuf32_put(&ups_tx_rbuf, (uint32_t)(byte));
+    }
+    UPS_USART->CR1 |= USART_CR1_TXEIE;
 }
 
-int ups_send_block(void *data, uint8_t len) {
-	int i = 0;
-	uint32_t s_temp = 0;
-	UPS_USART->CR1 &= ~USART_CR1_TXEIE;
-	//DBG printf("STOP \r\n");
-	while (i < len) {
-		if (!rbuf_isfull(&ups_tx_rbuf)) {
-			s_temp = ((uint8_t *)data)[i++];
-			rbuf32_put(&ups_tx_rbuf, s_temp);
-		}
-		else
-			break;
-	}
-	UPS_USART->CR1 |= USART_CR1_TXEIE;
-	return i;
+int ups_send_block(void *data, uint8_t len)
+{
+    int i = 0;
+    uint32_t s_temp = 0;
+    UPS_USART->CR1 &= ~USART_CR1_TXEIE;
+    //DBG printf("STOP \r\n");
+    while (i < len) {
+        if (!rbuf_isfull(&ups_tx_rbuf)) {
+            s_temp = ((uint8_t *)data)[i++];
+            rbuf32_put(&ups_tx_rbuf, s_temp);
+        } else {
+            break;
+        }
+    }
+    UPS_USART->CR1 |= USART_CR1_TXEIE;
+    return i;
 }
 
-int ups_getchar(unsigned int timeout) {
-	int res;
-	res = xSemaphoreTake( xSem_rx_buf, (TickType_t)timeout );
-	if (res == pdFALSE) {
-		return -1;
-	}
-	rbuf32_get(&ups_rx_rbuf, (uint32_t*)&res);
-//	DBG printf("STOP \r\n");
-//	DBG printf("wr: %d 0x%x\r\n", rs485_rx_rbuf.read_index,res);
-	return res;
+int ups_getchar(unsigned int timeout)
+{
+    int res;
+    res = xSemaphoreTake( xSem_rx_buf, (TickType_t)timeout );
+    if (res == pdFALSE) {
+        return -1;
+    }
+    rbuf32_get(&ups_rx_rbuf, (uint32_t *)&res);
+    //  DBG printf("STOP \r\n");
+    //  DBG printf("wr: %d 0x%x\r\n", rs485_rx_rbuf.read_index,res);
+    return res;
 }
 
 
-void service_putchar(uint16_t byte) {
-	USER_USART->CR1 &= ~USART_CR1_TXEIE;
-	if (!rbuf_isfull(&user_tx_rbuf)) {
-		rbuf32_put(&user_tx_rbuf, (uint32_t)(byte));
-	}
-	USER_USART->CR1 |= USART_CR1_TXEIE;
+void service_putchar(uint16_t byte)
+{
+    USER_USART->CR1 &= ~USART_CR1_TXEIE;
+    if (!rbuf_isfull(&user_tx_rbuf)) {
+        rbuf32_put(&user_tx_rbuf, (uint32_t)(byte));
+    }
+    USER_USART->CR1 |= USART_CR1_TXEIE;
 }
 
-int service_send_block(void *data, uint8_t len) {
-	int i = 0;
-	uint32_t s_temp = 0;
-	USER_USART->CR1 &= ~USART_CR1_TXEIE;
-	//DBG printf("STOP \r\n");
-	while (i < len) {
-		if (!rbuf_isfull(&user_tx_rbuf)) {
-			s_temp = ((uint8_t *)data)[i++];
-			rbuf32_put(&user_tx_rbuf, s_temp);
-		}
-		else
-			break;
-	}
-	USER_USART->CR1 |= USART_CR1_TXEIE;
-	return i;
+int service_send_block(void *data, uint8_t len)
+{
+    int i = 0;
+    uint32_t s_temp = 0;
+    USER_USART->CR1 &= ~USART_CR1_TXEIE;
+    //DBG printf("STOP \r\n");
+    while (i < len) {
+        if (!rbuf_isfull(&user_tx_rbuf)) {
+            s_temp = ((uint8_t *)data)[i++];
+            rbuf32_put(&user_tx_rbuf, s_temp);
+        } else {
+            break;
+        }
+    }
+    USER_USART->CR1 |= USART_CR1_TXEIE;
+    return i;
 }
 
-int service_getchar(unsigned int timeout) {
-	int res;
-	res = xSemaphoreTake( xSem_user_rx_buf, (TickType_t)timeout );
-	if (res == pdFALSE) {
-		return -1;
-	}
-	rbuf32_get(&user_rx_rbuf, (uint32_t*)&res);
-//	DBG printf("STOP \r\n");
-//	DBG printf("wr: %d 0x%x\r\n", rs485_rx_rbuf.read_index,res);
-	return res;
+int service_getchar(unsigned int timeout)
+{
+    int res;
+    res = xSemaphoreTake( xSem_user_rx_buf, (TickType_t)timeout );
+    if (res == pdFALSE) {
+        return -1;
+    }
+    rbuf32_get(&user_rx_rbuf, (uint32_t *)&res);
+    //  DBG printf("STOP \r\n");
+    //  DBG printf("wr: %d 0x%x\r\n", rs485_rx_rbuf.read_index,res);
+    return res;
 }
 
-void putchar_(uint8_t c) {
-	while (!(USER_USART->SR & USART_FLAG_TXE));
-	USER_USART->DR = (uint16_t)c;
+void putchar_(uint8_t c)
+{
+    while (!(USER_USART->SR & USART_FLAG_TXE));
+    USER_USART->DR = (uint16_t)c;
 }
 
-void putc_(void* p, char c) {
-	(void)p;
-	putchar_(c);
+void putc_(void *p, char c)
+{
+    (void)p;
+    putchar_(c);
 }
 
 //inline void rs232_irq_handler(void)
 void service_rs232_irq_handler(void)
 {
-	uint32_t c = 0;
-
-	static BaseType_t xHigherPriorityTaskWoken = pdFALSE;
-	if ((USER_USART->SR & USART_SR_ORE)) {
-		c = (uint32_t)USER_USART->DR;
-		//DBG printf("overrunRS485\r\n");
-	}
-	if (USART_GetITStatus(USER_USART, USART_IT_TXE) != RESET) {
-		if(rbuf32_get(&user_tx_rbuf, &c)) {
-			USER_USART->DR = (uint16_t)c;
-			//DBG printf("wr: %d 0x%x\r\n", rs485_tx_rbuf.read_index,c);
-		}
-		else {
-			USER_USART->CR1 &= ~USART_CR1_TXEIE;
-			USER_USART->CR1 |= USART_CR1_RXNEIE;
-		}
-			USART_ClearITPendingBit(USER_USART, USART_IT_TXE);
-	}
-	if(USART_GetITStatus(USER_USART, USART_IT_RXNE) != RESET)
-	{
-		c = (uint32_t)USER_USART->DR;
-		//DBG printf("read: %d 0x%x\r\n", rs485_rx_rbuf.write_index,c);
-		if (!rbuf_isfull(&user_rx_rbuf))
-			rbuf32_put(&user_rx_rbuf, c);
-		USART_ClearITPendingBit(USER_USART, USART_IT_RXNE);
-		xSemaphoreGiveFromISR(xSem_user_rx_buf, &xHigherPriorityTaskWoken);
-		portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
-	}
+    uint32_t c = 0;
+
+    static BaseType_t xHigherPriorityTaskWoken = pdFALSE;
+    if ((USER_USART->SR & USART_SR_ORE)) {
+        c = (uint32_t)USER_USART->DR;
+        //DBG printf("overrunRS485\r\n");
+    }
+    if (USART_GetITStatus(USER_USART, USART_IT_TXE) != RESET) {
+        if (rbuf32_get(&user_tx_rbuf, &c)) {
+            USER_USART->DR = (uint16_t)c;
+            //DBG printf("wr: %d 0x%x\r\n", rs485_tx_rbuf.read_index,c);
+        } else {
+            USER_USART->CR1 &= ~USART_CR1_TXEIE;
+            USER_USART->CR1 |= USART_CR1_RXNEIE;
+        }
+        USART_ClearITPendingBit(USER_USART, USART_IT_TXE);
+    }
+    if (USART_GetITStatus(USER_USART, USART_IT_RXNE) != RESET) {
+        c = (uint32_t)USER_USART->DR;
+        //DBG printf("read: %d 0x%x\r\n", rs485_rx_rbuf.write_index,c);
+        if (!rbuf_isfull(&user_rx_rbuf)) {
+            rbuf32_put(&user_rx_rbuf, c);
+        }
+        USART_ClearITPendingBit(USER_USART, USART_IT_RXNE);
+        xSemaphoreGiveFromISR(xSem_user_rx_buf, &xHigherPriorityTaskWoken);
+        portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
+    }
 }
 
 //inline void rs232_irq_handler(void)
 void rs232_irq_handler(void)
 {
-	uint32_t c = 0;
-
-	static BaseType_t xHigherPriorityTaskWoken = pdFALSE;
-	if ((UPS_USART->SR & USART_SR_ORE)) {
-		c = (uint32_t)UPS_USART->DR;
-		//DBG printf("overrunRS485\r\n");
-	}
-	if (USART_GetITStatus(UPS_USART, USART_IT_TXE) != RESET) {
-		if(rbuf32_get(&ups_tx_rbuf, &c)) {
-			UPS_USART->DR = (uint16_t)c;
-			//DBG printf("wr: %d 0x%x\r\n", rs485_tx_rbuf.read_index,c);
-		}
-		else {
-			UPS_USART->CR1 &= ~USART_CR1_TXEIE;
-			UPS_USART->CR1 |= USART_CR1_RXNEIE;
-		}
-			USART_ClearITPendingBit(UPS_USART, USART_IT_TXE);
-	}
-	if(USART_GetITStatus(UPS_USART, USART_IT_RXNE) != RESET)
-	{
-		c = (uint32_t)UPS_USART->DR;
-		//DBG printf("read: %d 0x%x\r\n", rs485_rx_rbuf.write_index,c);
-		if (!rbuf_isfull(&ups_rx_rbuf))
-			rbuf32_put(&ups_rx_rbuf, c);
-		USART_ClearITPendingBit(UPS_USART, USART_IT_RXNE);
-		xSemaphoreGiveFromISR(xSem_rx_buf, &xHigherPriorityTaskWoken);
-		portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
-	}
+    uint32_t c = 0;
+
+    static BaseType_t xHigherPriorityTaskWoken = pdFALSE;
+    if ((UPS_USART->SR & USART_SR_ORE)) {
+        c = (uint32_t)UPS_USART->DR;
+        //DBG printf("overrunRS485\r\n");
+    }
+    if (USART_GetITStatus(UPS_USART, USART_IT_TXE) != RESET) {
+        if (rbuf32_get(&ups_tx_rbuf, &c)) {
+            UPS_USART->DR = (uint16_t)c;
+            //DBG printf("wr: %d 0x%x\r\n", rs485_tx_rbuf.read_index,c);
+        } else {
+            UPS_USART->CR1 &= ~USART_CR1_TXEIE;
+            UPS_USART->CR1 |= USART_CR1_RXNEIE;
+        }
+        USART_ClearITPendingBit(UPS_USART, USART_IT_TXE);
+    }
+    if (USART_GetITStatus(UPS_USART, USART_IT_RXNE) != RESET) {
+        c = (uint32_t)UPS_USART->DR;
+        //DBG printf("read: %d 0x%x\r\n", rs485_rx_rbuf.write_index,c);
+        if (!rbuf_isfull(&ups_rx_rbuf)) {
+            rbuf32_put(&ups_rx_rbuf, c);
+        }
+        USART_ClearITPendingBit(UPS_USART, USART_IT_RXNE);
+        xSemaphoreGiveFromISR(xSem_rx_buf, &xHigherPriorityTaskWoken);
+        portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
+    }
 }
 
 #ifdef RS485_USART
-inline void rs485_enable_tx(void) {
-	RS485_USART->CR1 |= USART_CR1_TXEIE;
+inline void rs485_enable_tx(void)
+{
+    RS485_USART->CR1 |= USART_CR1_TXEIE;
 }
 
-inline void rs485_irq_handler(void) {
-	uint16_t c;
-	static BaseType_t xHigherPriorityTaskWoken = pdFALSE;
-	if (RS485_USART->SR & USART_SR_ORE) {
-		c = RS485_USART->DR;
-		DBG printf("[rs485] overrun\r\n");
-	}
-	if (RS485_USART->SR & USART_SR_PE) {
-		c = RS485_USART->DR;
-		DBG printf("[rs485] parity fail: 0x%X\r\n", c);
-	}
-	if (USART_GetITStatus(RS485_USART, USART_IT_TXE) != RESET) {
-		if (xQueueReceiveFromISR(rs485TxQ, &c, &xHigherPriorityTaskWoken) == pdTRUE) {
-			RS485_USART->DR = c;
-			// DBG printf("tx: 0x%x\r\n", c);
-			portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
-		} else {
-			RS485_USART->CR1 &= ~USART_CR1_TXEIE;
-			RS485_USART->CR1 |= USART_CR1_RXNEIE;
-		}
-		USART_ClearITPendingBit(RS485_USART, USART_IT_TXE);
-	}
-	if (USART_GetITStatus(RS485_USART, USART_IT_RXNE) != RESET) {
-		c = RS485_USART->DR;
-		/* Mask parity bits */
-		if (RS485_USART->CR1 & USART_CR1_PCE) {
-			if (RS485_USART->CR1 & USART_CR1_M) {
-				/* 8-bit data */
-				c &= 0xFF;
-			} else {
-				/* 7-bit data */
-				c &= 0x7F;
-			}
-		}
-		if (xQueueSendFromISR(rs485RxQ, &c, &xHigherPriorityTaskWoken) == pdTRUE) {
-			// DBG printf("rx: 0x%x\r\n", c);
-		} else {
-			DBG printf("[rs485] rx overflow\r\n");
-		}
-		USART_ClearITPendingBit(RS485_USART, USART_IT_RXNE);
-		portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
-	}
+inline void rs485_irq_handler(void)
+{
+    uint16_t c;
+    static BaseType_t xHigherPriorityTaskWoken = pdFALSE;
+    if (RS485_USART->SR & USART_SR_ORE) {
+        c = RS485_USART->DR;
+        DBG printf("[rs485] overrun\r\n");
+    }
+    if (RS485_USART->SR & USART_SR_PE) {
+        c = RS485_USART->DR;
+        DBG printf("[rs485] parity fail: 0x%X\r\n", c);
+    }
+    if (USART_GetITStatus(RS485_USART, USART_IT_TXE) != RESET) {
+        if (xQueueReceiveFromISR(rs485TxQ, &c, &xHigherPriorityTaskWoken) == pdTRUE) {
+            RS485_USART->DR = c;
+            // DBG printf("tx: 0x%x\r\n", c);
+            portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
+        } else {
+            RS485_USART->CR1 &= ~USART_CR1_TXEIE;
+            RS485_USART->CR1 |= USART_CR1_RXNEIE;
+        }
+        USART_ClearITPendingBit(RS485_USART, USART_IT_TXE);
+    }
+    if (USART_GetITStatus(RS485_USART, USART_IT_RXNE) != RESET) {
+        c = RS485_USART->DR;
+        /* Mask parity bits */
+        if (RS485_USART->CR1 & USART_CR1_PCE) {
+            if (RS485_USART->CR1 & USART_CR1_M) {
+                /* 8-bit data */
+                c &= 0xFF;
+            } else {
+                /* 7-bit data */
+                c &= 0x7F;
+            }
+        }
+        if (xQueueSendFromISR(rs485RxQ, &c, &xHigherPriorityTaskWoken) == pdTRUE) {
+            // DBG printf("rx: 0x%x\r\n", c);
+        } else {
+            DBG printf("[rs485] rx overflow\r\n");
+        }
+        USART_ClearITPendingBit(RS485_USART, USART_IT_RXNE);
+        portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
+    }
 }
 #endif /* RS485_USART */
 
-void USART1_IRQHandler(void) {
-	service_rs232_irq_handler();
+void USART1_IRQHandler(void)
+{
+    service_rs232_irq_handler();
 }
 
-void USART2_IRQHandler(void) {
-	rs232_irq_handler();
+void USART2_IRQHandler(void)
+{
+    rs232_irq_handler();
 }
 
-void USART3_IRQHandler(void) {
+void USART3_IRQHandler(void)
+{
 #ifdef RS485_USART
-	rs485_irq_handler();
+    rs485_irq_handler();
 #endif /* RS485_USART */
 }