Subversion Repositories canSerial

Rev

Rev 3 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 mjames 1
/* USER CODE BEGIN Header */
2
/**
3
 ******************************************************************************
4
 * @file           : main.c
5
 * @brief          : Main program body
6
 ******************************************************************************
7
 * @attention
8
 *
9
 * <h2><center>&copy; Copyright (c) 2022 STMicroelectronics.
10
 * All rights reserved.</center></h2>
11
 *
12
 * This software component is licensed by ST under BSD 3-Clause license,
13
 * the "License"; You may not use this file except in compliance with the
14
 * License. You may obtain a copy of the License at:
15
 *                        opensource.org/licenses/BSD-3-Clause
16
 *
17
 ******************************************************************************
18
 */
19
/* USER CODE END Header */
20
/* Includes ------------------------------------------------------------------*/
21
#include "main.h"
22
 
23
/* Private includes ----------------------------------------------------------*/
24
/* USER CODE BEGIN Includes */
3 mjames 25
#include "display.h"
26
 
2 mjames 27
#include "string.h"
28
#include "base64.h"
29
#include "libSerial/serial.H"
3 mjames 30
#include "libSerial/serialUtils.H"
2 mjames 31
#include "libSmallPrintf/small_printf.h"
32
 
33
/* USER CODE END Includes */
34
 
35
/* Private typedef -----------------------------------------------------------*/
36
/* USER CODE BEGIN PTD */
37
 
38
typedef enum
39
{
40
  FAIL,
41
  REJECT,
42
  ACCEPT,
43
  COMPLETE
44
} appendStatus;
45
 
46
typedef struct
47
{
48
  uint8_t payloadBuffer[233];
49
  uint32_t payloadId;
50
  uint8_t payloadRemaining;  // number of bytes remaining
51
  uint8_t payloadTotal;      // number total number of bytes
52
  uint8_t payloadOffset;     // byte offset
53
  uint8_t payloadNextSeq;    // next sequence frame expected
54
  uint32_t payloadTimestamp; // timestamp of reception
55
  appendStatus status;
56
} contextType;
57
 
58
/* USER CODE END PTD */
59
 
60
/* Private define ------------------------------------------------------------*/
61
/* USER CODE BEGIN PD */
62
/* USER CODE END PD */
63
 
64
/* Private macro -------------------------------------------------------------*/
65
/* USER CODE BEGIN PM */
66
#define False (0)
67
#define True (1)
68
/* USER CODE END PM */
69
 
70
/* Private variables ---------------------------------------------------------*/
71
CAN_HandleTypeDef hcan;
72
 
3 mjames 73
SPI_HandleTypeDef hspi1;
74
 
2 mjames 75
UART_HandleTypeDef huart1;
76
 
77
/* USER CODE BEGIN PV */
78
 
79
/* USER CODE END PV */
80
 
81
/* Private function prototypes -----------------------------------------------*/
82
void SystemClock_Config(void);
83
static void MX_GPIO_Init(void);
84
static void MX_CAN_Init(void);
85
static void MX_USART1_UART_Init(void);
3 mjames 86
static void MX_SPI1_Init(void);
2 mjames 87
/* USER CODE BEGIN PFP */
88
 
89
/* USER CODE END PFP */
90
 
91
/* Private user code ---------------------------------------------------------*/
92
/* USER CODE BEGIN 0 */
93
 
94
#define CONTEXTS 6
95
contextType contexts[CONTEXTS];
96
 
97
CAN_TxHeaderTypeDef TxHeader;
98
CAN_RxHeaderTypeDef RxHeader;
99
 
100
uint8_t TxData[8];
101
uint8_t RxData[8];
102
 
103
// Storage for the data
104
 
105
uint32_t TxMailbox;
106
 
107
char const version[] = "$PDGY,Mike_James_Converter_#00001_Mode:15\r\n";
108
char const keepawake[] = "$PDGY,000000,1,,4,%ld.%03ld,,,\r\n";
109
 
