xref: /nrf52832-nimble/rt-thread/components/net/freemodbus/port/portserial.c (revision 104654410c56c573564690304ae786df310c91fc)
1*10465441SEvalZero /*
2*10465441SEvalZero  * FreeModbus Libary: RT-Thread Port
3*10465441SEvalZero  * Copyright (C) 2013 Armink <[email protected]>
4*10465441SEvalZero  *
5*10465441SEvalZero  * This library is free software; you can redistribute it and/or
6*10465441SEvalZero  * modify it under the terms of the GNU Lesser General Public
7*10465441SEvalZero  * License as published by the Free Software Foundation; either
8*10465441SEvalZero  * version 2.1 of the License, or (at your option) any later version.
9*10465441SEvalZero  *
10*10465441SEvalZero  * This library is distributed in the hope that it will be useful,
11*10465441SEvalZero  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12*10465441SEvalZero  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13*10465441SEvalZero  * Lesser General Public License for more details.
14*10465441SEvalZero  *
15*10465441SEvalZero  * You should have received a copy of the GNU Lesser General Public
16*10465441SEvalZero  * License along with this library; if not, write to the Free Software
17*10465441SEvalZero  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
18*10465441SEvalZero  *
19*10465441SEvalZero  * File: $Id: portserial.c,v 1.60 2013/08/13 15:07:05 Armink $
20*10465441SEvalZero  */
21*10465441SEvalZero 
22*10465441SEvalZero #include "port.h"
23*10465441SEvalZero 
24*10465441SEvalZero /* ----------------------- Modbus includes ----------------------------------*/
25*10465441SEvalZero #include "mb.h"
26*10465441SEvalZero #include "mbport.h"
27*10465441SEvalZero #include "rtdevice.h"
28*10465441SEvalZero #include "board.h"
29*10465441SEvalZero 
30*10465441SEvalZero /* ----------------------- Static variables ---------------------------------*/
31*10465441SEvalZero ALIGN(RT_ALIGN_SIZE)
32*10465441SEvalZero /* software simulation serial transmit IRQ handler thread stack */
33*10465441SEvalZero static rt_uint8_t serial_soft_trans_irq_stack[512];
34*10465441SEvalZero /* software simulation serial transmit IRQ handler thread */
35*10465441SEvalZero static struct rt_thread thread_serial_soft_trans_irq;
36*10465441SEvalZero /* serial event */
37*10465441SEvalZero static struct rt_event event_serial;
38*10465441SEvalZero /* modbus slave serial device */
39*10465441SEvalZero static rt_serial_t *serial;
40*10465441SEvalZero 
41*10465441SEvalZero /* ----------------------- Defines ------------------------------------------*/
42*10465441SEvalZero /* serial transmit event */
43*10465441SEvalZero #define EVENT_SERIAL_TRANS_START    (1<<0)
44*10465441SEvalZero 
45*10465441SEvalZero /* ----------------------- static functions ---------------------------------*/
46*10465441SEvalZero static void prvvUARTTxReadyISR(void);
47*10465441SEvalZero static void prvvUARTRxISR(void);
48*10465441SEvalZero static rt_err_t serial_rx_ind(rt_device_t dev, rt_size_t size);
49*10465441SEvalZero static void serial_soft_trans_irq(void* parameter);
50*10465441SEvalZero 
51*10465441SEvalZero /* ----------------------- Start implementation -----------------------------*/
xMBPortSerialInit(UCHAR ucPORT,ULONG ulBaudRate,UCHAR ucDataBits,eMBParity eParity)52*10465441SEvalZero BOOL xMBPortSerialInit(UCHAR ucPORT, ULONG ulBaudRate, UCHAR ucDataBits,
53*10465441SEvalZero         eMBParity eParity)
54*10465441SEvalZero {
55*10465441SEvalZero     /**
56*10465441SEvalZero      * set 485 mode receive and transmit control IO
57*10465441SEvalZero      * @note MODBUS_SLAVE_RT_CONTROL_PIN_INDEX need be defined by user
58*10465441SEvalZero      */
59*10465441SEvalZero #if defined(RT_MODBUS_SLAVE_USE_CONTROL_PIN)
60*10465441SEvalZero     rt_pin_mode(MODBUS_SLAVE_RT_CONTROL_PIN_INDEX, PIN_MODE_OUTPUT);
61*10465441SEvalZero #endif
62*10465441SEvalZero     /* set serial name */
63*10465441SEvalZero     if (ucPORT == 1) {
64*10465441SEvalZero #if defined(RT_USING_UART1) || defined(RT_USING_REMAP_UART1)
65*10465441SEvalZero         extern struct rt_serial_device serial1;
66*10465441SEvalZero         serial = &serial1;
67*10465441SEvalZero #endif
68*10465441SEvalZero     } else if (ucPORT == 2) {
69*10465441SEvalZero #if defined(RT_USING_UART2)
70*10465441SEvalZero         extern struct rt_serial_device serial2;
71*10465441SEvalZero         serial = &serial2;
72*10465441SEvalZero #endif
73*10465441SEvalZero     } else if (ucPORT == 3) {
74*10465441SEvalZero #if defined(RT_USING_UART3)
75*10465441SEvalZero         extern struct rt_serial_device serial3;
76*10465441SEvalZero         serial = &serial3;
77*10465441SEvalZero #endif
78*10465441SEvalZero     }
79*10465441SEvalZero     /* set serial configure parameter */
80*10465441SEvalZero     serial->config.baud_rate = ulBaudRate;
81*10465441SEvalZero     serial->config.stop_bits = STOP_BITS_1;
82*10465441SEvalZero     switch(eParity){
83*10465441SEvalZero     case MB_PAR_NONE: {
84*10465441SEvalZero         serial->config.data_bits = DATA_BITS_8;
85*10465441SEvalZero         serial->config.parity = PARITY_NONE;
86*10465441SEvalZero         break;
87*10465441SEvalZero     }
88*10465441SEvalZero     case MB_PAR_ODD: {
89*10465441SEvalZero         serial->config.data_bits = DATA_BITS_9;
90*10465441SEvalZero         serial->config.parity = PARITY_ODD;
91*10465441SEvalZero         break;
92*10465441SEvalZero     }
93*10465441SEvalZero     case MB_PAR_EVEN: {
94*10465441SEvalZero         serial->config.data_bits = DATA_BITS_9;
95*10465441SEvalZero         serial->config.parity = PARITY_EVEN;
96*10465441SEvalZero         break;
97*10465441SEvalZero     }
98*10465441SEvalZero     }
99*10465441SEvalZero     /* set serial configure */
100*10465441SEvalZero     serial->ops->configure(serial, &(serial->config));
101*10465441SEvalZero 
102*10465441SEvalZero     /* open serial device */
103*10465441SEvalZero     if (!rt_device_open(&serial->parent, RT_DEVICE_OFLAG_RDWR | RT_DEVICE_FLAG_INT_RX)) {
104*10465441SEvalZero         rt_device_set_rx_indicate(&serial->parent, serial_rx_ind);
105*10465441SEvalZero     } else {
106*10465441SEvalZero         return FALSE;
107*10465441SEvalZero     }
108*10465441SEvalZero 
109*10465441SEvalZero     /* software initialize */
110*10465441SEvalZero     rt_event_init(&event_serial, "slave event", RT_IPC_FLAG_PRIO);
111*10465441SEvalZero     rt_thread_init(&thread_serial_soft_trans_irq,
112*10465441SEvalZero                    "slave trans",
113*10465441SEvalZero                    serial_soft_trans_irq,
114*10465441SEvalZero                    RT_NULL,
115*10465441SEvalZero                    serial_soft_trans_irq_stack,
116*10465441SEvalZero                    sizeof(serial_soft_trans_irq_stack),
117*10465441SEvalZero                    10, 5);
118*10465441SEvalZero     rt_thread_startup(&thread_serial_soft_trans_irq);
119*10465441SEvalZero 
120*10465441SEvalZero     return TRUE;
121*10465441SEvalZero }
122*10465441SEvalZero 
vMBPortSerialEnable(BOOL xRxEnable,BOOL xTxEnable)123*10465441SEvalZero void vMBPortSerialEnable(BOOL xRxEnable, BOOL xTxEnable)
124*10465441SEvalZero {
125*10465441SEvalZero     rt_uint32_t recved_event;
126*10465441SEvalZero     if (xRxEnable)
127*10465441SEvalZero     {
128*10465441SEvalZero         /* enable RX interrupt */
129*10465441SEvalZero         serial->ops->control(serial, RT_DEVICE_CTRL_SET_INT, (void *)RT_DEVICE_FLAG_INT_RX);
130*10465441SEvalZero         /* switch 485 to receive mode */
131*10465441SEvalZero #if defined(RT_MODBUS_SLAVE_USE_CONTROL_PIN)
132*10465441SEvalZero         rt_pin_write(MODBUS_SLAVE_RT_CONTROL_PIN_INDEX, PIN_LOW);
133*10465441SEvalZero #endif
134*10465441SEvalZero     }
135*10465441SEvalZero     else
136*10465441SEvalZero     {
137*10465441SEvalZero         /* switch 485 to transmit mode */
138*10465441SEvalZero #if defined(RT_MODBUS_SLAVE_USE_CONTROL_PIN)
139*10465441SEvalZero         rt_pin_write(MODBUS_SLAVE_RT_CONTROL_PIN_INDEX, PIN_HIGH);
140*10465441SEvalZero #endif
141*10465441SEvalZero         /* disable RX interrupt */
142*10465441SEvalZero         serial->ops->control(serial, RT_DEVICE_CTRL_CLR_INT, (void *)RT_DEVICE_FLAG_INT_RX);
143*10465441SEvalZero     }
144*10465441SEvalZero     if (xTxEnable)
145*10465441SEvalZero     {
146*10465441SEvalZero         /* start serial transmit */
147*10465441SEvalZero         rt_event_send(&event_serial, EVENT_SERIAL_TRANS_START);
148*10465441SEvalZero     }
149*10465441SEvalZero     else
150*10465441SEvalZero     {
151*10465441SEvalZero         /* stop serial transmit */
152*10465441SEvalZero         rt_event_recv(&event_serial, EVENT_SERIAL_TRANS_START,
153*10465441SEvalZero                 RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR, 0,
154*10465441SEvalZero                 &recved_event);
155*10465441SEvalZero     }
156*10465441SEvalZero }
157*10465441SEvalZero 
vMBPortClose(void)158*10465441SEvalZero void vMBPortClose(void)
159*10465441SEvalZero {
160*10465441SEvalZero     serial->parent.close(&(serial->parent));
161*10465441SEvalZero }
162*10465441SEvalZero 
xMBPortSerialPutByte(CHAR ucByte)163*10465441SEvalZero BOOL xMBPortSerialPutByte(CHAR ucByte)
164*10465441SEvalZero {
165*10465441SEvalZero     serial->parent.write(&(serial->parent), 0, &ucByte, 1);
166*10465441SEvalZero     return TRUE;
167*10465441SEvalZero }
168*10465441SEvalZero 
xMBPortSerialGetByte(CHAR * pucByte)169*10465441SEvalZero BOOL xMBPortSerialGetByte(CHAR * pucByte)
170*10465441SEvalZero {
171*10465441SEvalZero     serial->parent.read(&(serial->parent), 0, pucByte, 1);
172*10465441SEvalZero     return TRUE;
173*10465441SEvalZero }
174*10465441SEvalZero 
175*10465441SEvalZero /*
176*10465441SEvalZero  * Create an interrupt handler for the transmit buffer empty interrupt
177*10465441SEvalZero  * (or an equivalent) for your target processor. This function should then
178*10465441SEvalZero  * call pxMBFrameCBTransmitterEmpty( ) which tells the protocol stack that
179*10465441SEvalZero  * a new character can be sent. The protocol stack will then call
180*10465441SEvalZero  * xMBPortSerialPutByte( ) to send the character.
181*10465441SEvalZero  */
prvvUARTTxReadyISR(void)182*10465441SEvalZero void prvvUARTTxReadyISR(void)
183*10465441SEvalZero {
184*10465441SEvalZero     pxMBFrameCBTransmitterEmpty();
185*10465441SEvalZero }
186*10465441SEvalZero 
187*10465441SEvalZero /*
188*10465441SEvalZero  * Create an interrupt handler for the receive interrupt for your target
189*10465441SEvalZero  * processor. This function should then call pxMBFrameCBByteReceived( ). The
190*10465441SEvalZero  * protocol stack will then call xMBPortSerialGetByte( ) to retrieve the
191*10465441SEvalZero  * character.
192*10465441SEvalZero  */
prvvUARTRxISR(void)193*10465441SEvalZero void prvvUARTRxISR(void)
194*10465441SEvalZero {
195*10465441SEvalZero     pxMBFrameCBByteReceived();
196*10465441SEvalZero }
197*10465441SEvalZero 
198*10465441SEvalZero /**
199*10465441SEvalZero  * Software simulation serial transmit IRQ handler.
200*10465441SEvalZero  *
201*10465441SEvalZero  * @param parameter parameter
202*10465441SEvalZero  */
serial_soft_trans_irq(void * parameter)203*10465441SEvalZero static void serial_soft_trans_irq(void* parameter) {
204*10465441SEvalZero     rt_uint32_t recved_event;
205*10465441SEvalZero     while (1)
206*10465441SEvalZero     {
207*10465441SEvalZero         /* waiting for serial transmit start */
208*10465441SEvalZero         rt_event_recv(&event_serial, EVENT_SERIAL_TRANS_START, RT_EVENT_FLAG_OR,
209*10465441SEvalZero                 RT_WAITING_FOREVER, &recved_event);
210*10465441SEvalZero         /* execute modbus callback */
211*10465441SEvalZero         prvvUARTTxReadyISR();
212*10465441SEvalZero     }
213*10465441SEvalZero }
214*10465441SEvalZero 
215*10465441SEvalZero /**
216*10465441SEvalZero  * This function is serial receive callback function
217*10465441SEvalZero  *
218*10465441SEvalZero  * @param dev the device of serial
219*10465441SEvalZero  * @param size the data size that receive
220*10465441SEvalZero  *
221*10465441SEvalZero  * @return return RT_EOK
222*10465441SEvalZero  */
serial_rx_ind(rt_device_t dev,rt_size_t size)223*10465441SEvalZero static rt_err_t serial_rx_ind(rt_device_t dev, rt_size_t size) {
224*10465441SEvalZero     prvvUARTRxISR();
225*10465441SEvalZero     return RT_EOK;
226*10465441SEvalZero }
227