Skip to content

Commit 75544a7

Browse files
authored
Merge pull request ARMmbed#13565 from m-ecry/feature-stm32g4-can-support
Feature stm32g4 can support
2 parents fdab61d + 73493b9 commit 75544a7

File tree

4 files changed

+114
-8
lines changed

4 files changed

+114
-8
lines changed

targets/TARGET_STM/TARGET_STM32G4/TARGET_STM32G474xx/TARGET_NUCLEO_G474RE/system_clock.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,14 @@ uint8_t SetSysClock_PLL_HSE(uint8_t bypass)
105105
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
106106
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
107107
RCC_OscInitStruct.PLL.PLLM = RCC_PLLM_DIV6;
108+
//! 170MHz as a core frequency for FDCAN is not suitable for many frequencies,
109+
//! as it provides low accuracy. When no FDCAN is used, the full capacity of 170 MHz
110+
//! should be standard.
111+
#if DEVICE_CAN
112+
RCC_OscInitStruct.PLL.PLLN = 80;
113+
#else
108114
RCC_OscInitStruct.PLL.PLLN = 85;
115+
#endif
109116
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
110117
RCC_OscInitStruct.PLL.PLLQ = RCC_PLLQ_DIV2;
111118
RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2;

targets/TARGET_STM/TARGET_STM32G4/objects.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ struct analogin_s {
133133

134134
#if DEVICE_CAN
135135
struct can_s {
136-
CAN_HandleTypeDef CanHandle;
136+
FDCAN_HandleTypeDef CanHandle;
137137
int index;
138138
int hz;
139139
};

targets/TARGET_STM/can_api.c

Lines changed: 104 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,11 @@ static void _can_init_freq_direct(can_t *obj, const can_pinmap_t *pinmap, int hz
7676
else if (pinmap->peripheral == CAN_2) {
7777
obj->index = 1;
7878
}
79+
#endif
80+
#if defined(FDCAN3_BASE)
81+
else if (pinmap->peripheral == CAN_3) {
82+
obj->index = 2;
83+
}
7984
#endif
8085
else {
8186
error("can_init wrong instance\n");
@@ -118,24 +123,49 @@ static void _can_init_freq_direct(can_t *obj, const can_pinmap_t *pinmap, int hz
118123
Phase_segment_2 | 30 tq | <nts2> = <n_tq> - 1 - <nts1>
119124
Synchronization_Jump_width | 30 tq | <nsjw> = <nts2>
120125
*/
126+
127+
// !Attention Not all bitrates can be covered with all fdcan-core-clk values. When a clk
128+
// does not work for the desired bitrate, change system_clock settings for FDCAN_CLK
129+
// (default FDCAN_CLK is PLLQ)
130+
#ifdef TARGET_STM32G4
131+
int ntq = HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_FDCAN) / hz;
132+
#else
133+
// STM32H7 doesn't support yet HAL_RCCEx_GetPeriphCLKFreq for FDCAN
134+
// Internal ST ticket 92465
121135
int ntq = 10000000 / hz;
136+
#endif
137+
138+
int nominalPrescaler = 1;
139+
// !When the sample point should be lower than 50%, this must be changed to
140+
// !IS_FDCAN_NOMINAL_TSEG2(ntq/nominalPrescaler), since
141+
// NTSEG2 and SJW max values are lower. For now the sample point is fix @75%
142+
while (!IS_FDCAN_NOMINAL_TSEG1(ntq/nominalPrescaler)){
143+
nominalPrescaler ++;
144+
if (!IS_FDCAN_NOMINAL_PRESCALER(nominalPrescaler)){
145+
error("Could not determine good nominalPrescaler. Bad clock value\n");
146+
}
147+
}
148+
ntq = ntq/nominalPrescaler;
122149

123150
obj->CanHandle.Init.FrameFormat = FDCAN_FRAME_CLASSIC;
124151
obj->CanHandle.Init.Mode = FDCAN_MODE_NORMAL;
125152
obj->CanHandle.Init.AutoRetransmission = ENABLE;
126153
obj->CanHandle.Init.TransmitPause = DISABLE;
127154
obj->CanHandle.Init.ProtocolException = ENABLE;
128-
obj->CanHandle.Init.NominalPrescaler = 1; // Prescaler
155+
obj->CanHandle.Init.NominalPrescaler = nominalPrescaler; // Prescaler
129156
obj->CanHandle.Init.NominalTimeSeg1 = ntq * 0.75; // Phase_segment_1
130157
obj->CanHandle.Init.NominalTimeSeg2 = ntq - 1 - obj->CanHandle.Init.NominalTimeSeg1; // Phase_segment_2
131158
obj->CanHandle.Init.NominalSyncJumpWidth = obj->CanHandle.Init.NominalTimeSeg2; // Synchronization_Jump_width
132159
obj->CanHandle.Init.DataPrescaler = 0x1; // Not used - only in FDCAN
133160
obj->CanHandle.Init.DataSyncJumpWidth = 0x1; // Not used - only in FDCAN
134161
obj->CanHandle.Init.DataTimeSeg1 = 0x1; // Not used - only in FDCAN
135162
obj->CanHandle.Init.DataTimeSeg2 = 0x1; // Not used - only in FDCAN
163+
#ifndef TARGET_STM32G4
136164
obj->CanHandle.Init.MessageRAMOffset = 0;
165+
#endif
137166
obj->CanHandle.Init.StdFiltersNbr = 1; // to be aligned with the handle parameter in can_filter
138167
obj->CanHandle.Init.ExtFiltersNbr = 1; // to be aligned with the handle parameter in can_filter
168+
#ifndef TARGET_STM32G4
139169
obj->CanHandle.Init.RxFifo0ElmtsNbr = 8;
140170
obj->CanHandle.Init.RxFifo0ElmtSize = FDCAN_DATA_BYTES_8;
141171
obj->CanHandle.Init.RxFifo1ElmtsNbr = 0;
@@ -145,9 +175,11 @@ static void _can_init_freq_direct(can_t *obj, const can_pinmap_t *pinmap, int hz
145175
obj->CanHandle.Init.TxEventsNbr = 3;
146176
obj->CanHandle.Init.TxBuffersNbr = 0;
147177
obj->CanHandle.Init.TxFifoQueueElmtsNbr = 3;
178+
#endif
148179
obj->CanHandle.Init.TxFifoQueueMode = FDCAN_TX_FIFO_OPERATION;
180+
#ifndef TARGET_STM32G4
149181
obj->CanHandle.Init.TxElmtSize = FDCAN_DATA_BYTES_8;
150-
182+
#endif
151183
can_internal_init(obj);
152184
}
153185

@@ -194,11 +226,19 @@ void can_irq_free(can_t *obj)
194226
HAL_NVIC_DisableIRQ(FDCAN2_IT0_IRQn);
195227
HAL_NVIC_DisableIRQ(FDCAN2_IT1_IRQn);
196228
}
229+
#endif
230+
#if defined(FDCAN3_BASE)
231+
else if (can == CAN_3) {
232+
HAL_NVIC_DisableIRQ(FDCAN3_IT0_IRQn);
233+
HAL_NVIC_DisableIRQ(FDCAN3_IT1_IRQn);
234+
}
197235
#endif
198236
else {
199237
return;
200238
}
239+
#ifndef TARGET_STM32G4
201240
HAL_NVIC_DisableIRQ(FDCAN_CAL_IRQn);
241+
#endif
202242
can_irq_ids[obj->index] = 0;
203243
}
204244

@@ -235,8 +275,34 @@ int can_frequency(can_t *obj, int f)
235275
error("HAL_FDCAN_Stop error\n");
236276
}
237277