4 mjames 110
// Allocation of serial buffer sizes and storage
111
#define TX_BUFFER_SIZE 512
112
#define RX_BUFFER_SIZE 16
113
uint8_t tx_buffer[TX_BUFFER_SIZE];
114
uint8_t rx_buffer[RX_BUFFER_SIZE];
115
 
2 mjames 116
// reset a search context
117
void resetContext(contextType *c)
118
{
119
  c->payloadRemaining = 0; // number of bytes remaining
120
  c->payloadTotal = 0;     // number total number of bytes
121
  c->payloadOffset = 0;
122
  c->payloadNextSeq = 0;
123
  c->payloadTimestamp = 0;
124
  c->status = FAIL;
125
  c->payloadId = 0;
126
}
127
 
128
uint8_t singleFrame(uint32_t pgn)
129
{
130
 
131
  switch (pgn)
132
  {
133
  case 129029:
134
  case 129038:
135
  case 126996:
136
  case 127489:
137
    return False;
138
  default:
139
    break;
140
  }
141
 
142
  if (pgn >= 130816 && pgn <= 131071)
143
    return False;
144
  if (pgn >= 65536 && pgn <= 126975)
145
    return False;
146
  return True;
147
}
148
 
149
// called from CAN frame callback
150
appendStatus append(contextType *c, CAN_RxHeaderTypeDef *packet)
151
{
152
  uint32_t extId = RxHeader.ExtId;
153
 
154
  if (c->payloadId != 0 && c->payloadId != extId)
155
    return REJECT;
156
  uint8_t newId = c->payloadId == 0; // set a flag if this is a newly discovered frame
157
  c->payloadId = extId;
158
 
159
  uint32_t pgn = (c->payloadId >> 8) & ((1 << 18) - 1);
160
  uint8_t pf = (pgn >> 8) & 0xFF;
161
 
162
  if (pf < 240)
163
  {
164
    // process PS if in PDU1 , address is low byte
165
    pgn = pgn & 0x3FF00;
166
  }
167
 
168
  uint8_t packetLen = RxHeader.DLC;
169
 
170
  if (singleFrame(pgn))
171
  {
172
    c->payloadTimestamp = HAL_GetTick();
173
    memcpy(c->payloadBuffer, RxData, packetLen);
174
    c->payloadRemaining = 0;
175
    c->payloadTotal = packetLen;
176
    c->status = COMPLETE;
177
    return c->status; // successfully filled frame
178
  }
179
  else
180
  {
181
    // sort out fastpacket new ID
182
    if (newId)
183
    {
184
      if ((RxData[0] & 0x1f) != 0)
185
      {
186
        resetContext(c);
187
        return FAIL;
188
      }
189
      c->payloadTimestamp = HAL_GetTick();
190
      c->payloadNextSeq = RxData[0] + 1;
191
      c->payloadId = extId;
192
      c->payloadRemaining = RxData[1];
193
      c->payloadTotal = RxData[1];
194
      // no data , return
195
      if (c->payloadTotal == 0)
196
      {
197
        resetContext(c);
198
        return FAIL;
199
      }
200
      uint8_t numBytes = packetLen - 2;
201
      memcpy(c->payloadBuffer, RxData + 2, numBytes);
202
 
203
      // CAN frame can be longer than remaining bytes, do not make payloadRemaining wrap around !
204
      if (numBytes < c->payloadRemaining)
205
        c->payloadRemaining -= numBytes;
206
      else
207
        c->payloadRemaining = 0;
208
      c->payloadOffset = numBytes;
209
    }
210
    else
211
    {
212
      if (RxData[0] != c->payloadNextSeq)
213
      {
214
        resetContext(c);
215
        return FAIL;
216
      }
217
      // predict next payload sequence
218
      c->payloadNextSeq++;
219
      uint8_t numBytes = packetLen - 1;
220
      memcpy(c->payloadBuffer + c->payloadOffset, RxData + 1, numBytes);
221
      c->payloadRemaining -= numBytes;
222
      c->payloadOffset += numBytes;
223
    }
224
  }
225
 
226
  appendStatus stat = (c->payloadRemaining != 0) ? ACCEPT : COMPLETE;
227
  c->status = stat;
228
  return stat;
229
}
230
 
