amiro-blt / Host / Source / SerialBoot / port / win32 / xcptransport.c @ 69661903
History | View | Annotate | Download (10.574 KB)
1 | 69661903 | Thomas Schöpping | /************************************************************************************//** |
---|---|---|---|
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 *****************************/
|