238-
/* See can_init_freq function for calculation details */
278+
279+
/* See can_init_freq function for calculation details
280+
*
281+
* !Attention Not all bitrates can be covered with all fdcan-core-clk values. When a clk
282+
* does not work for the desired bitrate, change system_clock settings for FDCAN_CLK
283+
* (default FDCAN_CLK is PLLQ)
284+
*/
285+
#ifdef TARGET_STM32G4
286+
int ntq = HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_FDCAN) / f;
287+
#else
288+
// STM32H7 doesn't support yet HAL_RCCEx_GetPeriphCLKFreq for FDCAN
289+
// Internal ST ticket 92465
239290
int ntq = 10000000 / f;
291+
#endif
292+
293+
int nominalPrescaler = 1;
294+
// !When the sample point should be lower than 50%, this must be changed to
295+
// !IS_FDCAN_DATA_TSEG2(ntq/nominalPrescaler), since
296+
// NTSEG2 and SJW max values are lower. For now the sample point is fix @75%
297+
while (!IS_FDCAN_DATA_TSEG1(ntq/nominalPrescaler)){
298+
nominalPrescaler ++;
299+
if (!IS_FDCAN_NOMINAL_PRESCALER(nominalPrescaler)){
300+
error("Could not determine good nominalPrescaler. Bad clock value\n");
301+
}
302+
}
303+
ntq = ntq/nominalPrescaler;
304+
305+
obj->CanHandle.Init.NominalPrescaler = nominalPrescaler;
240306
obj->CanHandle.Init.NominalTimeSeg1 = ntq * 0.75; // Phase_segment_1
241307
obj->CanHandle.Init.NominalTimeSeg2 = ntq - 1 - obj->CanHandle.Init.NominalTimeSeg1; // Phase_segment_2
242308
obj->CanHandle.Init.NominalSyncJumpWidth = obj->CanHandle.Init.NominalTimeSeg2; // Synchronization_Jump_width
@@ -339,7 +405,7 @@ int can_read(can_t *obj, CAN_Message *msg, int handle)
339405
msg->format = CANExtended;
340406
}
341407
msg->id = RxHeader.Identifier;
342-
msg->type = CANData;
408+
msg->type = (RxHeader.RxFrameType == FDCAN_DATA_FRAME) ? CANData : CANRemote;
343409
msg->len = RxHeader.DataLength >> 16; // see FDCAN_data_length_code value
344410