231
void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)
232
{
233
  HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);
234
  HAL_CAN_GetRxMessage(hcan, CAN_RX_FIFO0, &RxHeader, RxData);
235
 
236
  int i;
237
  for (i = 0; i < CONTEXTS; ++i)
238
  {
239
    contextType *ctx = &contexts[i];
240
    appendStatus stat = append(ctx, &RxHeader);
241
    if (stat == ACCEPT || stat == COMPLETE)
242
      break; // accepted data, stop loop
243
  }
244
}
245
 
246
void heartBeat()
247
{
248
  char lineBuff[80];
249
  uint32_t timestamp = HAL_GetTick();
250
  size_t pos = small_sprintf(lineBuff, keepawake,
251
                             timestamp / 1000, // seconds
252
                             timestamp % 1000  // milliseconds
253
  );
254
  HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);
255
  if (pos < SerialTransmitSpace(&uc1))
256
  {
257
    __disable_irq();
258
    sendString(&uc1, (char *)lineBuff, pos);
259
    __enable_irq();
260
  }
261
}
262
 
263
// utility function to set up the filter mask
264
void CAN_FilterMaskEXT(CAN_FilterTypeDef *filter_, uint32_t id_, uint32_t mask_)
265
{
266
  filter_->FilterIdHigh = id_ >> 13;
267
  filter_->FilterIdLow = ((id_ & 0x1FFF) << 3) | CAN_ID_EXT;
268
  filter_->FilterMaskIdHigh = mask_ >> 13;
269
  filter_->FilterMaskIdLow = ((mask_ & 0x1FFF) << 3) | CAN_ID_EXT;
270
}
271
 
272
void processCmd(char *buff, int len)
273
{
274
  buff[len] = 0; // terminate in case of error
275
  char lineBuff[100];
4 mjames 276
  int pos = small_sprintf(lineBuff, "$PDGY,ACK,%s\r\n", buff);
2 mjames 277
  if (pos < SerialTransmitSpace(&uc1))
278
  {
279
    __disable_irq();
280
    sendString(&uc1, (char *)lineBuff, pos);
281
    __enable_irq();
282
  }
283
}
284
 
285
/* USER CODE END 0 */
286
 
287
/**
288
 * @brief  The application entry point.
289
 * @retval int
290
 */
