#include "usart.h" #include "common.h" #include "parameters.h" #include "portgw.h" #define DEBUG_RBUF_SIZE 256 // gcc-4.7 cannot handle const variable sizes #ifdef DEBUG static uint8_t debug_rx_fifo[DEBUG_RBUF_SIZE]; static uint8_t debug_tx_fifo[DEBUG_RBUF_SIZE]; #endif #define FIN { 0 }, { 0 }, 0, 0 #define UARTS_LEN 5 static uart_t uarts[UARTS_LEN] = { { // RS485_1 true, { BRD_9600, NO_PAR, DATABITS_8, STOP_1 }, UART7, NULL, NULL, 0, GetUsartSettingsInt, { NULL, NULL, }, SetUsartTransportQueue, FIN }, { // GSM false, { BRD_9600, NO_PAR, DATABITS_8, STOP_1 }, USART2, NULL, NULL, 0, GetUsartSettingsInt, { NULL, NULL, }, SetUsartTransportQueue, FIN }, { // RS485_2 true, { BRD_9600, NO_PAR, DATABITS_8, STOP_1 }, USART3, NULL, NULL, 0, GetUsartSettingsInt, { NULL, NULL, }, SetUsartTransportQueue, FIN }, { // RS232_1 true, { BRD_9600, NO_PAR, DATABITS_8, STOP_1 }, UART4, NULL, NULL, 0, GetUsartSettingsInt, { NULL, NULL, }, SetUsartTransportQueue, FIN }, { // RS232_2 true, { BRD_9600, NO_PAR, DATABITS_8, STOP_1 }, UART5, NULL, NULL, 0, GetUsartSettingsInt, { NULL, NULL, }, SetUsartTransportQueue, FIN } }; #undef FIN void uart_hw_init(usart_type *uart, uart_settings_t *sett); void uart_proddefault_init(uint8_t indx_uarts, uint8_t portgw_queue) { uarts[indx_uarts].setting.baud = BRD_9600; uarts[indx_uarts].setting.databits = DATABITS_8; uarts[indx_uarts].setting.parity = NO_PAR; uarts[indx_uarts].setting.stopbits = STOP_1; uart_hw_init( uarts[indx_uarts].addr, &uarts[indx_uarts].setting); uarts[indx_uarts].trans_queue.rxQ = &PortGwRxQ[portgw_queue];; uarts[indx_uarts].trans_queue.txQ = &PortGwTxQ[portgw_queue];; } void uart_hw_init(usart_type *uart, uart_settings_t *sett) { gpio_init_type gpio_initstructure; uint32_t baud; usart_data_bit_num_type wordlen; usart_parity_selection_type parity; usart_stop_bit_num_type stop; switch(sett->baud) { case BRD_1200: baud = 1200; break; case BRD_2400: baud = 2400; break; case BRD_4800: baud = 4800; break; case BRD_9600: baud = 9600; break; case BRD_19200: baud = 19200; break; case BRD_38400: baud = 38400; break; case BRD_57600: baud = 57600; break; case BRD_115200: baud = 115200; break; case BRD_230400: baud = 230400; break; case BRD_460800: baud = 460800; break; default: break; } switch(sett->databits) { case DATABITS_7: wordlen = USART_DATA_8BITS; break; case DATABITS_8: if ((sett->parity == EVEN_PAR) || (sett->parity == ODD_PAR)) { wordlen = USART_DATA_9BITS; } else { wordlen = USART_DATA_8BITS; } break; default: break; } switch(sett->parity) { case NO_PAR: parity = USART_PARITY_NONE; break; case ODD_PAR: parity = USART_PARITY_ODD; break; case EVEN_PAR: parity = USART_PARITY_EVEN; break; default: break; } switch(sett->stopbits) { case STOP_1: stop = USART_STOP_1_BIT; break; case STOP_2: stop = USART_STOP_2_BIT; break; default: break; } // RS485_1 if (uart == UART7) { crm_periph_clock_enable(CRM_GPIOE_PERIPH_CLOCK, TRUE); crm_periph_clock_enable(CRM_UART7_PERIPH_CLOCK, TRUE); gpio_default_para_init(&gpio_initstructure); gpio_initstructure.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER; gpio_initstructure.gpio_out_type = GPIO_OUTPUT_PUSH_PULL; gpio_initstructure.gpio_mode = GPIO_MODE_MUX; gpio_initstructure.gpio_pins = GPIO_PINS_8; gpio_initstructure.gpio_pull = GPIO_PULL_NONE; gpio_init(GPIOE, &gpio_initstructure); gpio_initstructure.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER; gpio_initstructure.gpio_out_type = GPIO_OUTPUT_PUSH_PULL; gpio_initstructure.gpio_mode = GPIO_MODE_INPUT; gpio_initstructure.gpio_pins = GPIO_PINS_7; gpio_initstructure.gpio_pull = GPIO_PULL_UP; gpio_init(GPIOE, &gpio_initstructure); nvic_priority_group_config(NVIC_PRIORITY_GROUP_4); nvic_irq_enable(UART7_IRQn, 6, 0); } // RS485_2 if (uart == USART3) { crm_periph_clock_enable(CRM_GPIOD_PERIPH_CLOCK, TRUE); crm_periph_clock_enable(CRM_USART3_PERIPH_CLOCK, TRUE); crm_periph_clock_enable(CRM_IOMUX_PERIPH_CLOCK, TRUE); gpio_pin_remap_config(USART3_GMUX_0011, TRUE); gpio_default_para_init(&gpio_initstructure); gpio_initstructure.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER; gpio_initstructure.gpio_out_type = GPIO_OUTPUT_PUSH_PULL; gpio_initstructure.gpio_mode = GPIO_MODE_MUX; gpio_initstructure.gpio_pins = GPIO_PINS_8; gpio_initstructure.gpio_pull = GPIO_PULL_NONE; gpio_init(GPIOD, &gpio_initstructure); gpio_initstructure.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER; gpio_initstructure.gpio_out_type = GPIO_OUTPUT_PUSH_PULL; gpio_initstructure.gpio_mode = GPIO_MODE_INPUT; gpio_initstructure.gpio_pins = GPIO_PINS_9; gpio_initstructure.gpio_pull = GPIO_PULL_UP; gpio_init(GPIOD, &gpio_initstructure); nvic_priority_group_config(NVIC_PRIORITY_GROUP_4); nvic_irq_enable(USART3_IRQn, 6, 0); } // RS232_1 if (uart == UART4) { crm_periph_clock_enable(CRM_GPIOC_PERIPH_CLOCK, TRUE); crm_periph_clock_enable(CRM_UART4_PERIPH_CLOCK, TRUE); gpio_default_para_init(&gpio_initstructure); gpio_initstructure.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER; gpio_initstructure.gpio_out_type = GPIO_OUTPUT_PUSH_PULL; gpio_initstructure.gpio_mode = GPIO_MODE_MUX; gpio_initstructure.gpio_pins = GPIO_PINS_10; gpio_initstructure.gpio_pull = GPIO_PULL_NONE; gpio_init(GPIOC, &gpio_initstructure); gpio_initstructure.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER; gpio_initstructure.gpio_out_type = GPIO_OUTPUT_PUSH_PULL; gpio_initstructure.gpio_mode = GPIO_MODE_INPUT; gpio_initstructure.gpio_pins = GPIO_PINS_11; gpio_initstructure.gpio_pull = GPIO_PULL_UP; gpio_init(GPIOC, &gpio_initstructure); nvic_priority_group_config(NVIC_PRIORITY_GROUP_4); nvic_irq_enable(UART4_IRQn, 6, 0); } // RS232_2 if (uart == UART5) { crm_periph_clock_enable(CRM_GPIOC_PERIPH_CLOCK, TRUE); crm_periph_clock_enable(CRM_GPIOD_PERIPH_CLOCK, TRUE); crm_periph_clock_enable(CRM_UART5_PERIPH_CLOCK, TRUE); gpio_default_para_init(&gpio_initstructure); // configure the uart tx pin gpio_initstructure.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER; gpio_initstructure.gpio_out_type = GPIO_OUTPUT_PUSH_PULL; gpio_initstructure.gpio_mode = GPIO_MODE_MUX; gpio_initstructure.gpio_pins = GPIO_PINS_12; gpio_initstructure.gpio_pull = GPIO_PULL_NONE; gpio_init(GPIOC, &gpio_initstructure); gpio_initstructure.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER; gpio_initstructure.gpio_out_type = GPIO_OUTPUT_PUSH_PULL; gpio_initstructure.gpio_mode = GPIO_MODE_INPUT; gpio_initstructure.gpio_pins = GPIO_PINS_2; gpio_initstructure.gpio_pull = GPIO_PULL_UP; gpio_init(GPIOD, &gpio_initstructure); nvic_priority_group_config(NVIC_PRIORITY_GROUP_4); nvic_irq_enable(UART5_IRQn, 6, 0); } usart_init(uart, baud, wordlen, stop); usart_parity_selection_config(uart, parity); usart_transmitter_enable(uart, TRUE); usart_receiver_enable(uart, TRUE); usart_enable(uart, TRUE); usart_interrupt_enable(uart, USART_RDBF_INT, TRUE); usart_interrupt_enable(uart, USART_TDC_INT, FALSE); usart_enable(uart, TRUE); } void usart_init_struct(void) { for (int i = 0; i < UARTS_LEN; ++i) { if (!uarts[i].enabled) continue; if(uarts[i].tx_fifo != NULL && uarts[i].rx_fifo != NULL){ uarts[i].rx_buf_sem = xSemaphoreCreateCounting(uarts[i].buf_size, 0); uarts[i].tx_buf_sem = xSemaphoreCreateCounting(uarts[i].buf_size, (uarts[i].buf_size-1)); rbuf8_init(&uarts[i].tx_buf, uarts[i].tx_fifo, uarts[i].buf_size); rbuf8_init(&uarts[i].rx_buf, uarts[i].rx_fifo, uarts[i].buf_size); } if(uarts[i].set_uart_queue != NULL){ uarts[i].set_uart_queue(&uarts[i].trans_queue, i); } uart_hw_init(uarts[i].addr, &uarts[i].setting); } #ifdef PRINTF_CUSTOM init_printf(NULL, putc_); #endif } void usart_reinit(void) { uart_settings_t uart_settings_new; for (int i = 0; i < UARTS_LEN; ++i) { if (!uarts[i].enabled) continue; if(uarts[i].get_uart_settings != NULL){ if(uarts[i].set_uart_queue != NULL){ uarts[i].set_uart_queue(&uarts[i].trans_queue, i); } if(uarts[i].get_uart_settings(&uart_settings_new, i)){ if(uart_settings_new.baud != uarts[i].setting.baud || uart_settings_new.databits != uarts[i].setting.databits || uart_settings_new.parity != uarts[i].setting.parity || uart_settings_new.stopbits != uarts[i].setting.stopbits){ uarts[i].setting.baud = uart_settings_new.baud; uarts[i].setting.databits = uart_settings_new.databits; uarts[i].setting.parity = uart_settings_new.parity; uarts[i].setting.stopbits = uart_settings_new.stopbits; uart_hw_init(uarts[i].addr, &uarts[i].setting); } } } } } void transport_enable_tx(uint8_t indx_uarts) { usart_interrupt_enable(uarts[indx_uarts].addr, USART_TDBE_INT, TRUE); } static inline void transport_irq_handler(uint8_t indx_uarts) { uint16_t c; static BaseType_t xHigherPriorityTaskWoken = pdFALSE; if (uarts[indx_uarts].addr->sts & USART_ROERR_FLAG) { c = uarts[indx_uarts].addr->dt; //DBG printf("overrunRS485\r\n"); } if (uarts[indx_uarts].addr->sts & USART_PERR_FLAG) { c = uarts[indx_uarts].addr->dt; //DBG printf("[rs485] parity fail: 0x%X\r\n", c); } if (usart_flag_get(uarts[indx_uarts].addr, USART_TDBE_FLAG) != RESET) { if(uarts[indx_uarts].trans_queue.txQ != NULL){ if (xQueueReceiveFromISR(*(uarts[indx_uarts].trans_queue.txQ), &c, &xHigherPriorityTaskWoken) == pdTRUE) { uarts[indx_uarts].addr->dt = c; //DBG printf("wr: 0x%x\r\n", c); portYIELD_FROM_ISR(xHigherPriorityTaskWoken); } else { uarts[indx_uarts].addr->ctrl1_bit.tdbeien = FALSE; uarts[indx_uarts].addr->ctrl1_bit.rdbfien = TRUE; } } else{ uarts[indx_uarts].addr->ctrl1_bit.tdbeien = FALSE; uarts[indx_uarts].addr->ctrl1_bit.rdbfien = TRUE; } //USART_ClearITPendingBit(uarts[indx_uarts].addr, USART_IT_TXE); } if (usart_flag_get(uarts[indx_uarts].addr, USART_RDBF_FLAG) != RESET) { c = uarts[indx_uarts].addr->dt; if (uarts[indx_uarts].addr->ctrl1_bit.pen == TRUE) { if (uarts[indx_uarts].addr->ctrl1_bit.dbn == TRUE) { /* 8-bit data */ c &= 0xFF; } else { /* 7-bit data */ c &= 0x7F; } } if(uarts[indx_uarts].trans_queue.rxQ != NULL){ if (xQueueSendFromISR(*(uarts[indx_uarts].trans_queue.rxQ), &c, &xHigherPriorityTaskWoken) == pdTRUE) { //DBG printf("wr: 0x%x\r\n", c); } else { //DBG printf("[uart] rx overflow\r\n"); } portYIELD_FROM_ISR(xHigherPriorityTaskWoken); } //USART_ClearITPendingBit(uarts[indx_uarts].addr, USART_IT_RXNE); } } // RS485_1 void UART7_IRQHandler(void) { transport_irq_handler(0); } // RS485_2 void USART3_IRQHandler(void) { transport_irq_handler(2); } // RS232_1 void UART4_IRQHandler(void) { transport_irq_handler(3); } // RS232_2 void UART5_IRQHandler(void) { transport_irq_handler(4); }