Mercurial > public > ostc4
comparison Small_CPU/Src/uart_Internal.c @ 922:7c996354b8ac Evo_2_23
Moved UART6 into a separate unit:
UART6 connects internal devices. As a first step the existing code sections have been moved into a new unit. As well the code of the external GNSS sensor has been copied into this unit as starting point for the further development. Later the internal part can be integrated into the common uart (code cleanup).
author | Ideenmodellierer |
---|---|
date | Sun, 03 Nov 2024 20:53:05 +0100 |
parents | |
children | 6fc0e3d230e4 |
comparison
equal
deleted
inserted
replaced
921:eb4109d7d1e9 | 922:7c996354b8ac |
---|---|
1 /** | |
2 ****************************************************************************** | |
3 * @file uart_Internal.c | |
4 * @author heinrichs weikamp gmbh | |
5 * @version V0.0.1 | |
6 * @date 03-November-2044 | |
7 * @brief Control functions for devices connected to the internal UART | |
8 * | |
9 @verbatim | |
10 ============================================================================== | |
11 ##### How to use ##### | |
12 ============================================================================== | |
13 @endverbatim | |
14 ****************************************************************************** | |
15 * @attention | |
16 * | |
17 * <h2><center>© COPYRIGHT(c) 2015 heinrichs weikamp</center></h2> | |
18 * | |
19 ****************************************************************************** | |
20 */ | |
21 /* Includes ------------------------------------------------------------------*/ | |
22 #include "uart.h" | |
23 #include "uart_Internal.h" | |
24 #include "uartProtocol_GNSS.h" | |
25 #include "GNSS.h" | |
26 #include "externalInterface.h" | |
27 #include "data_exchange.h" | |
28 #include <string.h> /* memset */ | |
29 | |
30 | |
31 static uint8_t isEndIndication6(uint8_t index); | |
32 static uint8_t gnssState = UART_GNSS_INIT; | |
33 | |
34 /* Private variables ---------------------------------------------------------*/ | |
35 | |
36 | |
37 #define TX_BUF_SIZE (40u) /* max length for commands */ | |
38 #define CHUNK_SIZE (25u) /* the DMA will handle chunk size transfers */ | |
39 #define CHUNKS_PER_BUFFER (6u) | |
40 | |
41 #define REQUEST_INT_SENSOR_MS (1500) /* Minimum time interval for cyclic sensor data requests per sensor (UART mux) */ | |
42 #define COMMAND_TX_DELAY (30u) /* The time the sensor needs to recover from a invalid command request */ | |
43 #define TIMEOUT_SENSOR_ANSWER (300) /* Time till a request is repeated if no answer was received */ | |
44 | |
45 | |
46 static receiveStateGnss_t rxState = GNSSRX_READY; | |
47 static uint8_t GnssConnected = 0; /* Binary indicator if a sensor is connected or not */ | |
48 | |
49 static uint8_t writeIndex = 0; | |
50 | |
51 static uint8_t dataToRead = 0; | |
52 | |
53 DMA_HandleTypeDef hdma_usart6_rx, hdma_usart6_tx; | |
54 | |
55 uint8_t tx6Buffer[CHUNK_SIZE]; /* tx uses less bytes */ | |
56 uint8_t tx6BufferQue[TX_BUF_SIZE]; /* In MUX mode command may be send shortly after each other => allow q 1 entry que */ | |
57 uint8_t tx6BufferQueLen; | |
58 | |
59 uint8_t rxBufferUart6[CHUNK_SIZE * CHUNKS_PER_BUFFER]; /* The complete buffer has a X * chunk size to allow variations in buffer read time */ | |
60 uint8_t txBufferUart6[CHUNK_SIZE * CHUNKS_PER_BUFFER]; /* The complete buffer has a X * chunk size to allow variations in buffer read time */ | |
61 | |
62 static uint8_t rx6WriteIndex; /* Index of the data item which is analysed */ | |
63 static uint8_t rx6ReadIndex; /* Index at which new data is stared */ | |
64 | |
65 static uint8_t dmaRx6Active; /* Indicator if DMA reception needs to be started */ | |
66 static uint8_t dmaTx6Active; /* Indicator if DMA reception needs to be started */ | |
67 | |
68 | |
69 /* Exported functions --------------------------------------------------------*/ | |
70 | |
71 void UART_clearRx6Buffer(void) | |
72 { | |
73 uint16_t index = 0; | |
74 do | |
75 { | |
76 rxBufferUart6[index++] = BUFFER_NODATA_LOW; | |
77 rxBufferUart6[index++] = BUFFER_NODATA_HIGH; | |
78 } while (index < sizeof(rxBufferUart6)); | |
79 | |
80 rx6ReadIndex = 0; | |
81 rx6WriteIndex = 0; | |
82 } | |
83 | |
84 void GNSS_IO_init() { | |
85 | |
86 GPIO_InitTypeDef GPIO_InitStruct = { 0 }; | |
87 /* Peripheral clock enable */ | |
88 __HAL_RCC_USART6_CLK_ENABLE() | |
89 ; | |
90 | |
91 __HAL_RCC_GPIOA_CLK_ENABLE() | |
92 ; | |
93 /**USART6 GPIO Configuration | |
94 PA11 ------> USART6_TX | |
95 PA12 ------> USART6_RX | |
96 */ | |
97 GPIO_InitStruct.Pin = GPIO_PIN_11 | GPIO_PIN_12; | |
98 GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; | |
99 GPIO_InitStruct.Pull = GPIO_NOPULL; | |
100 GPIO_InitStruct.Speed = GPIO_SPEED_FAST; | |
101 GPIO_InitStruct.Alternate = GPIO_AF8_USART6; | |
102 HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); | |
103 | |
104 /* USART6 DMA Init */ | |
105 /* USART6_RX Init */ | |
106 hdma_usart6_rx.Instance = DMA2_Stream1; | |
107 hdma_usart6_rx.Init.Channel = DMA_CHANNEL_5; | |
108 hdma_usart6_rx.Init.Direction = DMA_PERIPH_TO_MEMORY; | |
109 hdma_usart6_rx.Init.PeriphInc = DMA_PINC_DISABLE; | |
110 hdma_usart6_rx.Init.MemInc = DMA_MINC_ENABLE; | |
111 hdma_usart6_rx.Init.PeriphDataAlignment = DMA_MDATAALIGN_BYTE; | |
112 hdma_usart6_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; | |
113 hdma_usart6_rx.Init.Mode = DMA_NORMAL; | |
114 hdma_usart6_rx.Init.Priority = DMA_PRIORITY_LOW; | |
115 hdma_usart6_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE; | |
116 HAL_DMA_Init(&hdma_usart6_rx); | |
117 | |
118 __HAL_LINKDMA(&huart6, hdmarx, hdma_usart6_rx); | |
119 | |
120 /* USART6_TX Init */ | |
121 hdma_usart6_tx.Instance = DMA2_Stream6; | |
122 hdma_usart6_tx.Init.Channel = DMA_CHANNEL_5; | |
123 hdma_usart6_tx.Init.Direction = DMA_MEMORY_TO_PERIPH; | |
124 hdma_usart6_tx.Init.PeriphInc = DMA_PINC_DISABLE; | |
125 hdma_usart6_tx.Init.MemInc = DMA_MINC_ENABLE; | |
126 hdma_usart6_tx.Init.PeriphDataAlignment = DMA_MDATAALIGN_BYTE; | |
127 hdma_usart6_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; | |
128 hdma_usart6_tx.Init.Mode = DMA_NORMAL; | |
129 hdma_usart6_tx.Init.Priority = DMA_PRIORITY_LOW; | |
130 hdma_usart6_tx.Init.FIFOMode = DMA_FIFOMODE_DISABLE; | |
131 HAL_DMA_Init(&hdma_usart6_tx); | |
132 | |
133 __HAL_LINKDMA(&huart6, hdmatx, hdma_usart6_tx); | |
134 | |
135 /* USART6 interrupt Init */ | |
136 HAL_NVIC_SetPriority(USART6_IRQn, 0, 0); | |
137 HAL_NVIC_EnableIRQ(USART6_IRQn); | |
138 | |
139 MX_USART6_DMA_Init(); | |
140 | |
141 } | |
142 | |
143 void MX_USART6_DMA_Init() { | |
144 /* DMA controller clock enable */ | |
145 __HAL_RCC_DMA2_CLK_ENABLE(); | |
146 | |
147 /* DMA interrupt init */ | |
148 /* DMA2_Stream2_IRQn interrupt configuration */ | |
149 HAL_NVIC_SetPriority(DMA2_Stream2_IRQn, 0, 0); | |
150 HAL_NVIC_EnableIRQ(DMA2_Stream2_IRQn); | |
151 /* DMA2_Stream6_IRQn interrupt configuration */ | |
152 HAL_NVIC_SetPriority(DMA2_Stream6_IRQn, 0, 0); | |
153 HAL_NVIC_EnableIRQ(DMA2_Stream6_IRQn); | |
154 } | |
155 | |
156 | |
157 void MX_USART6_UART_DeInit(void) | |
158 { | |
159 HAL_DMA_Abort(&hdma_usart6_rx); | |
160 HAL_DMA_DeInit(&hdma_usart6_rx); | |
161 HAL_DMA_Abort(&hdma_usart6_tx); | |
162 HAL_DMA_DeInit(&hdma_usart6_tx); | |
163 HAL_UART_DeInit(&huart6); | |
164 HAL_UART_DeInit(&huart6); | |
165 } | |
166 | |
167 void MX_USART6_UART_Init(void) { | |
168 huart6.Instance = USART6; | |
169 huart6.Init.BaudRate = 9600; | |
170 huart6.Init.WordLength = UART_WORDLENGTH_8B; | |
171 huart6.Init.StopBits = UART_STOPBITS_1; | |
172 huart6.Init.Parity = UART_PARITY_NONE; | |
173 huart6.Init.Mode = UART_MODE_TX_RX; | |
174 huart6.Init.HwFlowCtl = UART_HWCONTROL_NONE; | |
175 huart6.Init.OverSampling = UART_OVERSAMPLING_16; | |
176 HAL_UART_Init(&huart6); | |
177 } | |
178 | |
179 | |
180 | |
181 void UART6_SendCmdUbx(const uint8_t *cmd, uint8_t len) | |
182 { | |
183 if(len < TX_BUF_SIZE) /* A longer string is an indication for a missing 0 termination */ | |
184 { | |
185 if(dmaRx6Active == 0) | |
186 { | |
187 UART_StartDMA_Receiption(); | |
188 } | |
189 memcpy(tx6Buffer, cmd, len); | |
190 if(HAL_OK == HAL_UART_Transmit_DMA(&huart6,tx6Buffer,len)) | |
191 { | |
192 dmaTx6Active = 1; | |
193 } | |
194 } | |
195 } | |
196 | |
197 uint8_t isEndIndication6(uint8_t index) | |
198 { | |
199 uint8_t ret = 0; | |
200 if(index % 2) | |
201 { | |
202 if(rxBufferUart6[index] == BUFFER_NODATA_HIGH) | |
203 { | |
204 ret = 1; | |
205 } | |
206 } | |
207 else | |
208 { | |
209 if(rxBufferUart6[index] == BUFFER_NODATA_LOW) | |
210 { | |
211 ret = 1; | |
212 } | |
213 } | |
214 | |
215 return ret; | |
216 } | |
217 | |
218 void UART6_StartDMA_Receiption() | |
219 { | |
220 if(dmaRx6Active == 0) | |
221 { | |
222 if(((rx6WriteIndex / CHUNK_SIZE) != (rx6ReadIndex / CHUNK_SIZE)) || ((isEndIndication6(rx6WriteIndex)) && (isEndIndication6(rx6WriteIndex + 1)))) /* start next transfer if we did not catch up with read index */ | |
223 { | |
224 if(HAL_OK == HAL_UART_Receive_DMA (&huart6, &rxBufferUart6[rx6WriteIndex], CHUNK_SIZE)) | |
225 { | |
226 dmaRx6Active = 1; | |
227 } | |
228 } | |
229 } | |
230 } | |
231 | |
232 | |
233 | |
234 void UART6_RxCpltCallback(UART_HandleTypeDef *huart) | |
235 { | |
236 if(huart == &huart6) | |
237 { | |
238 dmaRx6Active = 0; | |
239 rx6WriteIndex+=CHUNK_SIZE; | |
240 if(rx6WriteIndex >= CHUNK_SIZE * CHUNKS_PER_BUFFER) | |
241 { | |
242 rx6WriteIndex = 0; | |
243 } | |
244 UART6_StartDMA_Receiption(); | |
245 } | |
246 } | |
247 void UART6_TxCpltCallback(UART_HandleTypeDef *huart) | |
248 { | |
249 if(huart == &huart6) | |
250 { | |
251 dmaTx6Active = 0; | |
252 UART6_WriteData(); | |
253 if(tx6BufferQueLen) | |
254 { | |
255 memcpy(tx6Buffer, tx6BufferQue, tx6BufferQueLen); | |
256 HAL_UART_Transmit_DMA(&huart6,tx6Buffer,tx6BufferQueLen); | |
257 dmaTx6Active = 1; | |
258 tx6BufferQueLen = 0; | |
259 } | |
260 } | |
261 } | |
262 | |
263 void UART6_ReadData() | |
264 { | |
265 uint8_t localRX = rx6ReadIndex; | |
266 uint8_t futureIndex = rx6ReadIndex + 1; | |
267 uint8_t moreData = 0; | |
268 | |
269 if(futureIndex >= CHUNK_SIZE * CHUNKS_PER_BUFFER) | |
270 { | |
271 futureIndex = 0; | |
272 } | |
273 | |
274 if((!isEndIndication6(localRX)) || (!isEndIndication6(futureIndex))) do | |
275 { | |
276 while((!isEndIndication6(localRX)) || (moreData)) | |
277 { | |
278 moreData = 0; | |
279 UART6_Gnss_ProcessData(rxBufferUart6[localRX]); | |
280 | |
281 if(localRX % 2) | |
282 { | |
283 rxBufferUart6[localRX] = BUFFER_NODATA_HIGH; | |
284 } | |
285 else | |
286 { | |
287 rxBufferUart6[localRX] = BUFFER_NODATA_LOW; | |
288 } | |
289 | |
290 localRX++; | |
291 rx6ReadIndex++; | |
292 if(rx6ReadIndex >= CHUNK_SIZE * CHUNKS_PER_BUFFER) | |
293 { | |
294 localRX = 0; | |
295 rx6ReadIndex = 0; | |
296 } | |
297 futureIndex++; | |
298 if(futureIndex >= CHUNK_SIZE * CHUNKS_PER_BUFFER) | |
299 { | |
300 futureIndex = 0; | |
301 } | |
302 } | |
303 if(!isEndIndication6(futureIndex)) | |
304 { | |
305 moreData = 1; | |
306 } | |
307 } while(moreData); | |
308 } | |
309 | |
310 void UART6_WriteData(void) | |
311 { | |
312 if(huart6.hdmatx->State == HAL_DMA_STATE_READY) | |
313 { | |
314 huart6.gState = HAL_UART_STATE_READY; | |
315 dmaTx6Active = 0; | |
316 } | |
317 if(huart6.hdmarx->State == HAL_DMA_STATE_READY) | |
318 { | |
319 huart6.RxState = HAL_UART_STATE_READY; | |
320 dmaRx6Active = 0; | |
321 } | |
322 } | |
323 | |
324 void UART6_Gnss_SendCmd(uint8_t GnssCmd) | |
325 { | |
326 const uint8_t* pData; | |
327 uint8_t txLength = 0; | |
328 | |
329 switch (GnssCmd) | |
330 { | |
331 case GNSSCMD_LOADCONF_0: pData = configUBX; | |
332 txLength = sizeof(configUBX) / sizeof(uint8_t); | |
333 break; | |
334 case GNSSCMD_LOADCONF_1: pData = setNMEA410; | |
335 txLength = sizeof(setNMEA410) / sizeof(uint8_t); | |
336 break; | |
337 case GNSSCMD_LOADCONF_2: pData = setGNSS; | |
338 txLength = sizeof(setGNSS) / sizeof(uint8_t); | |
339 break; | |
340 case GNSSCMD_GET_PVT_DATA: pData = getPVTData; | |
341 txLength = sizeof(getPVTData) / sizeof(uint8_t); | |
342 break; | |
343 case GNSSCMD_GET_NAV_DATA: pData = getNavigatorData; | |
344 txLength = sizeof(getNavigatorData) / sizeof(uint8_t); | |
345 break; | |
346 | |
347 default: | |
348 break; | |
349 } | |
350 if(txLength != 0) | |
351 { | |
352 UART6_SendCmdUbx(pData, txLength); | |
353 } | |
354 } | |
355 | |
356 void UART6_Gnss_Control(void) | |
357 { | |
358 static uint32_t warmupTick = 0; | |
359 | |
360 switch (gnssState) | |
361 { | |
362 case UART_GNSS_INIT: gnssState = UART_GNSS_WARMUP; | |
363 warmupTick = HAL_GetTick(); | |
364 UART_clearRxBuffer(); | |
365 break; | |
366 case UART_GNSS_WARMUP: if(time_elapsed_ms(warmupTick,HAL_GetTick()) > 1000) | |
367 { | |
368 gnssState = UART_GNSS_LOADCONF_0; | |
369 } | |
370 break; | |
371 case UART_GNSS_LOADCONF_0: UART6_Gnss_SendCmd(GNSSCMD_LOADCONF_0); | |
372 gnssState = UART_GNSS_LOADCONF_1; | |
373 rxState = GNSSRX_DETECT_ACK_0; | |
374 break; | |
375 case UART_GNSS_LOADCONF_1: UART6_Gnss_SendCmd(GNSSCMD_LOADCONF_1); | |
376 gnssState = UART_GNSS_LOADCONF_2; | |
377 rxState = GNSSRX_DETECT_ACK_0; | |
378 break; | |
379 case UART_GNSS_LOADCONF_2: UART6_Gnss_SendCmd(GNSSCMD_LOADCONF_2); | |
380 gnssState = UART_GNSS_IDLE; | |
381 rxState = GNSSRX_DETECT_ACK_0; | |
382 break; | |
383 case UART_GNSS_IDLE: UART6_Gnss_SendCmd(GNSSCMD_GET_PVT_DATA); | |
384 gnssState = UART_GNSS_GET_PVT; | |
385 rxState = GNSSRX_DETECT_HEADER_0; | |
386 break; | |
387 default: | |
388 break; | |
389 } | |
390 } | |
391 | |
392 void UART6_Gnss_ProcessData(uint8_t data) | |
393 { | |
394 GNSS_Handle.uartWorkingBuffer[writeIndex++] = data; | |
395 switch(rxState) | |
396 { | |
397 case GNSSRX_DETECT_ACK_0: | |
398 case GNSSRX_DETECT_HEADER_0: if(data == 0xB5) | |
399 { | |
400 writeIndex = 0; | |
401 memset(GNSS_Handle.uartWorkingBuffer,0, sizeof(GNSS_Handle.uartWorkingBuffer)); | |
402 GNSS_Handle.uartWorkingBuffer[writeIndex++] = data; | |
403 rxState++; | |
404 } | |
405 break; | |
406 case GNSSRX_DETECT_ACK_1: | |
407 case GNSSRX_DETECT_HEADER_1: if(data == 0x62) | |
408 { | |
409 rxState++; | |
410 } | |
411 else | |
412 { | |
413 rxState = GNSSRX_DETECT_HEADER_0; | |
414 } | |
415 break; | |
416 case GNSSRX_DETECT_ACK_2: if(data == 0x05) | |
417 { | |
418 rxState++; | |
419 } | |
420 else | |
421 { | |
422 rxState = GNSSRX_DETECT_HEADER_0; | |
423 } | |
424 break; | |
425 case GNSSRX_DETECT_ACK_3: if((data == 0x01) || (data == 0x00)) | |
426 { | |
427 GnssConnected = 1; | |
428 rxState = GNSSRX_READY; | |
429 } | |
430 else | |
431 { | |
432 rxState = GNSSRX_DETECT_HEADER_0; | |
433 } | |
434 break; | |
435 case GNSSRX_DETECT_HEADER_2: if(data == 0x01) | |
436 { | |
437 rxState++; | |
438 } | |
439 else | |
440 { | |
441 rxState = GNSSRX_DETECT_HEADER_0; | |
442 } | |
443 break; | |
444 case GNSSRX_DETECT_HEADER_3: | |
445 switch(data) | |
446 { | |
447 case 0x21: rxState = GNSSRX_READ_NAV_DATA; | |
448 dataToRead = 20; | |
449 break; | |
450 case 0x07: rxState = GNSSRX_READ_PVT_DATA; | |
451 dataToRead = 92; | |
452 break; | |
453 case 0x02: rxState = GNSSRX_READ_POSLLH_DATA; | |
454 break; | |
455 default: rxState = GNSSRX_DETECT_HEADER_0; | |
456 break; | |
457 } | |
458 break; | |
459 case GNSSRX_READ_NAV_DATA: | |
460 case GNSSRX_READ_PVT_DATA: | |
461 case GNSSRX_READ_POSLLH_DATA: if(dataToRead > 0) | |
462 { | |
463 dataToRead--; | |
464 } | |
465 else | |
466 { | |
467 switch(rxState) | |
468 { | |
469 case GNSSRX_READ_NAV_DATA: GNSS_ParseNavigatorData(&GNSS_Handle); | |
470 break; | |
471 case GNSSRX_READ_PVT_DATA: GNSS_ParsePVTData(&GNSS_Handle); | |
472 break; | |
473 case GNSSRX_READ_POSLLH_DATA: GNSS_ParsePOSLLHData(&GNSS_Handle); | |
474 break; | |
475 default: rxState = GNSSRX_DETECT_HEADER_0; | |
476 break; | |
477 } | |
478 rxState = GNSSRX_DETECT_HEADER_0; | |
479 gnssState = UART_GNSS_IDLE; | |
480 } | |
481 break; | |
482 default: rxState = GNSSRX_READY; | |
483 break; | |
484 } | |
485 } | |
486 | |
487 | |
488 void UART6_HandleUART() | |
489 { | |
490 static uint8_t retryRequest = 0; | |
491 static uint32_t lastRequestTick = 0; | |
492 static uint32_t TriggerTick = 0; | |
493 static uint8_t timeToTrigger = 0; | |
494 uint32_t tick = HAL_GetTick(); | |
495 | |
496 if(gnssState != UART_GNSS_INIT) | |
497 { | |
498 UART6_ReadData(); | |
499 UART6_WriteData(); | |
500 } | |
501 if(gnssState == UART_GNSS_INIT) | |
502 { | |
503 lastRequestTick = tick; | |
504 TriggerTick = tick - 10; /* just to make sure control is triggered */ | |
505 timeToTrigger = 1; | |
506 retryRequest = 0; | |
507 } | |
508 else if(((retryRequest == 0) /* timeout or error */ | |
509 && (((time_elapsed_ms(lastRequestTick,tick) > (TIMEOUT_SENSOR_ANSWER)) && (gnssState != UART_GNSS_IDLE)) /* retry if no answer after half request interval */ | |
510 || (gnssState == UART_GNSS_ERROR)))) | |
511 { | |
512 /* The channel switch will cause the sensor to respond with an error message. */ | |
513 /* The sensor needs ~30ms to recover before he is ready to receive the next command => transmission delay needed */ | |
514 | |
515 TriggerTick = tick; | |
516 timeToTrigger = COMMAND_TX_DELAY; | |
517 retryRequest = 1; | |
518 } | |
519 | |
520 else if(time_elapsed_ms(lastRequestTick,tick) > 1000) /* switch sensor and / or trigger next request */ | |
521 { | |
522 lastRequestTick = tick; | |
523 TriggerTick = tick; | |
524 retryRequest = 0; | |
525 timeToTrigger = 1; | |
526 | |
527 if((gnssState == UART_GNSS_GET_PVT)) /* timeout */ | |
528 { | |
529 gnssState = UART_GNSS_IDLE; | |
530 } | |
531 timeToTrigger = 1; | |
532 } | |
533 if((timeToTrigger != 0) && (time_elapsed_ms(TriggerTick,tick) > timeToTrigger)) | |
534 { | |
535 timeToTrigger = 0; | |
536 UART6_Gnss_Control(); | |
537 } | |
538 | |
539 } | |
540 | |
541 | |
542 /************************ (C) COPYRIGHT heinrichs weikamp *****END OF FILE****/ |