291
int main(void)
292
{
293
  /* USER CODE BEGIN 1 */
294
 
295
  /* USER CODE END 1 */
296
 
297
  /* MCU Configuration--------------------------------------------------------*/
298
 
299
  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
300
  HAL_Init();
301
 
302
  /* USER CODE BEGIN Init */
303
 
304
  /* USER CODE END Init */
305
 
306
  /* Configure the system clock */
307
  SystemClock_Config();
308
 
309
  /* USER CODE BEGIN SysInit */
3 mjames 310
  cc_init();
2 mjames 311
 
312
  /* USER CODE END SysInit */
313
 
314
  /* Initialize all configured peripherals */
315
  MX_GPIO_Init();
316
  MX_CAN_Init();
317
  MX_USART1_UART_Init();
3 mjames 318
  MX_SPI1_Init();
2 mjames 319
  /* USER CODE BEGIN 2 */
320
 
321
  HAL_CAN_Start(&hcan);
322
 
4 mjames 323
  init_usart_ctl(&uc1, &huart1,
324
                 tx_buffer,
325
                 rx_buffer,
326
                 TX_BUFFER_SIZE,
327
                 RX_BUFFER_SIZE);
2 mjames 328
 
329
  EnableSerialRxInterrupt(&uc1);
330
 
331
  // Activate the notification
332
  HAL_CAN_ActivateNotification(&hcan, CAN_IT_RX_FIFO0_MSG_PENDING);
333
 
334
  // send out a version string on the serial port
335
  sendString(&uc1, (char *)version, sizeof(version));
336
 
337
  uint32_t sendTime = HAL_GetTick() + 1000;
338
  char cmdBuff[100];
339
 
4 mjames 340
  // serial utils library command editor
3 mjames 341
  editBuffer cmdEdit;
342
 
4 mjames 343
  initReadLine(&cmdEdit, cmdBuff, 100, READLINES_CR);
344
 
2 mjames 345
  for (int i = 0; i < CONTEXTS; ++i)
346
    resetContext(&contexts[i]);
347
 
348
  /* USER CODE END 2 */
349
 
350
  /* Infinite loop */
351
  /* USER CODE BEGIN WHILE */
352
  while (1)
353
  {
354
    /* USER CODE END WHILE */
355
 
356
    /* USER CODE BEGIN 3 */
357
 
4 mjames 358
    editBufferReturn ret = readLine(&uc1, &cmdEdit);
3 mjames 359
 
4 mjames 360
    if (ret == EDIT_CR)
361
    {
362
      processCmd(cmdBuff, charCount(&cmdEdit));
363
      resetInput(&cmdEdit);
364
    }
3 mjames 365
 
2 mjames 366
    if (HAL_GetTick() > sendTime)
367
    {
368
      sendTime += 1000;
369
      heartBeat();
3 mjames 370
      cc_display(2);
2 mjames 371
    }
372
 
373
    for (int i = 0; i < CONTEXTS; ++i)
374
    {
375
      contextType *ctx = &contexts[i];
376
      /// check for too old
377
      //   if (ctx->status == ACCEPT && ctx->payloadTimestamp < old)
378
      //   {
379
      //     resetContext(ctx);
380
      //     continue;
381
      //   }
382
 
383
      if (ctx->status == COMPLETE)
384
      {
385
        __disable_irq();
386
 
387
        uint8_t prio = (ctx->payloadId >> 26) & 0x7;
388
        uint8_t src = ctx->payloadId & 0xFF;
389
        uint8_t dst = 255;
390
        // mask out the PGN field as 18 bits.
391
        uint32_t pgn = (ctx->payloadId >> 8) & ((1 << 18) - 1);
392
        uint8_t pf = (pgn >> 8) & 0xFF;
393
 
394
        if (pf < 240)
395
        {
396
          // process PS if in PDU1 , address is low byte
397
          dst = pgn & 0xFF;
398
          pgn = pgn & 0x3FF00;
399
        }
400
 
401
        char lineBuff[300];
402
        size_t pos = small_sprintf(lineBuff, "!PDGY,%ld,%d,%d,%d,%ld.%03ld,",
403
                                   pgn,  // PGN
404
                                   prio, // priority
405
                                   src,  // source address
406
                                   dst,  // destination address
407
 
408
                                   ctx->payloadTimestamp / 1000, // milliseconds
409
                                   ctx->payloadTimestamp % 1000);
410
 
411
        size_t base64_len;
412
        base64_encode(ctx->payloadBuffer,
413
                      ctx->payloadTotal,
414
                      lineBuff + pos,
415
                      &base64_len);
416
 
417
        pos += base64_len;
418
        lineBuff[pos++] = '\r';
419
        lineBuff[pos++] = '\n';
420
        __enable_irq();
421
 
422
        // skip sending if this would overrun the buffer
423
        if (pos < SerialTransmitSpace(&uc1))
424
          sendString(&uc1, lineBuff, pos);
425
        __disable_irq();
426
 
427
        resetContext(ctx);
428
        __enable_irq();
429
      }
430
    }
431
  }
432
  /* USER CODE END 3 */
433
}
434
 
435
/**
436
 * @brief System Clock Configuration
437
 * @retval None
438
 */
439
void SystemClock_Config(void)
440
{
441
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
442
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
443
 
444
  /** Initializes the RCC Oscillators according to the specified parameters
445
   * in the RCC_OscInitTypeDef structure.
446
   */
447
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
448
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
449
  RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
450
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
451
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI_DIV2;
452
  RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL16;
453
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
454
  {
455
    Error_Handler();
456
  }
457
 
458
  /** Initializes the CPU, AHB and APB buses clocks
459
   */
460
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2;
461
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
462
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
463
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
464
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
465
 
466
  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
467
  {
468
    Error_Handler();
469
  }
470
}
471
 
