/********************************* (C) РОТЕК *********************************** * @module usart * @file usart.c * @version 1.0.0 * @date XX.XX.XXXX * $brief Template ******************************************************************************* * @history Version Author Comment * XX.XX.XXXX 1.0.0 Telenkov D.A. First release. ******************************************************************************* */ #include "stm32f4xx.h" #include "usart.h" //#include "port_microrl.h" #include "main.h" #include "ring_buf.h" //#include #include "FreeRTOS.h" #include "semphr.h" #ifdef PRINTF_STDLIB #include #endif #ifdef PRINTF_CUSTOM #include "tinystdio.h" #endif #ifdef __ICCARM__ #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; } #endif #ifdef BT6702_SERVICE #define UPS_RBUF_SIZE 1024 #else #define UPS_RBUF_SIZE 100 #endif rbuf_t ups_rx_rbuf, ups_tx_rbuf; uint32_t ups_rx_fifo[UPS_RBUF_SIZE]; uint32_t ups_tx_fifo[UPS_RBUF_SIZE]; SemaphoreHandle_t xSem_rx_buf; #define USER_RBUF_SIZE 256 rbuf_t user_rx_rbuf, user_tx_rbuf; uint32_t user_rx_fifo[USER_RBUF_SIZE]; uint32_t user_tx_fifo[USER_RBUF_SIZE]; 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); } if (uart == USART3) { RCC->APB1ENR |= RCC_APB1Periph_USART3; NVIC_SetPriority(USART3_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 0x05, 0)); 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); } } 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); #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; } 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; } 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_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 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); } } //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); } } void USART1_IRQHandler(void) { service_rs232_irq_handler(); } void USART2_IRQHandler(void) { rs232_irq_handler(); } void USART3_IRQHandler(void) { } /********************************* (C) РОТЕК **********************************/