-
Notifications
You must be signed in to change notification settings - Fork 6
/
luos_hal.c
986 lines (910 loc) · 32.8 KB
/
luos_hal.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
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
/******************************************************************************
* @file luosHAL
* @brief Luos Hardware Abstration Layer. Describe Low layer fonction
* @MCU Family STM32G4
* @author Luos
* @version 0.0.0
******************************************************************************/
#include "luos_hal.h"
#include <stdbool.h>
#include <string.h>
#include "reception.h"
#include "context.h"
// MCU dependencies this HAL is for family STM32G4 you can find
// the HAL stm32cubeg4 on ST web site
#include "stm32g4xx_ll_usart.h"
#include "stm32g4xx_ll_gpio.h"
#include "stm32g4xx_ll_tim.h"
#include "stm32g4xx_ll_exti.h"
#include "stm32g4xx_ll_dma.h"
#include "stm32g4xx_ll_system.h"
/*******************************************************************************
* Definitions
******************************************************************************/
#define DEFAULT_TIMEOUT 20
#define TIMEOUT_ACK DEFAULT_TIMEOUT / 4
/*******************************************************************************
* Variables
******************************************************************************/
#if (USE_CRC_HW == 1)
CRC_HandleTypeDef hcrc;
#endif
GPIO_InitTypeDef GPIO_InitStruct = {0};
uint32_t Timer_Prescaler = (MCUFREQ / DEFAULTBAUDRATE) / TIMERDIV; //(freq MCU/freq timer)/divider timer clock source
typedef struct
{
uint16_t Pin;
GPIO_TypeDef *Port;
uint8_t IRQ;
} Port_t;
Port_t PTP[NBR_PORT];
volatile uint16_t data_size_to_transmit = 0;
volatile uint8_t *tx_data = 0;
// timestamp variable
static ll_timestamp_t ll_timestamp;
/*******************************************************************************
* Function
******************************************************************************/
static void LuosHAL_SystickInit(void);
static void LuosHAL_FlashInit(void);
static void LuosHAL_CRCInit(void);
static void LuosHAL_TimeoutInit(void);
static void LuosHAL_GPIOInit(void);
static void LuosHAL_FlashEraseLuosMemoryInfo(void);
static void LuosHAL_RegisterPTP(void);
/////////////////////////Luos Library Needed function///////////////////////////
/******************************************************************************
* @brief Luos HAL general initialisation
* @param None
* @return None
******************************************************************************/
void LuosHAL_Init(void)
{
// Systick Initialization
LuosHAL_SystickInit();
// IO Initialization
LuosHAL_GPIOInit();
// Flash Initialization
LuosHAL_FlashInit();
// CRC Initialization
LuosHAL_CRCInit();
// Com Initialization
LuosHAL_ComInit(DEFAULTBAUDRATE);
// start timestamp
LuosHAL_StartTimestamp();
}
/******************************************************************************
* @brief Luos HAL general disable IRQ
* @param None
* @return None
******************************************************************************/
void LuosHAL_SetIrqState(uint8_t Enable)
{
if (Enable == true)
{
__enable_irq();
}
else
{
__disable_irq();
}
}
/******************************************************************************
* @brief Luos HAL general systick tick at 1ms initialize
* @param None
* @return tick Counter
******************************************************************************/
static void LuosHAL_SystickInit(void)
{
}
/******************************************************************************
* @brief Luos HAL general systick tick at 1ms
* @param None
* @return tick Counter
******************************************************************************/
uint32_t LuosHAL_GetSystick(void)
{
return HAL_GetTick();
}
/******************************************************************************
* @brief Luos HAL Initialize Generale communication inter node
* @param Select a baudrate for the Com
* @return none
******************************************************************************/
void LuosHAL_ComInit(uint32_t Baudrate)
{
LUOS_COM_CLOCK_ENABLE();
LL_USART_InitTypeDef USART_InitStruct;
// Initialise USART1
LL_USART_Disable(LUOS_COM);
USART_InitStruct.BaudRate = Baudrate;
USART_InitStruct.DataWidth = LL_USART_DATAWIDTH_8B;
USART_InitStruct.StopBits = LL_USART_STOPBITS_1;
USART_InitStruct.Parity = LL_USART_PARITY_NONE;
USART_InitStruct.TransferDirection = LL_USART_DIRECTION_TX_RX;
USART_InitStruct.HardwareFlowControl = LL_USART_HWCONTROL_NONE;
USART_InitStruct.OverSampling = LL_USART_OVERSAMPLING_16;
while (LL_USART_Init(LUOS_COM, &USART_InitStruct) != SUCCESS)
;
LL_USART_Enable(LUOS_COM);
// Enable Reception interrupt
LL_USART_EnableIT_RXNE(LUOS_COM);
HAL_NVIC_EnableIRQ(LUOS_COM_IRQ);
HAL_NVIC_SetPriority(LUOS_COM_IRQ, 0, 1);
// Timeout Initialization
Timer_Prescaler = (MCUFREQ / Baudrate) / TIMERDIV;
LuosHAL_TimeoutInit();
#ifndef USE_TX_IT
LUOS_DMA_CLOCK_ENABLE();
LL_DMA_SetPeriphRequest(LUOS_DMA, LUOS_DMA_CHANNEL, LUOS_DMA_REQUEST);
LL_DMA_SetDataTransferDirection(LUOS_DMA, LUOS_DMA_CHANNEL, LL_DMA_DIRECTION_MEMORY_TO_PERIPH);
LL_DMA_SetChannelPriorityLevel(LUOS_DMA, LUOS_DMA_CHANNEL, LL_DMA_PRIORITY_LOW);
LL_DMA_SetMode(LUOS_DMA, LUOS_DMA_CHANNEL, LL_DMA_MODE_NORMAL);
LL_DMA_SetPeriphIncMode(LUOS_DMA, LUOS_DMA_CHANNEL, LL_DMA_PERIPH_NOINCREMENT);
LL_DMA_SetMemoryIncMode(LUOS_DMA, LUOS_DMA_CHANNEL, LL_DMA_MEMORY_INCREMENT);
LL_DMA_SetPeriphSize(LUOS_DMA, LUOS_DMA_CHANNEL, LL_DMA_PDATAALIGN_BYTE);
LL_DMA_SetMemorySize(LUOS_DMA, LUOS_DMA_CHANNEL, LL_DMA_MDATAALIGN_BYTE);
LL_DMA_SetPeriphAddress(LUOS_DMA, LUOS_DMA_CHANNEL, (uint32_t)&LUOS_COM->TDR);
#endif
}
/******************************************************************************
* @brief Tx enable/disable relative to com
* @param None
* @return None
******************************************************************************/
void LuosHAL_SetTxState(uint8_t Enable)
{
if (Enable == true)
{
// Put Tx in push pull
LL_GPIO_SetPinOutputType(COM_TX_PORT, COM_TX_PIN, LL_GPIO_OUTPUT_PUSHPULL);
if ((TX_EN_PIN != DISABLE) || (TX_EN_PORT != DISABLE))
{
LL_GPIO_SetOutputPin(TX_EN_PORT, TX_EN_PIN);
}
}
else
{
// Put Tx in open drain
LL_GPIO_SetPinOutputType(COM_TX_PORT, COM_TX_PIN, LL_GPIO_OUTPUT_OPENDRAIN);
if ((TX_EN_PIN != DISABLE) || (TX_EN_PORT != DISABLE))
{
LL_GPIO_ResetOutputPin(TX_EN_PORT, TX_EN_PIN);
}
#ifdef USE_TX_IT
// Stop current transmit operation
data_size_to_transmit = 0;
// Disable Transmission empty buffer interrupt
LL_USART_DisableIT_TXE(LUOS_COM);
#else
LL_USART_DisableDMAReq_TX(LUOS_COM);
LL_DMA_DisableChannel(LUOS_DMA, LUOS_DMA_CHANNEL);
#endif
// Disable Transmission complete interrupt
LL_USART_DisableIT_TC(LUOS_COM);
}
}
/******************************************************************************
* @brief Rx enable/disable relative to com
* @param
* @return
******************************************************************************/
void LuosHAL_SetRxState(uint8_t Enable)
{
if (Enable == true)
{
LL_USART_RequestRxDataFlush(LUOS_COM); // Clear data register
LL_USART_EnableIT_RXNE(LUOS_COM); // Enable Rx IT
}
else
{
LL_USART_DisableIT_RXNE(LUOS_COM); // Disable Rx IT
}
}
/******************************************************************************
* @brief Process data send or receive
* @param None
* @return None
******************************************************************************/
void LUOS_COM_IRQHANDLER()
{
// Reset timeout to it's default value
LuosHAL_ResetTimeout(DEFAULT_TIMEOUT);
// reception management
if ((LL_USART_IsActiveFlag_RXNE(LUOS_COM) != RESET) && (LL_USART_IsEnabledIT_RXNE(LUOS_COM) != RESET))
{
// We receive a byte
uint8_t data = LL_USART_ReceiveData8(LUOS_COM);
ctx.rx.callback(&data); // send reception byte to state machine
if (data_size_to_transmit == 0)
{
LUOS_COM->ICR = 0xFFFFFFFF;
return;
}
}
else if (LL_USART_IsActiveFlag_FE(LUOS_COM) != RESET)
{
// Framing ERROR
ctx.rx.status.rx_framing_error = true;
}
// Transmission management
if ((LL_USART_IsActiveFlag_TC(LUOS_COM) != RESET) && (LL_USART_IsEnabledIT_TC(LUOS_COM) != RESET))
{
// Transmission complete
// Switch to reception mode
LuosHAL_SetTxState(false);
LuosHAL_SetRxState(true);
// Disable transmission complete IRQ
LL_USART_ClearFlag_TC(LUOS_COM);
LL_USART_DisableIT_TC(LUOS_COM);
}
#ifdef USE_TX_IT
else if ((LL_USART_IsActiveFlag_TXE(LUOS_COM) != RESET) && (LL_USART_IsEnabledIT_TXE(LUOS_COM) != RESET))
{
// Transmit buffer empty (this is a software DMA)
data_size_to_transmit--;
LL_USART_TransmitData8(LUOS_COM, *(tx_data++));
if (data_size_to_transmit == 0)
{
// Transmission complete, stop loading data and watch for the end of transmission
// Disable Transmission empty buffer interrupt
LL_USART_DisableIT_TXE(LUOS_COM);
// Enable Transmission complete interrupt
LL_USART_EnableIT_TC(LUOS_COM);
}
}
#endif
LUOS_COM->ICR = 0xFFFFFFFF;
}
/******************************************************************************
* @brief Process data transmit
* @param None
* @return None
******************************************************************************/
void LuosHAL_ComTransmit(uint8_t *data, uint16_t size)
{
while (LL_USART_IsActiveFlag_TXE(LUOS_COM) == RESET)
;
// Disable RX detec pin if needed
// Reduce size by one because we send one directly
data_size_to_transmit = size - 1;
if (size > 1)
{
// Start the data buffer transmission
// **** NO DMA
// Copy the data pointer globally alowing to keep it and run the transmission.
tx_data = data;
#ifdef USE_TX_IT
// Send the first byte
LL_USART_TransmitData8(LUOS_COM, *(tx_data++));
// Enable Transmission empty buffer interrupt to transmit next datas
LL_USART_EnableIT_TXE(LUOS_COM);
// Disable Transmission complete interrupt
LL_USART_DisableIT_TC(LUOS_COM);
#else
data_size_to_transmit = 0; // to not check IT TC during collision
// Disable DMA to load new length to be tranmitted
LL_DMA_DisableChannel(LUOS_DMA, LUOS_DMA_CHANNEL);
// configure address to be transmitted by DMA
LL_DMA_SetMemoryAddress(LUOS_DMA, LUOS_DMA_CHANNEL, (uint32_t)data);
// set length to be tranmitted
LL_DMA_SetDataLength(LUOS_DMA, LUOS_DMA_CHANNEL, size);
// set request DMA
LL_USART_EnableDMAReq_TX(LUOS_COM);
// Enable TX
LuosHAL_SetTxState(true);
// Enable DMA again
LL_DMA_EnableChannel(LUOS_DMA, LUOS_DMA_CHANNEL);
// enable transmit complete
LL_USART_EnableIT_TC(LUOS_COM);
#endif
}
else
{
// Wait before send ack
// This is a patch du to difference MCU frequency
while (LL_TIM_GetCounter(LUOS_TIMER) < TIMEOUT_ACK)
;
// Enable TX
LuosHAL_SetTxState(true);
// Transmit the only byte we have
LL_USART_TransmitData8(LUOS_COM, *data);
// Enable Transmission complete interrupt because we only have one.
LL_USART_EnableIT_TC(LUOS_COM);
}
LuosHAL_ResetTimeout(DEFAULT_TIMEOUT);
}
/******************************************************************************
* @brief set state of Txlock detection pin
* @param None
* @return Lock status
******************************************************************************/
void LuosHAL_SetRxDetecPin(uint8_t Enable)
{
if (TX_LOCK_DETECT_IRQ != DISABLE)
{
__HAL_GPIO_EXTI_CLEAR_IT(TX_LOCK_DETECT_IRQ);
if (Enable == true)
{
EXTI->IMR1 |= TX_LOCK_DETECT_PIN;
}
else
{
EXTI->IMR1 &= ~TX_LOCK_DETECT_PIN;
}
}
}
/******************************************************************************
* @brief get Lock Com transmit status this is the HW that can generate lock TX
* @param None
* @return Lock status
******************************************************************************/
uint8_t LuosHAL_GetTxLockState(void)
{
uint8_t result = false;
#ifdef USART_ISR_BUSY
if (LL_USART_IsActiveFlag_BUSY(LUOS_COM) == true)
{
LuosHAL_ResetTimeout(DEFAULT_TIMEOUT);
result = true;
}
#else
if ((TX_LOCK_DETECT_PIN != DISABLE) && (TX_LOCK_DETECT_PORT != DISABLE))
{
if (HAL_GPIO_ReadPin(TX_LOCK_DETECT_PORT, TX_LOCK_DETECT_PIN) == GPIO_PIN_RESET)
{
result = true;
}
if (TX_LOCK_DETECT_IRQ == DISABLE)
{
if (result == true)
{
LuosHAL_ResetTimeout(DEFAULT_TIMEOUT);
}
}
}
#endif
return result;
}
/******************************************************************************
* @brief Luos Timeout initialisation
* @param None
* @return None
******************************************************************************/
static void LuosHAL_TimeoutInit(void)
{
LL_TIM_InitTypeDef TimerInit = {0};
// initialize clock
LUOS_TIMER_CLOCK_ENABLE();
TimerInit.Autoreload = DEFAULT_TIMEOUT;
TimerInit.ClockDivision = LL_TIM_CLOCKDIVISION_DIV1;
TimerInit.CounterMode = LL_TIM_COUNTERMODE_UP;
TimerInit.Prescaler = Timer_Prescaler - 1;
TimerInit.RepetitionCounter = 0;
while (LL_TIM_Init(LUOS_TIMER, &TimerInit) != SUCCESS)
;
LL_TIM_EnableIT_UPDATE(LUOS_TIMER);
HAL_NVIC_SetPriority(LUOS_TIMER_IRQ, 0, 2);
HAL_NVIC_EnableIRQ(LUOS_TIMER_IRQ);
}
/******************************************************************************
* @brief Luos Timeout communication
* @param None
* @return None
******************************************************************************/
void LuosHAL_ResetTimeout(uint16_t nbrbit)
{
LL_TIM_DisableCounter(LUOS_TIMER);
NVIC_ClearPendingIRQ(LUOS_TIMER_IRQ); // Clear IT pending NVIC
LL_TIM_ClearFlag_UPDATE(LUOS_TIMER);
LL_TIM_SetCounter(LUOS_TIMER, 0); // Reset counter
if (nbrbit != 0)
{
LL_TIM_SetAutoReload(LUOS_TIMER, nbrbit); // reload value
LL_TIM_EnableCounter(LUOS_TIMER);
}
}
/******************************************************************************
* @brief Luos Timeout communication
* @param None
* @return None
******************************************************************************/
void LUOS_TIMER_IRQHANDLER()
{
if (LL_TIM_IsActiveFlag_UPDATE(LUOS_TIMER) != RESET)
{
LL_TIM_ClearFlag_UPDATE(LUOS_TIMER);
LL_TIM_DisableCounter(LUOS_TIMER);
if ((ctx.tx.lock == true) && (LuosHAL_GetTxLockState() == false))
{
// Enable RX detection pin if needed
LuosHAL_SetTxState(false);
LuosHAL_SetRxState(true);
Recep_Timeout();
}
}
}
/******************************************************************************
* @brief Luos GetTimestamp
* @param None
* @return uint64_t
******************************************************************************/
uint64_t LuosHAL_GetTimestamp(void)
{
ll_timestamp.lower_timestamp = (SysTick->LOAD - SysTick->VAL) * (1000000000 / MCUFREQ);
ll_timestamp.higher_timestamp = (uint64_t)(LuosHAL_GetSystick() - ll_timestamp.start_offset);
return ll_timestamp.higher_timestamp * 1000000 + (uint64_t)ll_timestamp.lower_timestamp;
}
/******************************************************************************
* @brief Luos start Timestamp
* @param None
* @return None
******************************************************************************/
void LuosHAL_StartTimestamp(void)
{
ll_timestamp.start_offset = LuosHAL_GetSystick();
}
/******************************************************************************
* @brief Luos stop Timestamp
* @param None
* @return None
******************************************************************************/
void LuosHAL_StopTimestamp(void)
{
ll_timestamp.lower_timestamp = 0;
ll_timestamp.higher_timestamp = 0;
ll_timestamp.start_offset = 0;
}
/******************************************************************************
* @brief Initialisation GPIO
* @param None
* @return None
******************************************************************************/
static void LuosHAL_GPIOInit(void)
{
// Activate Clock for PIN choosen in luosHAL
PORT_CLOCK_ENABLE();
if ((RX_EN_PIN != DISABLE) || (RX_EN_PORT != DISABLE))
{
/*Configure GPIO pins : RxEN_Pin */
GPIO_InitStruct.Pin = RX_EN_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(RX_EN_PORT, &GPIO_InitStruct);
}
if ((TX_EN_PIN != DISABLE) || (TX_EN_PORT != DISABLE))
{
/*Configure GPIO pins : TxEN_Pin */
GPIO_InitStruct.Pin = TX_EN_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(TX_EN_PORT, &GPIO_InitStruct);
}
/*Configure GPIO pin : TxPin */
GPIO_InitStruct.Pin = COM_TX_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
GPIO_InitStruct.Alternate = COM_TX_AF;
HAL_GPIO_Init(COM_TX_PORT, &GPIO_InitStruct);
/*Configure GPIO pin : RxPin */
GPIO_InitStruct.Pin = COM_RX_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
GPIO_InitStruct.Alternate = COM_RX_AF;
HAL_GPIO_Init(COM_RX_PORT, &GPIO_InitStruct);
// configure PTP
LuosHAL_RegisterPTP();
for (uint8_t i = 0; i < NBR_PORT; i++) /*Configure GPIO pins : PTP_Pin */
{
GPIO_InitStruct.Pin = PTP[i].Pin;
GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING;
GPIO_InitStruct.Pull = GPIO_PULLDOWN;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(PTP[i].Port, &GPIO_InitStruct);
// Setup PTP lines
LuosHAL_SetPTPDefaultState(i);
// activate IT for PTP
HAL_NVIC_SetPriority(PTP[i].IRQ, 1, 0);
HAL_NVIC_EnableIRQ(PTP[i].IRQ);
}
if ((TX_LOCK_DETECT_PIN != DISABLE) || (TX_LOCK_DETECT_PORT != DISABLE))
{
/*Configure GPIO pins : TX_LOCK_DETECT_Pin */
GPIO_InitStruct.Pin = TX_LOCK_DETECT_PIN;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
if (TX_LOCK_DETECT_IRQ != DISABLE)
{
GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING;
HAL_NVIC_SetPriority(TX_LOCK_DETECT_IRQ, 1, 0);
HAL_NVIC_EnableIRQ(TX_LOCK_DETECT_IRQ);
}
HAL_GPIO_Init(TX_LOCK_DETECT_PORT, &GPIO_InitStruct);
}
}
/******************************************************************************
* @brief Register PTP
* @param void
* @return None
******************************************************************************/
static void LuosHAL_RegisterPTP(void)
{
#if (NBR_PORT >= 1)
PTP[0].Pin = PTPA_PIN;
PTP[0].Port = PTPA_PORT;
PTP[0].IRQ = PTPA_IRQ;
#endif
#if (NBR_PORT >= 2)
PTP[1].Pin = PTPB_PIN;
PTP[1].Port = PTPB_PORT;
PTP[1].IRQ = PTPB_IRQ;
#endif
#if (NBR_PORT >= 3)
PTP[2].Pin = PTPC_PIN;
PTP[2].Port = PTPC_PORT;
PTP[2].IRQ = PTPC_IRQ;
#endif
#if (NBR_PORT >= 4)
PTP[3].Pin = PTPD_PIN;
PTP[3].Port = PTPD_PORT;
PTP[3].IRQ = PTPD_IRQ;
#endif
}
/******************************************************************************
* @brief callback for GPIO IT
* @param GPIO IT line
* @return None
******************************************************************************/
void PINOUT_IRQHANDLER(uint16_t GPIO_Pin)
{
////Process for Tx Lock Detec
if ((GPIO_Pin == TX_LOCK_DETECT_PIN) && (TX_LOCK_DETECT_IRQ != DISABLE))
{
ctx.tx.lock = true;
LuosHAL_ResetTimeout(DEFAULT_TIMEOUT);
EXTI->IMR1 &= ~TX_LOCK_DETECT_PIN;
}
else
{
for (uint8_t i = 0; i < NBR_PORT; i++)
{
if (GPIO_Pin == PTP[i].Pin)
{
PortMng_PtpHandler(i);
break;
}
}
}
}
/******************************************************************************
* @brief Set PTP for Detection on branch
* @param PTP branch
* @return None
******************************************************************************/
void LuosHAL_SetPTPDefaultState(uint8_t PTPNbr)
{
__HAL_GPIO_EXTI_CLEAR_IT(PTP[PTPNbr].Pin);
// Pull Down / IT mode / Rising Edge
GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING;
GPIO_InitStruct.Pull = GPIO_PULLDOWN;
GPIO_InitStruct.Pin = PTP[PTPNbr].Pin;
HAL_GPIO_Init(PTP[PTPNbr].Port, &GPIO_InitStruct);
}
/******************************************************************************
* @brief Set PTP for reverse detection on branch
* @param PTP branch
* @return None
******************************************************************************/
void LuosHAL_SetPTPReverseState(uint8_t PTPNbr)
{
__HAL_GPIO_EXTI_CLEAR_IT(PTP[PTPNbr].Pin);
// Pull Down / IT mode / Falling Edge
GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING; // reverse the detection edge
GPIO_InitStruct.Pull = GPIO_PULLDOWN;
GPIO_InitStruct.Pin = PTP[PTPNbr].Pin;
HAL_GPIO_Init(PTP[PTPNbr].Port, &GPIO_InitStruct);
}
/******************************************************************************
* @brief Set PTP line
* @param PTP branch
* @return None
******************************************************************************/
void LuosHAL_PushPTP(uint8_t PTPNbr)
{
// Pull Down / Output mode
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; // Clean edge/state detection and set the PTP pin as output
GPIO_InitStruct.Pull = GPIO_PULLDOWN;
GPIO_InitStruct.Pin = PTP[PTPNbr].Pin;
HAL_GPIO_Init(PTP[PTPNbr].Port, &GPIO_InitStruct);
HAL_GPIO_WritePin(PTP[PTPNbr].Port, PTP[PTPNbr].Pin, GPIO_PIN_SET);
}
/******************************************************************************
* @brief Get PTP line
* @param PTP branch
* @return Line state
******************************************************************************/
uint8_t LuosHAL_GetPTPState(uint8_t PTPNbr)
{
// Pull Down / Input mode
return (HAL_GPIO_ReadPin(PTP[PTPNbr].Port, PTP[PTPNbr].Pin));
}
/******************************************************************************
* @brief Initialize CRC Process
* @param None
* @return None
******************************************************************************/
static void LuosHAL_CRCInit(void)
{
#if (USE_CRC_HW == 1)
__HAL_RCC_CRC_CLK_ENABLE();
hcrc.Instance = CRC;
hcrc.Init.DefaultPolynomialUse = DEFAULT_POLYNOMIAL_DISABLE;
hcrc.Init.DefaultInitValueUse = DEFAULT_INIT_VALUE_ENABLE;
hcrc.Init.GeneratingPolynomial = 7;
hcrc.Init.CRCLength = CRC_POLYLENGTH_16B;
hcrc.Init.InputDataInversionMode = CRC_INPUTDATA_INVERSION_NONE;
hcrc.Init.OutputDataInversionMode = CRC_OUTPUTDATA_INVERSION_DISABLE;
hcrc.InputDataFormat = CRC_INPUTDATA_FORMAT_BYTES;
if (HAL_CRC_Init(&hcrc) != HAL_OK)
{
while (1)
;
}
#endif
}
/******************************************************************************
* @brief Compute CRC
* @param None
* @return None
******************************************************************************/
void LuosHAL_ComputeCRC(uint8_t *data, uint8_t *crc)
{
#if (USE_CRC_HW == 1)
hcrc.Instance->INIT = *(uint16_t *)crc;
__HAL_CRC_DR_RESET(&hcrc);
*(uint16_t *)crc = (uint16_t)HAL_CRC_Accumulate(&hcrc, (uint32_t *)data, 1);
#else
uint16_t dbyte = *data;
*(uint16_t *)crc ^= dbyte << 8;
for (uint8_t j = 0; j < 8; ++j)
{
uint16_t mix = *(uint16_t *)crc & 0x8000;
*(uint16_t *)crc = (*(uint16_t *)crc << 1);
if (mix)
*(uint16_t *)crc = *(uint16_t *)crc ^ 0x0007;
}
#endif
}
/******************************************************************************
* @brief Flash Initialisation
* @param None
* @return None
******************************************************************************/
static void LuosHAL_FlashInit(void)
{
}
/******************************************************************************
* @brief Erase flash page where Luos keep permanente information
* @param None
* @return None
******************************************************************************/
static void LuosHAL_FlashEraseLuosMemoryInfo(void)
{
uint32_t page_error = 0;
FLASH_EraseInitTypeDef s_eraseinit;
s_eraseinit.TypeErase = FLASH_TYPEERASE_PAGES;
s_eraseinit.Page = NB_OF_PAGE - 1;
s_eraseinit.NbPages = 1;
// Erase Page
HAL_FLASH_Unlock();
HAL_FLASHEx_Erase(&s_eraseinit, &page_error);
HAL_FLASH_Lock();
}
/******************************************************************************
* @brief Write flash page where Luos keep permanente information
* @param Address page / size to write / pointer to data to write
* @return
******************************************************************************/
void LuosHAL_FlashWriteLuosMemoryInfo(uint32_t addr, uint16_t size, uint8_t *data)
{
// Before writing we have to erase the entire page
// to do that we have to backup current falues by copying it into RAM
uint8_t page_backup[PAGE_SIZE];
memcpy(page_backup, (void *)ADDRESS_ALIASES_FLASH, PAGE_SIZE);
// Now we can erase the page
LuosHAL_FlashEraseLuosMemoryInfo();
// Then add input data into backuped value on RAM
uint32_t RAMaddr = (addr - ADDRESS_ALIASES_FLASH);
memcpy(&page_backup[RAMaddr], data, size);
// and copy it into flash
HAL_FLASH_Unlock();
// ST hal flash program function write data by uint64_t raw data
for (uint32_t i = 0; i < PAGE_SIZE; i += sizeof(uint64_t))
{
while (HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, i + ADDRESS_ALIASES_FLASH, *(uint64_t *)(&page_backup[i])) != HAL_OK)
;
}
HAL_FLASH_Lock();
}
/******************************************************************************
* @brief read information from page where Luos keep permanente information
* @param Address info / size to read / pointer callback data to read
* @return
******************************************************************************/
void LuosHAL_FlashReadLuosMemoryInfo(uint32_t addr, uint16_t size, uint8_t *data)
{
memcpy(data, (void *)(addr), size);
}
/******************************************************************************
* @brief Set boot mode in shared flash memory
* @param
* @return
******************************************************************************/
void LuosHAL_SetMode(uint8_t mode)
{
uint32_t data_to_write = ~BOOT_MODE_MASK | (mode << BOOT_MODE_OFFSET);
uint32_t page_error = 0;
FLASH_EraseInitTypeDef s_eraseinit;
s_eraseinit.TypeErase = FLASH_TYPEERASE_PAGES;
s_eraseinit.Banks = FLASH_BANK_1;
s_eraseinit.Page = SHARED_MEMORY_ADDRESS / (uint32_t)PAGE_SIZE;
s_eraseinit.NbPages = 1;
// Unlock flash
HAL_FLASH_Unlock();
// Erase Page
HAL_FLASHEx_Erase(&s_eraseinit, &page_error);
// ST hal flash program function write data by uint64_t raw data
HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, (uint32_t)SHARED_MEMORY_ADDRESS, data_to_write);
// re-lock FLASH
HAL_FLASH_Lock();
}
/******************************************************************************
* @brief Save node ID in shared flash memory
* @param Address, node_id
* @return
******************************************************************************/
void LuosHAL_SaveNodeID(uint16_t node_id)
{
uint32_t page_error = 0;
FLASH_EraseInitTypeDef s_eraseinit;
uint32_t *p_start = (uint32_t *)SHARED_MEMORY_ADDRESS;
uint32_t saved_data = *p_start;
uint32_t data_tmp = ~NODE_ID_MASK | (node_id << NODE_ID_OFFSET);
uint32_t data_to_write = saved_data & data_tmp;
s_eraseinit.TypeErase = FLASH_TYPEERASE_PAGES;
s_eraseinit.Banks = FLASH_BANK_1;
s_eraseinit.Page = SHARED_MEMORY_ADDRESS / (uint32_t)PAGE_SIZE;
s_eraseinit.NbPages = 1;
// Unlock flash
HAL_FLASH_Unlock();
// Erase Page
HAL_FLASHEx_Erase(&s_eraseinit, &page_error);
// ST hal flash program function write data by uint64_t raw data
HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, (uint32_t)SHARED_MEMORY_ADDRESS, (uint64_t)data_to_write);
// re-lock FLASH
HAL_FLASH_Lock();
}
/******************************************************************************
* @brief software reboot the microprocessor
* @param
* @return
******************************************************************************/
void LuosHAL_Reboot(void)
{
// DeInit RCC and HAL
HAL_RCC_DeInit();
HAL_DeInit();
// reset systick
SysTick->CTRL = 0;
SysTick->LOAD = 0;
SysTick->VAL = 0;
// reset in bootloader mode
NVIC_SystemReset();
}
#ifdef BOOTLOADER_CONFIG
/******************************************************************************
* @brief DeInit Bootloader peripherals
* @param
* @return
******************************************************************************/
void LuosHAL_DeInit(void)
{
HAL_RCC_DeInit();
HAL_DeInit();
}
/******************************************************************************
* @brief DeInit Bootloader peripherals
* @param
* @return
******************************************************************************/
typedef void (*pFunction)(void); /*!< Function pointer definition */
void LuosHAL_JumpToApp(uint32_t app_addr)
{
uint32_t JumpAddress = *(__IO uint32_t *)(app_addr + 4);
pFunction Jump = (pFunction)JumpAddress;
__disable_irq();
SysTick->CTRL = 0;
SysTick->LOAD = 0;
SysTick->VAL = 0;
SCB->VTOR = app_addr;
__set_MSP(*(__IO uint32_t *)app_addr);
__enable_irq();
Jump();
}
/******************************************************************************
* @brief Return bootloader mode saved in flash
* @param
* @return
******************************************************************************/
uint8_t LuosHAL_GetMode(void)
{
uint32_t *p_start = (uint32_t *)SHARED_MEMORY_ADDRESS;
uint32_t data = (*p_start & BOOT_MODE_MASK) >> BOOT_MODE_OFFSET;
return (uint8_t)data;
}
/******************************************************************************
* @brief Get node id saved in flash memory
* @param Address
* @return node_id
******************************************************************************/
uint16_t LuosHAL_GetNodeID(void)
{
uint32_t *p_start = (uint32_t *)SHARED_MEMORY_ADDRESS;
uint32_t data = *p_start & NODE_ID_MASK;
uint16_t node_id = (uint16_t)(data >> NODE_ID_OFFSET);
return node_id;
}
/******************************************************************************
* @brief erase sectors in flash memory
* @param Address, size
* @return
******************************************************************************/
void LuosHAL_EraseMemory(uint32_t address, uint16_t size)
{
uint32_t nb_sectors_to_erase = 0;
uint32_t page_to_erase = address / (uint32_t)PAGE_SIZE;
// compute number of sectors to erase
nb_sectors_to_erase = ((uint32_t)(FLASH_BASE + END_ERASE_BOOTLOADER) - (uint32_t)address) / (uint32_t)PAGE_SIZE;
uint32_t page_error = 0;
FLASH_EraseInitTypeDef s_eraseinit;
s_eraseinit.TypeErase = FLASH_TYPEERASE_PAGES;
s_eraseinit.Banks = FLASH_BANK_1;
s_eraseinit.NbPages = 1;
int i = 0;
for (i = 0; i < nb_sectors_to_erase; i++)
{
s_eraseinit.Page = page_to_erase;
// Unlock flash
HAL_FLASH_Unlock();
// Erase Page
HAL_FLASHEx_Erase(&s_eraseinit, &page_error);
// re-lock FLASH
HAL_FLASH_Lock();
// update page to erase
page_to_erase += 1;
}
}
/******************************************************************************
* @brief Save binary data in shared flash memory
* @param Address, size, data[]
* @return
******************************************************************************/
void LuosHAL_ProgramFlash(uint32_t address, uint16_t size, uint8_t *data)
{
// Unlock flash
HAL_FLASH_Unlock();
// ST hal flash program function write data by uint64_t raw data
for (uint32_t i = 0; i < size; i += sizeof(uint64_t))
{
while (HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, i + address, *(uint64_t *)(&data[i])) != HAL_OK)
;
}
// re-lock FLASH
HAL_FLASH_Lock();
}
#endif