472
/**
473
 * @brief CAN Initialization Function
474
 * @param None
475
 * @retval None
476
 */
477
static void MX_CAN_Init(void)
478
{
479
 
480
  /* USER CODE BEGIN CAN_Init 0 */
481
 
482
  /* USER CODE END CAN_Init 0 */
483
 
484
  /* USER CODE BEGIN CAN_Init 1 */
485
 
486
  /* USER CODE END CAN_Init 1 */
487
  hcan.Instance = CAN1;
488
  hcan.Init.Prescaler = 16;
489
  hcan.Init.Mode = CAN_MODE_NORMAL;
490
  hcan.Init.SyncJumpWidth = CAN_SJW_2TQ;
491
  hcan.Init.TimeSeg1 = CAN_BS1_3TQ;
492
  hcan.Init.TimeSeg2 = CAN_BS2_4TQ;
493
  hcan.Init.TimeTriggeredMode = DISABLE;
494
  hcan.Init.AutoBusOff = DISABLE;
495
  hcan.Init.AutoWakeUp = DISABLE;
496
  hcan.Init.AutoRetransmission = ENABLE;
497
  hcan.Init.ReceiveFifoLocked = DISABLE;
498
  hcan.Init.TransmitFifoPriority = DISABLE;
499
  if (HAL_CAN_Init(&hcan) != HAL_OK)
500
  {
501
    Error_Handler();
502
  }
503
  /* USER CODE BEGIN CAN_Init 2 */
504
  /* USER CODE BEGIN CAN_Init 2 */
505
 
506
  // allow absolutely everything into filter
507
  CAN_FilterTypeDef filterConfig;
508
  filterConfig.FilterMode = CAN_FILTERMODE_IDMASK;
509
  filterConfig.FilterScale = CAN_FILTERSCALE_32BIT;
510
  filterConfig.FilterFIFOAssignment = CAN_FILTER_FIFO0;
511
  filterConfig.FilterActivation = CAN_FILTER_ENABLE;
512
  filterConfig.FilterBank = 0;
513
 
514
  CAN_FilterMaskEXT(&filterConfig, 0, 0);
515
 
516
  HAL_CAN_ConfigFilter(&hcan, &filterConfig);
517
 
518
  /* USER CODE END CAN_Init 2 */
519
}
520
 
521
/**
3 mjames 522
 * @brief SPI1 Initialization Function
523
 * @param None
524
 * @retval None
525
 */
526
static void MX_SPI1_Init(void)
527
{
528
 
529
  /* USER CODE BEGIN SPI1_Init 0 */
530
 
531
  /* USER CODE END SPI1_Init 0 */
532
 
533
  /* USER CODE BEGIN SPI1_Init 1 */
534
 
535
  /* USER CODE END SPI1_Init 1 */
536
  /* SPI1 parameter configuration*/
537
  hspi1.Instance = SPI1;
538
  hspi1.Init.Mode = SPI_MODE_MASTER;
539
  hspi1.Init.Direction = SPI_DIRECTION_2LINES;
540
  hspi1.Init.DataSize = SPI_DATASIZE_8BIT;
541
  hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;
542
  hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;
543
  hspi1.Init.NSS = SPI_NSS_SOFT;
544
  hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_8;
545
  hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
546
  hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
547
  hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
548
  hspi1.Init.CRCPolynomial = 10;
549
  if (HAL_SPI_Init(&hspi1) != HAL_OK)
550
  {
551
    Error_Handler();
552
  }
553
  /* USER CODE BEGIN SPI1_Init 2 */
554
 
555
  /* USER CODE END SPI1_Init 2 */
556
}
557
 
558
/**
2 mjames 559
 * @brief USART1 Initialization Function
560
 * @param None
561
 * @retval None
562
 */