345411
return 1;
@@ -441,14 +507,21 @@ static void can_irq(CANName name, int id)
441507
irq_handler(can_irq_ids[id], IRQ_TX);
442508
}
443509
}
444-
510+
#ifndef TARGET_STM32G4
445511
if (__HAL_FDCAN_GET_IT_SOURCE(&CanHandle, FDCAN_IT_RX_BUFFER_NEW_MESSAGE)) {
446512
if (__HAL_FDCAN_GET_FLAG(&CanHandle, FDCAN_IT_RX_BUFFER_NEW_MESSAGE)) {
447513
__HAL_FDCAN_CLEAR_FLAG(&CanHandle, FDCAN_IT_RX_BUFFER_NEW_MESSAGE);
448514
irq_handler(can_irq_ids[id], IRQ_RX);
449515
}
450516
}
451-
517+
#else
518+
if (__HAL_FDCAN_GET_IT_SOURCE(&CanHandle, FDCAN_IT_RX_FIFO0_NEW_MESSAGE)) {
519+
if (__HAL_FDCAN_GET_FLAG(&CanHandle, FDCAN_IT_RX_FIFO0_NEW_MESSAGE)) {
520+
__HAL_FDCAN_CLEAR_FLAG(&CanHandle, FDCAN_IT_RX_FIFO0_NEW_MESSAGE);
521+
irq_handler(can_irq_ids[id], IRQ_RX);
522+
}
523+
}
524+
#endif
452525
if (__HAL_FDCAN_GET_IT_SOURCE(&CanHandle, FDCAN_IT_ERROR_WARNING)) {
453526
if (__HAL_FDCAN_GET_FLAG(&CanHandle, FDCAN_FLAG_ERROR_WARNING)) {
454527
__HAL_FDCAN_CLEAR_FLAG(&CanHandle, FDCAN_FLAG_ERROR_WARNING);
@@ -481,6 +554,7 @@ void FDCAN1_IT1_IRQHandler(void)
481554
can_irq(CAN_1, 0);
482555
}
483556

557+
#if defined(FDCAN2_BASE)
484558
void FDCAN2_IT0_IRQHandler(void)
485559
{
486560
can_irq(CAN_2, 1);
@@ -490,6 +564,20 @@ void FDCAN2_IT1_IRQHandler(void)
490564
{
491565
can_irq(CAN_2, 1);
492566
}
567+
#endif //FDCAN2_BASE
568+
569+
#if defined(FDCAN3_BASE)
570+
void FDCAN3_IT0_IRQHandler(void)
571+
{
572+
can_irq(CAN_3, 2);
573+
}
574+
575+
void FDCAN3_IT1_IRQHandler(void)
576+
{
577+
can_irq(CAN_3, 2);
578+
}
579+
#endif //FDCAN3_BASE
580+
493581

494582
// TODO Add other interrupts ?
495583
void can_irq_set(can_t *obj, CanIrqType type, uint32_t enable)
@@ -501,7 +589,11 @@ void can_irq_set(can_t *obj, CanIrqType type, uint32_t enable)
501589
interrupts = FDCAN_IT_TX_COMPLETE;
502590
break;
503591
case IRQ_RX:
592+
#ifndef TARGET_STM32G4
504593
interrupts = FDCAN_IT_RX_BUFFER_NEW_MESSAGE;
594+
#else
595+
interrupts = FDCAN_IT_RX_FIFO0_NEW_MESSAGE;
596+
#endif
505597
break;
506598
case IRQ_ERROR:
507599
interrupts = FDCAN_IT_ERROR_WARNING;
@@ -531,6 +623,12 @@ void can_irq_set(can_t *obj, CanIrqType type, uint32_t enable)
531623
NVIC_SetVector(FDCAN2_IT1_IRQn, (uint32_t)&FDCAN2_IT1_IRQHandler);
532624
NVIC_EnableIRQ(FDCAN2_IT1_IRQn);
533625
#endif
626+
#if defined(FDCAN3_BASE)
627+
NVIC_SetVector(FDCAN3_IT0_IRQn, (uint32_t)&FDCAN3_IT0_IRQHandler);
628+
NVIC_EnableIRQ(FDCAN3_IT0_IRQn);
629+
NVIC_SetVector(FDCAN3_IT1_IRQn, (uint32_t)&FDCAN3_IT1_IRQHandler);
630+
NVIC_EnableIRQ(FDCAN3_IT1_IRQn);
631+
#endif
534632
}
535633

536634
#else /* FDCAN1 */

targets/targets.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2467,7 +2467,8 @@
24672467
"device_has_add": [
24682468
"ANALOGOUT",
24692469
"FLASH",
2470-
"MPU"
2470+
"MPU",
2471+
"CAN"
24712472
]
24722473
},
24732474
"NUCLEO_G474RE": {

0 commit comments

Comments
 (0)