-
Notifications
You must be signed in to change notification settings - Fork 2
/
portserial.c
175 lines (155 loc) · 4.87 KB
/
portserial.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
#include "port.h"
#include "main.h"
#include "cmsis_os2.h"
/* ----------------------- Modbus includes ----------------------------------*/
#include "mb.h"
#include "mbport.h"
/* ----------------------- Static variables ---------------------------------*/
static volatile uint8_t rx_buff[256];
static int rx_index;
static int put_index;
static osThreadId_t receiveDataHandle;
static osEventFlagsId_t xSerialEventHandle;
extern UART_HandleTypeDef huart3;
/* ----------------------- Defines ------------------------------------------*/
#define EVENT_MBSLAVE_HANDLE_RECEIVED_DATA 0x00000001UL
#define huart huart3
#define RS485_SLAVE_TX_MODE() LL_GPIO_SetOutputPin(RS485_SLAVE_CTRL_GPIO_Port, RS485_SLAVE_CTRL_Pin)
#define RS485_SLAVE_RX_MODE() LL_GPIO_ResetOutputPin(RS485_SLAVE_CTRL_GPIO_Port, RS485_SLAVE_CTRL_Pin)
/* ----------------------- static functions ---------------------------------*/
static void handleReceivedDataTask(void *argument);
/* ----------------------- Start implementation -----------------------------*/
BOOL xMBPortSerialInit(UCHAR ucPORT, ULONG ulBaudRate, UCHAR ucDataBits,
eMBParity eParity)
{
/* set serial configure parameter */
huart.Init.BaudRate = ulBaudRate;
huart.Init.WordLength = ucDataBits == 8 ? UART_WORDLENGTH_8B : UART_WORDLENGTH_9B;
huart.Init.StopBits = UART_STOPBITS_1;
switch (eParity)
{
case MB_PAR_NONE:
huart.Init.Parity = UART_PARITY_NONE;
break;
case MB_PAR_ODD:
huart.Init.Parity = UART_PARITY_ODD;
break;
case MB_PAR_EVEN:
huart.Init.Parity = UART_PARITY_EVEN;
break;
default:
return FALSE;
}
huart.Init.Mode = UART_MODE_TX_RX;
huart.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart.Init.OverSampling = UART_OVERSAMPLING_16;
/* open serial device */
if (HAL_UART_Init(&huart) != HAL_OK)
{
Error_Handler();
return FALSE;
}
/* software initialize */
__HAL_UART_ENABLE_IT(&huart, UART_IT_RXNE);
__HAL_UART_ENABLE_IT(&huart, UART_IT_TC);
__HAL_UART_ENABLE_IT(&huart, UART_IT_IDLE);
receiveDataHandle = osThreadNew(handleReceivedDataTask, NULL, NULL);
return TRUE;
}
void vMBPortSerialEnable(BOOL xRxEnable, BOOL xTxEnable)
{
if (xRxEnable)
{
/* switch 485 to receive mode */
RS485_SLAVE_RX_MODE();
}
else
{
/* switch 485 to transmit mode */
RS485_SLAVE_TX_MODE();
}
if (xTxEnable)
{
/* start serial transmit */
rx_index = 0;
put_index = 0;
pxMBFrameCBTransmitterEmpty();
}
else
{
/* stop serial transmit */
HAL_UART_AbortTransmit_IT(&huart);
}
}
void vMBPortClose(void)
{
HAL_UART_AbortReceive_IT(&huart);
HAL_UART_AbortTransmit_IT(&huart);
}
BOOL xMBPortSerialPutByte(CHAR ucByte)
{
HAL_UART_Transmit_IT(&huart, (uint8_t*)&ucByte, 1);
return TRUE;
}
/*
* A Function to send all bytes in one call.
*/
BOOL xMBPortSerialPutBytes(volatile UCHAR *ucByte, USHORT usSize)
{
HAL_UART_Transmit_IT(&huart, (uint8_t *)ucByte, usSize);
return TRUE;
}
BOOL xMBPortSerialGetByte(CHAR * pucByte)
{
*pucByte = rx_buff[rx_index++];
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)
{
pxMBFrameCBTransmitterEmpty();
}
/*
* 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.
*
* quanghona: This function is called when IDLE is detected. thus will then
* trigger the received message handler.
*/
void prvvUARTRxISR(void)
{
osEventFlagsSet(xSerialEventHandle, EVENT_MBSLAVE_HANDLE_RECEIVED_DATA);
}
/*
* Create an interrupt handler for the receive character for your target processor.
* This function should store data to a buffer for received message thread to
* handle later.
*/
void prvvUARTRxReceiveCharISR(CHAR data)
{
rx_buff[put_index++] = data;
}
/*
* A thread to handle the received message.
* This thread is wait until a received message flag is set, then it will call
* pxMBFrameCBByteReceived() until all characters in the receive buffer is handled.
*/
static void handleReceivedDataTask(void *argument)
{
while (1)
{
osEventFlagsWait(xSerialEventHandle, EVENT_MBSLAVE_HANDLE_RECEIVED_DATA, osFlagsWaitAny, osWaitForever);
while (put_index > 0) {
pxMBFrameCBByteReceived();
put_index--;
}
}
}