563
static void MX_USART1_UART_Init(void)
564
{
565
 
566
  /* USER CODE BEGIN USART1_Init 0 */
567
 
568
  /* USER CODE END USART1_Init 0 */
569
 
570
  /* USER CODE BEGIN USART1_Init 1 */
571
 
572
  /* USER CODE END USART1_Init 1 */
573
  huart1.Instance = USART1;
574
  huart1.Init.BaudRate = 460800;
575
  huart1.Init.WordLength = UART_WORDLENGTH_8B;
576
  huart1.Init.StopBits = UART_STOPBITS_1;
577
  huart1.Init.Parity = UART_PARITY_NONE;
578
  huart1.Init.Mode = UART_MODE_TX_RX;
579
  huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
580
  huart1.Init.OverSampling = UART_OVERSAMPLING_16;
581
  if (HAL_UART_Init(&huart1) != HAL_OK)
582
  {
583
    Error_Handler();
584
  }
585
  /* USER CODE BEGIN USART1_Init 2 */
586
 
587
  /* USER CODE END USART1_Init 2 */
588
}
589
 
590
/**
591
 * @brief GPIO Initialization Function
592
 * @param None
593
 * @retval None
594
 */
595
static void MX_GPIO_Init(void)
596
{
597
  GPIO_InitTypeDef GPIO_InitStruct = {0};
3 mjames 598
  /* USER CODE BEGIN MX_GPIO_Init_1 */
599
  /* USER CODE END MX_GPIO_Init_1 */
2 mjames 600
 
601
  /* GPIO Ports Clock Enable */
602
  __HAL_RCC_GPIOC_CLK_ENABLE();
603
  __HAL_RCC_GPIOD_CLK_ENABLE();
604
  __HAL_RCC_GPIOA_CLK_ENABLE();
605
 
606
  /*Configure GPIO pin Output Level */
607
  HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_RESET);
608
 
3 mjames 609
  /*Configure GPIO pin Output Level */
610
  HAL_GPIO_WritePin(GPIOA, SPI1_CS_Pin | SPI1_CD_Pin | SPI1_RESET_Pin, GPIO_PIN_RESET);
611
 
2 mjames 612
  /*Configure GPIO pin : LED_Pin */
613
  GPIO_InitStruct.Pin = LED_Pin;
614
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
615
  GPIO_InitStruct.Pull = GPIO_NOPULL;
616
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
617
  HAL_GPIO_Init(LED_GPIO_Port, &GPIO_InitStruct);
3 mjames 618
 
619
  /*Configure GPIO pins : SPI1_CS_Pin SPI1_CD_Pin SPI1_RESET_Pin */
620
  GPIO_InitStruct.Pin = SPI1_CS_Pin | SPI1_CD_Pin | SPI1_RESET_Pin;
621
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
622
  GPIO_InitStruct.Pull = GPIO_NOPULL;
623
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
624
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
625
 
626
  /* USER CODE BEGIN MX_GPIO_Init_2 */
627
  /* USER CODE END MX_GPIO_Init_2 */
2 mjames 628
}
629
 
630
/* USER CODE BEGIN 4 */
631
 
632
/* USER CODE END 4 */
633
 
634
/**
635
 * @brief  This function is executed in case of error occurrence.
636
 * @retval None
637
 */
638
void Error_Handler(void)
639
{
640
  /* USER CODE BEGIN Error_Handler_Debug */
641
  /* User can add his own implementation to report the HAL error return state */
642
 
643
  /* USER CODE END Error_Handler_Debug */
644
}
645
 
646
#ifdef USE_FULL_ASSERT
647
/**
648
 * @brief  Reports the name of the source file and the source line number
649
 *         where the assert_param error has occurred.
650
 * @param  file: pointer to the source file name
651
 * @param  line: assert_param error line source number
652
 * @retval None
653
 */
654
void assert_failed(uint8_t *file, uint32_t line)
655
{
656
  /* USER CODE BEGIN 6 */
657
  /* User can add his own implementation to report the file name and line number,
658
     tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
659
  /* USER CODE END 6 */
660
}
661
#endif /* USE_FULL_ASSERT */