amiro-blt / Host / Source / SerialBoot / port / win32 / xcptransport.c @ 69661903
History | View | Annotate | Download (10.6 KB)
1 |
/************************************************************************************//** |
---|---|
2 |
* \file port\win32\xcptransport.c
|
3 |
* \brief XCP transport layer interface source file.
|
4 |
* \ingroup SerialBoot
|
5 |
* \internal
|
6 |
*----------------------------------------------------------------------------------------
|
7 |
* C O P Y R I G H T
|
8 |
*----------------------------------------------------------------------------------------
|
9 |
* Copyright (c) 2014 by Feaser http://www.feaser.com All rights reserved
|
10 |
*
|
11 |
*----------------------------------------------------------------------------------------
|
12 |
* L I C E N S E
|
13 |
*----------------------------------------------------------------------------------------
|
14 |
* This file is part of OpenBLT. OpenBLT is free software: you can redistribute it and/or
|
15 |
* modify it under the terms of the GNU General Public License as published by the Free
|
16 |
* Software Foundation, either version 3 of the License, or (at your option) any later
|
17 |
* version.
|
18 |
*
|
19 |
* OpenBLT is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
20 |
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
21 |
* PURPOSE. See the GNU General Public License for more details.
|
22 |
*
|
23 |
* You should have received a copy of the GNU General Public License along with OpenBLT.
|
24 |
* If not, see <http://www.gnu.org/licenses/>.
|
25 |
*
|
26 |
* A special exception to the GPL is included to allow you to distribute a combined work
|
27 |
* that includes OpenBLT without being obliged to provide the source code for any
|
28 |
* proprietary components. The exception text is included at the bottom of the license
|
29 |
* file <license.html>.
|
30 |
*
|
31 |
* \endinternal
|
32 |
****************************************************************************************/
|
33 |
|
34 |
/****************************************************************************************
|
35 |
* Include files
|
36 |
****************************************************************************************/
|
37 |
#include <assert.h> /* assertion module */ |
38 |
#include <sb_types.h> /* C types */ |
39 |
#include <windows.h> /* for WIN32 library */ |
40 |
#include <string.h> /* string library */ |
41 |
#include "xcpmaster.h" /* XCP master protocol module */ |
42 |
#include "timeutil.h" /* time utility module */ |
43 |
|
44 |
|
45 |
/****************************************************************************************
|
46 |
* Macro definitions
|
47 |
****************************************************************************************/
|
48 |
#define UART_TX_BUFFER_SIZE (1024) /**< transmission buffer size */ |
49 |
#define UART_RX_BUFFER_SIZE (1024) /**< reception buffer size */ |
50 |
|
51 |
/** \brief maximum number of bytes in a transmit/receive XCP packet in UART. */
|
52 |
#define XCP_MASTER_UART_MAX_DATA ((XCP_MASTER_TX_MAX_DATA>XCP_MASTER_RX_MAX_DATA) ? \
|
53 |
(XCP_MASTER_TX_MAX_DATA+1) : (XCP_MASTER_RX_MAX_DATA+1)) |
54 |
|
55 |
/** \brief The smallest time in millisecond that the UART is configured for. */
|
56 |
#define UART_RX_TIMEOUT_MIN_MS (5) |
57 |
|
58 |
|
59 |
/****************************************************************************************
|
60 |
* Local data declarations
|
61 |
****************************************************************************************/
|
62 |
static tXcpTransportResponsePacket responsePacket;
|
63 |
static HANDLE hUart = INVALID_HANDLE_VALUE;
|
64 |
|
65 |
|
66 |
/************************************************************************************//** |
67 |
** \brief Initializes the communication interface used by this transport layer.
|
68 |
** \param device Serial communication device name. For example "COM4".
|
69 |
** \param baudrate Communication speed in bits/sec.
|
70 |
** \return SB_TRUE if successful, SB_FALSE otherwise.
|
71 |
**
|
72 |
****************************************************************************************/
|
73 |
sb_uint8 XcpTransportInit(sb_char *device, sb_uint32 baudrate, sb_uint8 comIsUart) |
74 |
{ |
75 |
COMMTIMEOUTS timeouts = { 0 };
|
76 |
DCB dcbSerialParams = { 0 };
|
77 |
char portStr[64] = "\\\\.\\\0"; |
78 |
|
79 |
if (hUart != INVALID_HANDLE_VALUE) {
|
80 |
return SB_TRUE;
|
81 |
} |
82 |
|
83 |
/* construct the COM port name as a string */
|
84 |
strncat(portStr, device, 59);
|
85 |
|
86 |
/* obtain access to the COM port */
|
87 |
hUart = CreateFile(portStr, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, |
88 |
FILE_ATTRIBUTE_NORMAL, 0);
|
89 |
|
90 |
/* validate COM port handle */
|
91 |
if (hUart == INVALID_HANDLE_VALUE)
|
92 |
{ |
93 |
return SB_FALSE;
|
94 |
} |
95 |
|
96 |
/* get current COM port configuration */
|
97 |
dcbSerialParams.DCBlength = sizeof(dcbSerialParams);
|
98 |
if (!GetCommState(hUart, &dcbSerialParams))
|
99 |
{ |
100 |
XcpTransportClose(); |
101 |
return SB_FALSE;
|
102 |
} |
103 |
|
104 |
/* configure the baudrate and 8,n,1 */
|
105 |
dcbSerialParams.BaudRate = baudrate; |
106 |
dcbSerialParams.ByteSize = 8;
|
107 |
dcbSerialParams.StopBits = ONESTOPBIT; |
108 |
dcbSerialParams.Parity = NOPARITY; |
109 |
if (!SetCommState(hUart, &dcbSerialParams))
|
110 |
{ |
111 |
XcpTransportClose(); |
112 |
return SB_FALSE;
|
113 |
} |
114 |
|
115 |
/* set communication timeout parameters */
|
116 |
timeouts.ReadIntervalTimeout = UART_RX_TIMEOUT_MIN_MS; |
117 |
timeouts.ReadTotalTimeoutConstant = UART_RX_TIMEOUT_MIN_MS; |
118 |
timeouts.ReadTotalTimeoutMultiplier = 1;
|
119 |
timeouts.WriteTotalTimeoutConstant = UART_RX_TIMEOUT_MIN_MS; |
120 |
timeouts.WriteTotalTimeoutMultiplier = 1;
|
121 |
if (!SetCommTimeouts(hUart, &timeouts))
|
122 |
{ |
123 |
XcpTransportClose(); |
124 |
return SB_FALSE;
|
125 |
} |
126 |
|
127 |
if (!EscapeCommFunction(hUart,SETDTR))
|
128 |
{ |
129 |
XcpTransportClose(); |
130 |
return SB_FALSE;
|
131 |
} |
132 |
/* if (!EscapeCommFunction(hUart,CLRDTR))
|
133 |
{
|
134 |
XcpTransportClose();
|
135 |
return SB_FALSE;
|
136 |
}*/
|
137 |
if (!EscapeCommFunction(hUart,SETRTS))
|
138 |
{ |
139 |
XcpTransportClose(); |
140 |
return SB_FALSE;
|
141 |
} |
142 |
if (!EscapeCommFunction(hUart,CLRRTS))
|
143 |
{ |
144 |
XcpTransportClose(); |
145 |
return SB_FALSE;
|
146 |
} |
147 |
|
148 |
/* set transmit and receive buffer sizes */
|
149 |
if(!SetupComm(hUart, UART_RX_BUFFER_SIZE, UART_TX_BUFFER_SIZE))
|
150 |
{ |
151 |
XcpTransportClose(); |
152 |
return SB_FALSE;
|
153 |
} |
154 |
|
155 |
/* empty the transmit and receive buffers */
|
156 |
if (!FlushFileBuffers(hUart))
|
157 |
{ |
158 |
XcpTransportClose(); |
159 |
return SB_FALSE;
|
160 |
} |
161 |
/* successfully connected to the serial device */
|
162 |
return SB_TRUE;
|
163 |
} /*** end of XcpTransportInit ***/
|
164 |
|
165 |
|
166 |
/************************************************************************************//** |
167 |
** \brief Transmits an XCP packet on the transport layer and attemps to receive the
|
168 |
** response within the given timeout. The data in the response packet is
|
169 |
** stored in an internal data buffer that can be obtained through function
|
170 |
** XcpTransportReadResponsePacket().
|
171 |
** \return SB_TRUE is the response packet was successfully received and stored,
|
172 |
** SB_FALSE otherwise.
|
173 |
**
|
174 |
****************************************************************************************/
|
175 |
sb_uint8 XcpTransportSendPacket(sb_uint8 *data, sb_uint8 len, sb_uint16 timeOutMs) |
176 |
{ |
177 |
DWORD dwWritten = 0;
|
178 |
DWORD dwRead = 0;
|
179 |
sb_uint32 dwToRead; |
180 |
sb_uint16 cnt; |
181 |
static sb_uint8 xcpUartBuffer[XCP_MASTER_UART_MAX_DATA]; /* static to lower stack load */ |
182 |
sb_uint16 xcpUartLen; |
183 |
sb_uint8 *uartReadDataPtr; |
184 |
sb_uint32 timeoutTime; |
185 |
|
186 |
/* ------------------------ XCP packet transmission -------------------------------- */
|
187 |
/* prepare the XCP packet for transmission on UART. this is basically the same as the
|
188 |
* xcp packet data but just the length of the packet is added to the first byte.
|
189 |
*/
|
190 |
xcpUartLen = len+1;
|
191 |
xcpUartBuffer[0] = len;
|
192 |
for (cnt=0; cnt<len; cnt++) |
193 |
{ |
194 |
xcpUartBuffer[cnt+1] = data[cnt];
|
195 |
} |
196 |
|
197 |
/* first submit the XCP packet for transmission */
|
198 |
if (!WriteFile(hUart, xcpUartBuffer, xcpUartLen, &dwWritten, SB_NULL))
|
199 |
{ |
200 |
return SB_FALSE;
|
201 |
} |
202 |
/* double check that all bytes were actually transmitted */
|
203 |
if (dwWritten != xcpUartLen)
|
204 |
{ |
205 |
return SB_FALSE;
|
206 |
} |
207 |
|
208 |
/* ------------------------ XCP packet reception ----------------------------------- */
|
209 |
/* determine timeout time */
|
210 |
timeoutTime = TimeUtilGetSystemTimeMs() + timeOutMs + UART_RX_TIMEOUT_MIN_MS; |
211 |
|
212 |
/* read the first byte, which contains the length of the xcp packet that follows */
|
213 |
dwToRead = 1;
|
214 |
uartReadDataPtr = &responsePacket.len; |
215 |
while(dwToRead > 0) |
216 |
{ |
217 |
dwRead = 0;
|
218 |
if (ReadFile(hUart, uartReadDataPtr, dwToRead, &dwRead, NULL)) |
219 |
{ |
220 |
/* update the bytes that were already read */
|
221 |
uartReadDataPtr += dwRead; |
222 |
dwToRead -= dwRead; |
223 |
} |
224 |
/* check for timeout if not yet done */
|
225 |
if ( (dwToRead > 0) && (TimeUtilGetSystemTimeMs() >= timeoutTime) ) |
226 |
{ |
227 |
/* timeout occurred */
|
228 |
return SB_FALSE;
|
229 |
} |
230 |
} |
231 |
|
232 |
/* read the rest of the packet */
|
233 |
dwToRead = responsePacket.len; |
234 |
uartReadDataPtr = &responsePacket.data[0];
|
235 |
while(dwToRead > 0) |
236 |
{ |
237 |
dwRead = 0;
|
238 |
if (ReadFile(hUart, uartReadDataPtr, dwToRead, &dwRead, NULL)) |
239 |
{ |
240 |
/* update the bytes that were already read */
|
241 |
uartReadDataPtr += dwRead; |
242 |
dwToRead -= dwRead; |
243 |
} |
244 |
/* check for timeout if not yet done */
|
245 |
if ( (dwToRead > 0) && (TimeUtilGetSystemTimeMs() >= timeoutTime) ) |
246 |
{ |
247 |
/* timeout occurred */
|
248 |
return SB_FALSE;
|
249 |
} |
250 |
} |
251 |
/* still here so the complete packet was received */
|
252 |
return SB_TRUE;
|
253 |
} /*** end of XcpMasterTpSendPacket ***/
|
254 |
|
255 |
|
256 |
/************************************************************************************//** |
257 |
** \brief Reads the data from the response packet. Make sure to not call this
|
258 |
** function while XcpTransportSendPacket() is active, because the data won't be
|
259 |
** valid then.
|
260 |
** \return Pointer to the response packet data.
|
261 |
**
|
262 |
****************************************************************************************/
|
263 |
tXcpTransportResponsePacket *XcpTransportReadResponsePacket(void)
|
264 |
{ |
265 |
return &responsePacket;
|
266 |
} /*** end of XcpTransportReadResponsePacket ***/
|
267 |
|
268 |
|
269 |
/************************************************************************************//** |
270 |
** \brief Closes the communication channel.
|
271 |
** \return none.
|
272 |
**
|
273 |
****************************************************************************************/
|
274 |
void XcpTransportClose(void) |
275 |
{ |
276 |
/* close the COM port handle if valid */
|
277 |
if (hUart != INVALID_HANDLE_VALUE)
|
278 |
{ |
279 |
CloseHandle(hUart); |
280 |
} |
281 |
|
282 |
/* set handles to invalid */
|
283 |
hUart = INVALID_HANDLE_VALUE; |
284 |
} /*** end of XcpTransportClose ***/
|
285 |
|
286 |
|
287 |
/*********************************** end of xcptransport.c *****************************/
|