/* * FreeModbus Libary: RT-Thread Port * Copyright (C) 2013 Armink * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * File: $Id: portserial_m.c,v 1.60 2013/08/13 15:07:05 Armink add Master * Functions $ */ #include "port.h" /* ----------------------- Modbus includes ----------------------------------*/ #include "mb.h" #include "mbport.h" #include "wk_bsp.h" static usart_type* port_uart_list[] = {UART7}; static usart_type* port_uart; #if MB_MASTER_RTU_ENABLED > 0 || MB_MASTER_ASCII_ENABLED > 0 /* ----------------------- Static variables ---------------------------------*/ static volatile uint8_t rx_buff[FIFO_SIZE_MAX]; static Serial_fifo Master_serial_rx_fifo; /* software simulation serial transmit IRQ handler thread stack */ /* software simulation serial transmit IRQ handler thread */ static TaskHandle_t thread_serial_soft_trans_irq = NULL; /* 创建任务句柄 */ /* serial event */ static EventGroupHandle_t event_serial = NULL; /* modbus master serial device */ //static UART_HandleTypeDef *serial; /* ----------------------- Defines ------------------------------------------*/ /* serial transmit event */ #define EVENT_SERIAL_TRANS_START (1 << 0) /* ----------------------- static functions ---------------------------------*/ static void prvvUARTTxReadyISR(void); static void prvvUARTRxISR(void); static void serial_soft_trans_irq(void *parameter); //static void Master_TxCpltCallback(struct __UART_HandleTypeDef *huart); //static void Master_RxCpltCallback(struct __UART_HandleTypeDef *huart); static int stm32_getc(void); static int stm32_putc(CHAR c); /* ----------------------- Start implementation -----------------------------*/ BOOL xMBMasterPortSerialInit(UCHAR ucPORT, ULONG ulBaudRate, UCHAR ucDataBits, eMBParity eParity) { /** * set 485 mode receive and transmit control IO * @note MODBUS_MASTER_RT_CONTROL_PIN_INDEX need be defined by user */ BOOL bStatus = FALSE; usart_parity_selection_type usart_parity; usart_stop_bit_num_type usart_stop; usart_data_bit_num_type usart_data; gpio_init_type gpio_init_struct; bStatus = TRUE; if(ucPORT < (sizeof(port_uart_list) / sizeof(usart_type*))) { port_uart = port_uart_list[ucPORT]; } else { bStatus = FALSE; } switch ( eParity ) { case MB_PAR_NONE: usart_parity = USART_PARITY_NONE; usart_stop = USART_STOP_1_BIT; break; case MB_PAR_ODD: usart_parity = USART_PARITY_ODD; usart_stop = USART_STOP_1_BIT; break; case MB_PAR_EVEN: usart_parity = USART_PARITY_EVEN; usart_stop = USART_STOP_1_BIT; break; default: bStatus = FALSE; break; } switch ( ucDataBits ) { case 8: if(usart_stop == USART_STOP_1_BIT) { usart_data = USART_DATA_8BITS; } else { bStatus = FALSE; } break; default: bStatus = FALSE; break; } //串口初始化 if(TRUE == bStatus) { wk_uart7_init(ulBaudRate, usart_data, usart_stop, usart_parity); switch((u32)port_uart){ case (u32)UART7: usart_interrupt_enable(port_uart, USART_RDBF_INT, FALSE); // NVIC_SetPriority(UART7_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 4, 0));//emac = 5 NVIC_ClearPendingIRQ(UART7_IRQn); nvic_irq_enable(UART7_IRQn, 6, 0); //emac = 5 break; default: bStatus = FALSE; break; } } /* software initialize */ Master_serial_rx_fifo.buffer = rx_buff; Master_serial_rx_fifo.get_index = 0; Master_serial_rx_fifo.put_index = 0; /* software initialize */ /* 创建主站发送任�?? */ event_serial = xEventGroupCreate(); if (NULL != event_serial) { MODBUS_DEBUG("Master create event_serial success! event_serial=%d\r\n", event_serial); } else { MODBUS_DEBUG("Master create event_serial Failed!\r\n"); } BaseType_t xReturn = pdPASS; xReturn = xTaskCreate((TaskFunction_t)serial_soft_trans_irq, /* 任务入口函数 */ (const char *)"mb_tx_irq", /* 任务名字 */ (uint16_t)MB_TX_STK_SIZE, /* 任务栈大�?? */ (void *)NULL, /* 任务入口函数参数 */ (UBaseType_t)MB_TX_PRIO, /* 任务的优先级 */ NULL); /*任务控制块指�?? */ if (xReturn == pdPASS) { MODBUS_DEBUG("xTaskCreate Master trans success\r\n"); } else { MODBUS_DEBUG("xTaskCreate Master trans faild!\r\n"); return FALSE; } return TRUE; } void vMBMasterPortSerialEnable(BOOL xRxEnable, BOOL xTxEnable) { /*这一步不能省略,需要提前清理掉标志位,否则接收会有问题*/ usart_flag_clear(port_uart, USART_RDBF_FLAG); if(xRxEnable == TRUE) { at32_gpio_low(RS485_DE2); usart_interrupt_enable(port_uart, USART_RDBF_INT, TRUE); } else { usart_interrupt_enable(port_uart, USART_RDBF_INT, FALSE); } if (xTxEnable == pdTRUE) { at32_gpio_high(RS485_DE2); /* start serial transmit */ xEventGroupSetBits(event_serial, EVENT_SERIAL_TRANS_START); } else { xEventGroupClearBits(event_serial, EVENT_SERIAL_TRANS_START); } } void vMBMasterPortClose(void) { // __HAL_UART_DISABLE(serial); } BOOL xMBMasterPortSerialPutByte(CHAR ucByte) { // RTT_LOG("%x ",ucByte); stm32_putc(ucByte); return TRUE; } BOOL xMBMasterPortSerialGetByte(CHAR *pucByte) { Get_from_fifo(&Master_serial_rx_fifo, (uint8_t *)pucByte, 1); return TRUE; } /* * Create an interrupt handler for the transmit buffer empty interrupt * (or an equivalent) for your target processor. This function should then * call pxMBFrameCBTransmitterEmpty( ) which tells the protocol stack that * a new character can be sent. The protocol stack will then call * xMBPortSerialPutByte( ) to send the character. */ void prvvUARTTxReadyISR(void) { pxMBMasterFrameCBTransmitterEmpty(); } /* * Create an interrupt handler for the receive interrupt for your target * processor. This function should then call pxMBFrameCBByteReceived( ). The * protocol stack will then call xMBPortSerialGetByte( ) to retrieve the * character. */ void prvvUARTRxISR(void) { pxMBMasterFrameCBByteReceived(); } /** * Software simulation serial transmit IRQ handler. * * @param parameter parameter */ static void serial_soft_trans_irq(void *parameter) { while (1) { /* waiting for serial transmit start */ xEventGroupWaitBits(event_serial, /* 事件对象句柄 */ EVENT_SERIAL_TRANS_START, /* 接收任务感兴趣的事件 */ pdFALSE, /* 退出时清除事件�?? */ pdFALSE, /* 满足感兴趣的所有事�?? */ portMAX_DELAY); /* 指定超时事件,无限等待 */ /* execute modbus callback */ prvvUARTTxReadyISR(); } } /** * @brief Rx Transfer completed callbacks. * @param huart Pointer to a UART_HandleTypeDef structure that contains * the configuration information for the specified UART module. * @retval None */ /*UART发送一个数据*/ static int stm32_putc(CHAR c) { while(usart_flag_get(port_uart, USART_TDBE_FLAG) == RESET); usart_data_transmit(port_uart, (uint16_t)c); while(usart_flag_get(port_uart, USART_TDC_FLAG) == RESET); return TRUE; } void Master_vUSARTHandler( void ) { int ch = -1; if(port_uart->ctrl1_bit.rdbfien == SET) { if(usart_flag_get(port_uart, USART_RDBF_FLAG) == SET) { ch = usart_data_receive(port_uart); Put_in_fifo(&Master_serial_rx_fifo, (uint8_t *)&ch, 1); prvvUARTRxISR(); } } if(port_uart->ctrl1_bit.tdbeien == SET) { if(usart_flag_get(port_uart, USART_TDBE_FLAG) == SET) { prvvUARTTxReadyISR(); } } } void UART7_IRQHandler(void) { Master_vUSARTHandler( ); } #endif