291 lines
8.5 KiB
C
291 lines
8.5 KiB
C
/*
|
||
* FreeModbus Libary: RT-Thread Port
|
||
* Copyright (C) 2013 Armink <armink.ztl@gmail.com>
|
||
*
|
||
* 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 */
|
||
|
||
/* 创建主站发送任<E98081>?? */
|
||
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, /* 任务栈大<E6A088>?? */
|
||
(void *)NULL, /* 任务入口函数参数 */
|
||
(UBaseType_t)MB_TX_PRIO, /* 任务的优先级 */
|
||
NULL); /*任务控制块指<E59D97>?? */
|
||
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, /* 退出时清除事件<E4BA8B>?? */
|
||
pdFALSE, /* 满足感兴趣的所有事<E69C89>?? */
|
||
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
|