Statistics
| Branch: | Tag: | Revision:

amiro-blt / Target / Modules / LightRing_1-0 / Boot / main.c @ d54d2f07

History | View | Annotate | Download (32.222 KB)

1 69661903 Thomas Schöpping
/************************************************************************************//**
2
* \file         Demo\ARMCM3_STM32_Olimex_STM32P103_GCC\Boot\main.c
3
* \brief        Bootloader application source file.
4
* \ingroup      Boot_ARMCM3_STM32_Olimex_STM32P103_GCC
5
* \internal
6
*----------------------------------------------------------------------------------------
7
*                          C O P Y R I G H T
8
*----------------------------------------------------------------------------------------
9
*   Copyright (c) 2012  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 470d0567 Thomas Schöpping
* 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 69661903 Thomas Schöpping
* proprietary components. The exception text is included at the bottom of the license
29
* file <license.html>.
30 470d0567 Thomas Schöpping
*
31 69661903 Thomas Schöpping
* \endinternal
32
****************************************************************************************/
33
34
/****************************************************************************************
35
* Include files
36
****************************************************************************************/
37
#include "boot.h"                                /* bootloader generic header          */
38
#include "stm32f10x.h"                           /* microcontroller registers          */
39
#include "stm32f10x_conf.h"                      /* STM32 peripheral drivers           */
40
#include "timer.h"
41
#include "ARMCM3_STM32/types.h"
42 470d0567 Thomas Schöpping
#include "AMiRo/amiroblt.h"
43 69661903 Thomas Schöpping
#include "AMiRo/helper.h"
44
45
/****************************************************************************************
46
* Defines
47
****************************************************************************************/
48
#define PSEUDO_LED_GPIO     GPIOA
49
#define PSEUDO_LED_PIN      GPIO_Pin_1
50
#define LASER_RX_GPIO       GPIOA
51
#define LASER_RX_PIN        GPIO_Pin_2
52
#define LASER_TX_GPIO       GPIOA
53
#define LASER_TX_PIN        GPIO_Pin_3
54
#define LIGHT_BLANK_GPIO    GPIOA
55
#define LIGHT_BLANK_PIN     GPIO_Pin_4
56
#define LIGHT_SCLK_GPIO     GPIOA
57
#define LIGHT_SCLK_PIN      GPIO_Pin_5
58
#define LIGHT_MOSI_GPIO     GPIOA
59
#define LIGHT_MOSI_PIN      GPIO_Pin_7
60
#define PROG_RX_GPIO        GPIOA
61
#define PROG_RX_PIN         GPIO_Pin_9
62
#define PROG_TX_GPIO        GPIOA
63
#define PROG_TX_PIN         GPIO_Pin_10
64
#define CAN_RX_GPIO         GPIOA
65
#define CAN_RX_PIN          GPIO_Pin_11
66
#define CAN_TX_GPIO         GPIOA
67
#define CAN_TX_PIN          GPIO_Pin_12
68
#define SWDIO_GPIO          GPIOA
69
#define SWDIO_PIN           GPIO_Pin_13
70
#define SWCLK_GPIO          GPIOA
71
#define SWCLK_PIN           GPIO_Pin_14
72
73
#define LASER_EN_GPIO       GPIOB
74
#define LASER_EN_PIN        GPIO_Pin_2
75
#define LASER_OC_N_GPIO     GPIOB
76
#define LASER_OC_N_PIN      GPIO_Pin_5
77
#define SYS_UART_DN_GPIO    GPIOB
78
#define SYS_UART_DN_PIN     GPIO_Pin_6
79
#define WL_GDO2_GPIO        GPIOB
80
#define WL_GDO2_PIN         GPIO_Pin_8
81
#define WL_GDO0_GPIO        GPIOB
82
#define WL_GDO0_PIN         GPIO_Pin_9
83
#define MEM_SCL_GPIO        GPIOB
84
#define MEM_SCL_PIN         GPIO_Pin_10
85
#define MEM_SDA_GPIO        GPIOB
86
#define MEM_SDA_PIN         GPIO_Pin_11
87
#define WL_SS_N_GPIO        GPIOB
88
#define WL_SS_N_PIN         GPIO_Pin_12
89
#define WL_SCLK_GPIO        GPIOB
90
#define WL_SCLK_PIN         GPIO_Pin_13
91
#define WL_MISO_GPIO        GPIOB
92
#define WL_MISO_PIN         GPIO_Pin_14
93
#define WL_MOSI_GPIO        GPIOB
94
#define WL_MOSI_PIN         GPIO_Pin_15
95
96
#define LIGHT_XLAT_GPIO     GPIOC
97
#define LIGHT_XLAT_PIN      GPIO_Pin_4
98
#define SYS_UART_RX_GPIO    GPIOC
99
#define SYS_UART_RX_PIN     GPIO_Pin_10
100
#define SYS_UART_TX_GPIO    GPIOC
101
#define SYS_UART_TX_PIN     GPIO_Pin_11
102
#define SYS_PD_N_GPIO       GPIOC
103
#define SYS_PD_N_PIN        GPIO_Pin_14
104
105
#define OSC_IN_GPIO         GPIOD
106
#define OSC_IN_PIN          GPIO_Pin_0
107
#define OSC_OUT_GPIO        GPIOD
108
#define OSC_OUT_PIN         GPIO_Pin_1
109
#define SYS_SYNC_N_GPIO     GPIOD
110
#define SYS_SYNC_N_PIN      GPIO_Pin_2
111
112
/****************************************************************************************
113
* Function prototypes
114
****************************************************************************************/
115
static void Init(void);
116
117
static void initGpio();
118
static void initExti();
119
void configGpioForShutdown();
120
121
ErrorStatus handleWarmReset();
122
123
ErrorStatus shutdownDisambiguationProcedure(const uint8_t type);
124
void shutdownToTransportation(const blt_bool exec_disambiguation);
125
void shutdownToDeepsleep(const blt_bool exec_disambiguation);
126
void shutdownToHibernate(const blt_bool exec_disambiguation);
127
void shutdownAndRestart(const blt_bool exec_disambiguation);
128
129 470d0567 Thomas Schöpping
volatile blBackupRegister_t backup_reg;
130 69661903 Thomas Schöpping
131
/****************************************************************************************
132
* Callback configuration
133
****************************************************************************************/
134
void blCallbackShutdownTransportation(void);
135
void blCallbackShutdownDeepsleep(void);
136
void blCallbackShutdownHibernate(void);
137
void blCallbackShutdownRestart(void);
138
void blCallbackHandleShutdownRequest(void);
139
140 470d0567 Thomas Schöpping
const blCallbackTable_t cbtable __attribute__ ((section ("_callback_table"))) = {
141 69661903 Thomas Schöpping
  .magicNumber = BL_MAGIC_NUMBER,
142 d54d2f07 Thomas Schöpping
  .vBootloader = {BL_VERSION_ID_AMiRoBLT_Release, BL_VERSION_MAJOR, BL_VERSION_MINOR, 0},
143 470d0567 Thomas Schöpping
  .vSSSP = {BL_VERSION_ID_SSSP, SSSP_VERSION_MAJOR, SSSP_VERSION_MINOR, 0},
144
  .vCompiler = {BL_VERSION_ID_GCC, __GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__},  // currently only GCC is supported
145 69661903 Thomas Schöpping
  .cbShutdownHibernate = blCallbackShutdownHibernate,
146
  .cbShutdownDeepsleep = blCallbackShutdownDeepsleep,
147
  .cbShutdownTransportation = blCallbackShutdownTransportation,
148
  .cbShutdownRestart = blCallbackShutdownRestart,
149
  .cbHandleShutdownRequest = blCallbackHandleShutdownRequest,
150
  .cb5 = (void*)0,
151
  .cb6 = (void*)0,
152
  .cb7 = (void*)0,
153
  .cb8 = (void*)0,
154
  .cb9 = (void*)0,
155
  .cb10 = (void*)0,
156
  .cb11 = (void*)0
157
};
158
159
/************************************************************************************//**
160 470d0567 Thomas Schöpping
** \brief     This is the entry point for the bootloader application and is called
161 69661903 Thomas Schöpping
**            by the reset interrupt vector after the C-startup routines executed.
162
** \return    Program return code.
163
**
164
****************************************************************************************/
165
int main(void)
166
{
167
  /* initialize the microcontroller */
168
  Init();
169
170
  /* activate some required cocks */
171
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);
172
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOC | RCC_APB2Periph_GPIOD, ENABLE);
173
174
  /* initialize GPIOs and EXTI lines */
175
  initGpio();
176
  setLed(BLT_TRUE);
177
  initExti();
178
179
  /* initialize the timer */
180
  TimerInit();
181
182
  /* detect the primary reason for this wakeup/restart */
183
  backup_reg.wakeup_pri_reason =
184
      ((RCC_GetFlagStatus(RCC_FLAG_LPWRRST) == SET) ? BL_WAKEUP_PRI_RSN_LPWRRST : 0) |
185
      ((RCC_GetFlagStatus(RCC_FLAG_WWDGRST) == SET) ? BL_WAKEUP_PRI_RSN_WWDGRST : 0) |
186
      ((RCC_GetFlagStatus(RCC_FLAG_IWDGRST) == SET) ? BL_WAKEUP_PRI_RSN_IWDGRST : 0) |
187
      ((RCC_GetFlagStatus(RCC_FLAG_SFTRST) == SET) ? BL_WAKEUP_PRI_RSN_SFTRST : 0)   |
188
      ((RCC_GetFlagStatus(RCC_FLAG_PORRST) == SET) ? BL_WAKEUP_PRI_RSN_PORRST : 0)   |
189
      ((RCC_GetFlagStatus(RCC_FLAG_PINRST) == SET) ? BL_WAKEUP_PRI_RSN_PINRST : 0)   |
190
      ((PWR_GetFlagStatus(PWR_FLAG_WU) == SET) ? BL_WAKEUP_PRI_RSN_WKUP : 0);
191
  /* for this module there is no secondary wakeup reason */
192
  backup_reg.wakeup_sec_reason = BL_WAKEUP_SEC_RSN_UNKNOWN;
193
194
  /* clear the flags */
195
  RCC_ClearFlag();
196
  PWR_ClearFlag(PWR_FLAG_WU);
197
198
  setLed(BLT_FALSE);
199
200
  /* hanlde different wakeup/reset reasons */
201
  ErrorStatus status = ERROR;
202
  if (backup_reg.wakeup_pri_reason & BL_WAKEUP_PRI_RSN_PINRST) {
203
    /* system was woken via NRST pin */
204
    status = handleWarmReset();
205
  } else {
206
    /* system was woken/reset for an unexpected reason */
207
    blinkSOS(1);
208
    status = handleWarmReset();
209
  }
210
211
  /* if something went wrong, signal this failure */
212
  if (status != SUCCESS) {
213
    blinkSOSinf();
214
  }
215
216
  return 0;
217
} /*** end of main ***/
218
219
220
/************************************************************************************//**
221 470d0567 Thomas Schöpping
** \brief     Initializes the microcontroller.
222 69661903 Thomas Schöpping
** \return    none.
223
**
224
****************************************************************************************/
225
static void Init(void)
226
{
227
  volatile blt_int32u StartUpCounter = 0, HSEStatus = 0;
228
  blt_int32u pll_multiplier;
229
#if (BOOT_FILE_LOGGING_ENABLE > 0) && (BOOT_COM_UART_ENABLE == 0) && (BOOT_GATE_UART_ENABLE == 0)
230
  GPIO_InitTypeDef  GPIO_InitStruct;
231 470d0567 Thomas Schöpping
  USART_InitTypeDef USART_InitStruct;
232
#endif
233 69661903 Thomas Schöpping
234
  /* reset the RCC clock configuration to the default reset state (for debug purpose) */
235
  /* set HSION bit */
236
  RCC->CR |= (blt_int32u)0x00000001;
237
  /* reset SW, HPRE, PPRE1, PPRE2, ADCPRE and MCO bits */
238
  RCC->CFGR &= (blt_int32u)0xF8FF0000;
239
  /* reset HSEON, CSSON and PLLON bits */
240
  RCC->CR &= (blt_int32u)0xFEF6FFFF;
241
  /* reset HSEBYP bit */
242
  RCC->CR &= (blt_int32u)0xFFFBFFFF;
243
  /* reset PLLSRC, PLLXTPRE, PLLMUL and USBPRE/OTGFSPRE bits */
244
  RCC->CFGR &= (blt_int32u)0xFF80FFFF;
245
  /* disable all interrupts and clear pending bits  */
246
  RCC->CIR = 0x009F0000;
247 470d0567 Thomas Schöpping
  /* enable HSE */
248 69661903 Thomas Schöpping
  RCC->CR |= ((blt_int32u)RCC_CR_HSEON);
249
  /* wait till HSE is ready and if Time out is reached exit */
250
  do
251
  {
252
    HSEStatus = RCC->CR & RCC_CR_HSERDY;
253 470d0567 Thomas Schöpping
    StartUpCounter++;
254
  }
255 69661903 Thomas Schöpping
  while((HSEStatus == 0) && (StartUpCounter != 1500));
256
  /* check if time out was reached */
257
  if ((RCC->CR & RCC_CR_HSERDY) == RESET)
258
  {
259
    /* cannot continue when HSE is not ready */
260
    ASSERT_RT(BLT_FALSE);
261
  }
262
  /* enable flash prefetch buffer */
263
  FLASH->ACR |= FLASH_ACR_PRFTBE;
264
  /* reset flash wait state configuration to default 0 wait states */
265
  FLASH->ACR &= (blt_int32u)((blt_int32u)~FLASH_ACR_LATENCY);
266
#if (BOOT_CPU_SYSTEM_SPEED_KHZ > 48000)
267
  /* configure 2 flash wait states */
268 470d0567 Thomas Schöpping
  FLASH->ACR |= (blt_int32u)FLASH_ACR_LATENCY_2;
269
#elif (BOOT_CPU_SYSTEM_SPEED_KHZ > 24000)
270 69661903 Thomas Schöpping
  /* configure 1 flash wait states */
271 470d0567 Thomas Schöpping
  FLASH->ACR |= (blt_int32u)FLASH_ACR_LATENCY_1;
272 69661903 Thomas Schöpping
#endif
273
  /* HCLK = SYSCLK */
274
  RCC->CFGR |= (blt_int32u)RCC_CFGR_HPRE_DIV1;
275
  /* PCLK2 = HCLK/2 */
276
  RCC->CFGR |= (blt_int32u)RCC_CFGR_PPRE2_DIV2;
277
  /* PCLK1 = HCLK/2 */
278
  RCC->CFGR |= (blt_int32u)RCC_CFGR_PPRE1_DIV2;
279
  /* reset PLL configuration */
280
  RCC->CFGR &= (blt_int32u)((blt_int32u)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE | \
281
                                          RCC_CFGR_PLLMULL));
282
  /* assert that the pll_multiplier is between 2 and 16 */
283
  ASSERT_CT((BOOT_CPU_SYSTEM_SPEED_KHZ/BOOT_CPU_XTAL_SPEED_KHZ) >= 2);
284
  ASSERT_CT((BOOT_CPU_SYSTEM_SPEED_KHZ/BOOT_CPU_XTAL_SPEED_KHZ) <= 16);
285
  /* calculate multiplier value */
286
  pll_multiplier = BOOT_CPU_SYSTEM_SPEED_KHZ/BOOT_CPU_XTAL_SPEED_KHZ;
287
  /* convert to register value */
288
  pll_multiplier = (blt_int32u)((pll_multiplier - 2) << 18);
289
  /* set the PLL multiplier and clock source */
290
  RCC->CFGR |= (blt_int32u)(RCC_CFGR_PLLSRC_HSE | pll_multiplier);
291
  /* enable PLL */
292
  RCC->CR |= RCC_CR_PLLON;
293
  /* wait till PLL is ready */
294
  while((RCC->CR & RCC_CR_PLLRDY) == 0)
295
  {
296
  }
297
  /* select PLL as system clock source */
298
  RCC->CFGR &= (blt_int32u)((blt_int32u)~(RCC_CFGR_SW));
299 470d0567 Thomas Schöpping
  RCC->CFGR |= (blt_int32u)RCC_CFGR_SW_PLL;
300 69661903 Thomas Schöpping
  /* wait till PLL is used as system clock source */
301
  while ((RCC->CFGR & (blt_int32u)RCC_CFGR_SWS) != (blt_int32u)0x08)
302
  {
303
  }
304
#if (BOOT_COM_CAN_ENABLE > 0 || BOOT_GATE_CAN_ENABLE > 0)
305
  /* enable clocks for CAN transmitter and receiver pins (GPIOB and AFIO) */
306
  RCC->APB2ENR |= (blt_int32u)(0x00000004 | 0x00000001);
307
  /* configure CAN Rx (GPIOA11) as alternate function input */
308
  /* first reset the configuration */
309
  GPIOA->CRH &= ~(blt_int32u)((blt_int32u)0xf << 12);
310
  /* CNF8[1:0] = %01 and MODE8[1:0] = %00 */
311
  GPIOA->CRH |= (blt_int32u)((blt_int32u)0x4 << 12);
312
  /* configure CAN Tx (GPIOA12) as alternate function push-pull */
313
  /* first reset the configuration */
314
  GPIOA->CRH &= ~(blt_int32u)((blt_int32u)0xf << 16);
315
  /* CNF9[1:0] = %11 and MODE9[1:0] = %11 */
316
  GPIOA->CRH |= (blt_int32u)((blt_int32u)0xb << 16);
317
318
  /* remap CAN1 pins to PortA */
319
  AFIO->MAPR &= ~(blt_int32u)((blt_int32u)0x3 << 13);
320
  AFIO->MAPR |=  (blt_int32u)((blt_int32u)0x0 << 13);
321
  /* enable clocks for CAN controller peripheral */
322
  RCC->APB1ENR |= (blt_int32u)0x02000000;
323
#endif
324
#if (BOOT_COM_UART_ENABLE > 0 || BOOT_GATE_UART_ENABLE > 0)
325
  /* enable clocks for USART1 peripheral, transmitter and receiver pins (GPIOA and AFIO) */
326
  RCC->APB2ENR |= (blt_int32u)(0x00004000 | 0x00000004 | 0x00000001);
327
  /* configure USART1 Tx (GPIOA9) as alternate function push-pull */
328
  /* first reset the configuration */
329
  GPIOA->CRH &= ~(blt_int32u)((blt_int32u)0xf << 4);
330
  /* CNF2[1:0] = %10 and MODE2[1:0] = %11 */
331
  GPIOA->CRH |= (blt_int32u)((blt_int32u)0xb << 4);
332
  /* configure USART1 Rx (GPIOA10) as alternate function input floating */
333
  /* first reset the configuration */
334
  GPIOA->CRH &= ~(blt_int32u)((blt_int32u)0xf << 8);
335
  /* CNF2[1:0] = %01 and MODE2[1:0] = %00 */
336
  GPIOA->CRH |= (blt_int32u)((blt_int32u)0x4 << 8);
337
338
#if (BOOT_DEBUGGING_UART2_ENABLE > 0)
339
  /* enable clocks for USART2 peripheral */
340
  RCC->APB1ENR |= (blt_int32u)(0x00020000);
341
  /* configure USART2 Tx (GPIOA2) as alternate function push-pull */
342
  /* first reset the configuration */
343
  GPIOA->CRL &= ~(blt_int32u)((blt_int32u)0xf << 8);
344
  /* CNF2[1:0] = %10 and MODE2[1:0] = %11 */
345
  GPIOA->CRL |= (blt_int32u)((blt_int32u)0xb << 8);
346
  /* configure USART2 Rx (GPIOA3) as alternate function input floating */
347
  /* first reset the configuration */
348
  GPIOA->CRL &= ~(blt_int32u)((blt_int32u)0xf << 12);
349
  /* CNF2[1:0] = %01 and MODE2[1:0] = %00 */
350
  GPIOA->CRL |= (blt_int32u)((blt_int32u)0x4 << 12);
351
#endif
352
353
#elif (BOOT_FILE_LOGGING_ENABLE > 0)
354
  /* enable UART peripheral clock */
355
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
356
  /* enable GPIO peripheral clock for transmitter and receiver pins */
357
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE);
358
  /* configure USART Tx as alternate function push-pull */
359
  GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;
360
  GPIO_InitStruct.GPIO_Pin = GPIO_Pin_2;
361
  GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
362
  GPIO_Init(GPIOA, &GPIO_InitStruct);
363
  /* Configure USART Rx as alternate function input floating */
364
  GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;
365
  GPIO_InitStruct.GPIO_Pin = GPIO_Pin_3;
366
  GPIO_Init(GPIOA, &GPIO_InitStruct);
367 470d0567 Thomas Schöpping
  /* configure UART communcation parameters */
368 69661903 Thomas Schöpping
  USART_InitStruct.USART_BaudRate = BOOT_COM_UART_BAUDRATE;
369
  USART_InitStruct.USART_WordLength = USART_WordLength_8b;
370
  USART_InitStruct.USART_StopBits = USART_StopBits_1;
371
  USART_InitStruct.USART_Parity = USART_Parity_No;
372
  USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
373
  USART_InitStruct.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
374
  USART_Init(USART2, &USART_InitStruct);
375
  /* enable UART */
376
  USART_Cmd(USART2, ENABLE);
377
#endif
378
} /*** end of Init ***/
379
380
/*
381
 * Initializes all GPIO used by the bootloader
382
 */
383
static void initGpio() {
384
  GPIO_InitTypeDef gpio_init;
385
386
  /*
387
   * OUTPUTS
388
   */
389
390
  /* initialize the pseudo LED and push it up (inactive) */
391
  GPIO_SetBits(PSEUDO_LED_GPIO, PSEUDO_LED_PIN);
392
  gpio_init.GPIO_Pin    = PSEUDO_LED_PIN;
393
  gpio_init.GPIO_Mode   = GPIO_Mode_Out_PP;
394
  gpio_init.GPIO_Speed  = GPIO_Speed_50MHz;
395
  GPIO_Init(PSEUDO_LED_GPIO, &gpio_init);
396
397
  /* initialize SYS_PD_N and let it go (inactive) */
398
  GPIO_SetBits(SYS_PD_N_GPIO, SYS_PD_N_PIN);
399
  gpio_init.GPIO_Pin    = SYS_PD_N_PIN;
400
  gpio_init.GPIO_Mode   = GPIO_Mode_Out_OD;
401
  gpio_init.GPIO_Speed  = GPIO_Speed_50MHz;
402
  GPIO_Init(SYS_PD_N_GPIO, &gpio_init);
403
404
  /* initialize SYS_SYNC_N and pull it down (active) */
405
  GPIO_ResetBits(SYS_SYNC_N_GPIO, SYS_SYNC_N_PIN);
406
  gpio_init.GPIO_Pin    = SYS_SYNC_N_PIN;
407
  gpio_init.GPIO_Mode   = GPIO_Mode_Out_OD;
408
  gpio_init.GPIO_Speed  = GPIO_Speed_50MHz;
409
  GPIO_Init(SYS_SYNC_N_GPIO, &gpio_init);
410
411
  /*
412
   * INPUTS
413
   */
414
415
} /*** end of initGpio ***/
416
417
/*
418
 * Initialize all EXTI lines
419
 */
420
static void initExti() {
421
  /* configure EXTI lines */
422
  GPIO_EXTILineConfig(GPIO_PortSourceGPIOD, GPIO_PinSource2); // SYS_SYNC_N
423
  GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource5); // LASER_OC_N
424
  GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource6); // SYS_UART_DN
425
  GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource8); // WL_GDO2
426
  GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource9); // WL_GDO0
427
  GPIO_EXTILineConfig(GPIO_PortSourceGPIOC, GPIO_PinSource14); // SYS_PD_N
428
429
  return;
430
} /*** end of initExti ***/
431
432
/*
433
 * Signals, which type of low-power mode the system shall enter after the shutdown sequence.
434
 */
435
ErrorStatus shutdownDisambiguationProcedure(const uint8_t type) {
436
  GPIO_SetBits(SYS_SYNC_N_GPIO, SYS_SYNC_N_PIN);
437
  ErrorStatus ret_val = ERROR;
438
439
  switch (type) {
440
    case BL_SHUTDOWN_PRI_RSN_UNKNOWN:
441
    case BL_SHUTDOWN_PRI_RSN_HIBERNATE:
442
    case BL_SHUTDOWN_PRI_RSN_DEEPSLEEP:
443
    case BL_SHUTDOWN_PRI_RSN_TRANSPORT:
444
    {
445
      // broadcast a number of pulses, depending on the argument
446
      uint8_t pulse_counter = 0;
447
      for (pulse_counter = 0; pulse_counter < type; ++pulse_counter) {
448
        msleep(1);
449
        GPIO_ResetBits(SYS_SYNC_N_GPIO, SYS_SYNC_N_PIN);
450
        msleep(1);
451
        GPIO_SetBits(SYS_SYNC_N_GPIO, SYS_SYNC_N_PIN);
452
      }
453
      // wait for timeout
454
      msleep(10);
455
      ret_val = SUCCESS;
456
      break;
457
    }
458
    case BL_SHUTDOWN_PRI_RSN_RESTART:
459
    {
460
      // since there is no ambiguity for restart requests, no pulses are generated
461
      msleep(10);
462
      ret_val = SUCCESS;
463
      break;
464
    }
465
    default:
466
      ret_val = ERROR;
467
      break;
468
  }
469
470
  return ret_val;
471
} /*** end of shutdownDisambiguationProcedure ***/
472
473
/*
474
 * Final shutdown of the system to enter transportation mode.
475
 */
476
void shutdownToTransportation(const blt_bool exec_disambiguation) {
477
  /* configure some criticpal GPIOs as input
478
   * This is required, because otherwise some hardware might be powered through these signals */
479
  configGpioForShutdown();
480
481
  /* wait for all boards to be ready for shutdown */
482
  GPIO_SetBits(SYS_SYNC_N_GPIO, SYS_SYNC_N_PIN);
483
  // this must no be skipped, since the pull-up voltage for SYS_SYNC_N (VIO3.3) must be configured at this point by definition.
484
  setLed(BLT_TRUE);
485
  waitForSignal(SYS_SYNC_N_GPIO, SYS_SYNC_N_PIN, Bit_SET);
486
  setLed(BLT_FALSE);
487
488
  if (exec_disambiguation == BLT_TRUE) {
489
    /* execute disambiguation procedure and signal all modules to enter transportation mode */
490
    if (shutdownDisambiguationProcedure(BL_SHUTDOWN_PRI_RSN_TRANSPORT) != SUCCESS) {
491
      blinkSOS(1);
492
      msleep(10);
493
    }
494
  }
495
496
  /* morse 'OK' via the LED to signal that shutdown was successful */
497
  blinkOK(1);
498
499
  /* enter standby mode */
500
  PWR_EnterSTANDBYMode();
501
502
  return;
503
} /*** end of shutdownToTransportation ***/
504
505
/*
506
 * Final shutdown of the system to enter deepsleep mode.
507
 */
508
void shutdownToDeepsleep(const blt_bool exec_disambiguation) {
509
  /* configure some criticpal GPIOs as input
510
   * This is required, because otherwise some hardware might be powered through these signals */
511
  configGpioForShutdown();
512
513
  /* wait for all boards to be ready for shutdown */
514
  GPIO_SetBits(SYS_SYNC_N_GPIO, SYS_SYNC_N_PIN);
515
  // this must no be skipped, since the pull-up voltage for SYS_SYNC_N (VIO3.3) must be configured at this point by definition.
516
  setLed(BLT_TRUE);
517
  waitForSignal(SYS_SYNC_N_GPIO, SYS_SYNC_N_PIN, Bit_SET);
518
  setLed(BLT_FALSE);
519
520
  if (exec_disambiguation == BLT_TRUE) {
521
    /* execute disambiguation procedure and signal all modules to enter deepsleep mode */
522
    if (shutdownDisambiguationProcedure(BL_SHUTDOWN_PRI_RSN_DEEPSLEEP) != SUCCESS) {
523
      blinkSOS(1);
524
      msleep(10);
525
    }
526
  }
527
528
  /* morse 'OK' via the LED to signal that shutdown was successful */
529
  blinkOK(1);
530
531
  /* enter standby mode */
532
  PWR_EnterSTANDBYMode();
533
534
  return;
535
} /*** end of shutdownToDeepsleep ***/
536
537
/*
538
 * Final shutdown of the system to enter hibernate mode.
539
 */
540
void shutdownToHibernate(const blt_bool exec_disambiguation) {
541
  /* configure some criticpal GPIOs as input
542
   * This is required, because otherwise some hardware might be powered through these signals */
543
  configGpioForShutdown();
544
545
  /* wait for all boards to be ready for shutdown */
546
  GPIO_SetBits(SYS_SYNC_N_GPIO, SYS_SYNC_N_PIN);
547
  // this must no be skipped, since the pull-up voltage for SYS_SYNC_N (VIO3.3) must be configured at this point by definition.
548
  setLed(BLT_TRUE);
549
  waitForSignal(SYS_SYNC_N_GPIO, SYS_SYNC_N_PIN, Bit_SET);
550
  setLed(BLT_FALSE);
551
552
  if (exec_disambiguation == BLT_TRUE) {
553
    /* execute disambiguation procedure and signal all modules to enter hibernate mode */
554
    if (shutdownDisambiguationProcedure(BL_SHUTDOWN_PRI_RSN_HIBERNATE) != SUCCESS) {
555
      blinkSOS(1);
556
      msleep(10);
557
    }
558
  }
559
560
  /* morse 'OK' via the LED to signal that shutdown was successful */
561
  blinkOK(1);
562
563
  /* enter standby mode */
564
  PWR_EnterSTANDBYMode();
565
566
  return;
567
} /*** end of shutdownToHibernate ***/
568
569
void shutdownAndRestart(const blt_bool exec_disambiguation) {
570
  /* configure some criticpal GPIOs as input
571
   * This is required, because otherwise some hardware might be powered through these signals */
572
  configGpioForShutdown();
573
574
  /* wait for all boards to be ready for shutdown */
575
  GPIO_SetBits(SYS_SYNC_N_GPIO, SYS_SYNC_N_PIN);
576
  // this must no be skipped, since the pull-up voltage for SYS_SYNC_N (VIO3.3) must be configured at this point by definition.
577
  setLed(BLT_TRUE);
578
  waitForSignal(SYS_SYNC_N_GPIO, SYS_SYNC_N_PIN, Bit_SET);
579
  setLed(BLT_FALSE);
580
581
  if (exec_disambiguation == BLT_TRUE) {
582
    /* execute disambiguation procedure and signal all modules to restart in default mode */
583
    if (shutdownDisambiguationProcedure(BL_SHUTDOWN_PRI_RSN_RESTART) != SUCCESS) {
584
      blinkSOS(1);
585
      msleep(10);
586
    }
587
  }
588
589
  /* morse 'OK' via the LED to signal that shutdown was successful */
590
  blinkOK(1);
591
592
  /* enter standby mode */
593
  PWR_EnterSTANDBYMode();
594
595
  /*
596
   * Even though this module will not restart the system by its own, the PowerManagement will reset the system.
597
   */
598
599
  return;
600
}
601
602
/*
603
 * Configures some GPIO pins as inputs for safety reasons.
604
 * Under certain circumstances, these pins might power hardware that is supposed to be shut down.
605
 */
606
void configGpioForShutdown() {
607
  /* setup the configuration */
608
  GPIO_InitTypeDef gpio_init;
609
  gpio_init.GPIO_Mode   = GPIO_Mode_IN_FLOATING;
610
  gpio_init.GPIO_Speed  = GPIO_Speed_50MHz;
611
612
  /* configure SYS_UART_TX */
613
  gpio_init.GPIO_Pin = SYS_UART_TX_PIN;
614
  GPIO_Init(SYS_UART_TX_GPIO, &gpio_init);
615
616
  /* configure CAN_TX */
617
  gpio_init.GPIO_Pin = CAN_TX_PIN;
618
  GPIO_Init(CAN_TX_GPIO, &gpio_init);
619
620
  /* configure all LASER signals */
621
  gpio_init.GPIO_Pin = LASER_EN_PIN;
622
  GPIO_Init(LASER_EN_GPIO, &gpio_init);
623
  gpio_init.GPIO_Pin = LASER_TX_PIN;
624
  GPIO_Init(LASER_TX_GPIO, &gpio_init);
625
626
  /* configure all LIGHT (SPI) signals */
627
  gpio_init.GPIO_Pin = LIGHT_SCLK_PIN;
628
  GPIO_Init(LIGHT_SCLK_GPIO, &gpio_init);
629
  gpio_init.GPIO_Pin = LIGHT_MOSI_PIN;
630
  GPIO_Init(LIGHT_MOSI_GPIO, &gpio_init);
631
  gpio_init.GPIO_Pin = LIGHT_XLAT_PIN;
632
  GPIO_Init(LIGHT_XLAT_GPIO, &gpio_init);
633
  gpio_init.GPIO_Pin = LIGHT_BLANK_PIN;
634
  GPIO_Init(LIGHT_BLANK_GPIO, &gpio_init);
635
636
  /* configure all WL (SPI) signals */
637
  gpio_init.GPIO_Pin = WL_SS_N_PIN;
638
  GPIO_Init(WL_SS_N_GPIO, &gpio_init);
639
  gpio_init.GPIO_Pin = WL_SCLK_PIN;
640
  GPIO_Init(WL_SCLK_GPIO, &gpio_init);
641
  gpio_init.GPIO_Pin = WL_MOSI_PIN;
642
  GPIO_Init(WL_MOSI_GPIO, &gpio_init);
643
644
  return;
645
} /*** end of configGpioForShutdown ***/
646
647
/*
648
 * System was reset via the NRST pin or the reason could not be detected.
649
 * In this case, the system enters the boot loop and starts the OS.
650
 */
651
ErrorStatus handleWarmReset() {
652
  /* initialize the bootloader */
653
  BootInit();
654
655
  /* start the infinite program loop */
656
  uint32_t loopStartTime = 0;
657
  saTimerUpdate(&loopStartTime);
658
  uint32_t currentTime = loopStartTime;
659
  while (1)
660
  {
661 d54d2f07 Thomas Schöpping
//    /* make the pseudo LED "double-blink" */
662
//    saTimerUpdate(&currentTime);
663
//    if (currentTime < loopStartTime + 50) {
664
//      setLed(BLT_TRUE);
665
//    } else if (currentTime < loopStartTime + 50+100) {
666
//      setLed(BLT_FALSE);
667
//    } else if (currentTime < loopStartTime + 50+100+50) {
668
//      setLed(BLT_TRUE);
669
//    } else if ( currentTime < loopStartTime + 50+100+50+300) {
670
//      setLed(BLT_FALSE);
671
//    } else {
672
//      loopStartTime = currentTime;
673
//    }
674 69661903 Thomas Schöpping
675
    /* run the bootloader task */
676
    BootTask();
677
678
    /* check the SYS_PD_N signal */
679
    if (GPIO_ReadInputDataBit(SYS_PD_N_GPIO, SYS_PD_N_PIN) == Bit_RESET) {
680
      blCallbackHandleShutdownRequest();
681
      return SUCCESS;
682
    }
683
  }
684
685
  return ERROR;
686
} /*** end of handleWarmReset ***/
687
688
/*
689
 * Callback function that handles the system shutdown and enters transportation mode.
690
 * When called from a multithreaded environment, it must be ensured that no other thread will preempt this function.
691
 * In transportation low-power mode the system can only be woken up by pulling down the NRST signal.
692
 * Furthermore, the system can not be charged when in transportation mode.
693
 */
694
void blCallbackShutdownTransportation() {
695
  /* make sure that the required clocks are activated */
696
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);
697
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOC | RCC_APB2Periph_GPIOD, ENABLE);
698
699
  /* set/keep the SYS_SYNC and SYS_PD signals active */
700
  GPIO_ResetBits(SYS_SYNC_N_GPIO, SYS_SYNC_N_PIN);
701
  GPIO_ResetBits(SYS_PD_N_GPIO, SYS_PD_N_PIN);
702
703
  saTimerInit();
704
705
  setLed(BLT_TRUE);
706
707
  shutdownToTransportation(BLT_TRUE);
708
709
  return;
710
} /*** end of blCallbackShutdownTransportation ***/
711
712
/*
713
 * Callback function that handles the system shutdown and enters deepsleep mode.
714
 * When called from a multithreaded environment, it must be ensured that no other thread will preempt this function.
715
 * In deepsleep low-power mode the system can only be woken up via the NRST or the WKUP signal, or the RTC or IWDG, if configured.
716
 */
717
void blCallbackShutdownDeepsleep(void) {
718
  /* make sure that the required clocks are activated */
719
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);
720
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOC | RCC_APB2Periph_GPIOD, ENABLE);
721
722
  /* set/keep the SYS_SYNC and SYS_PD signals active */
723
  GPIO_ResetBits(SYS_SYNC_N_GPIO, SYS_SYNC_N_PIN);
724
  GPIO_ResetBits(SYS_PD_N_GPIO, SYS_PD_N_PIN);
725
726
  saTimerInit();
727
728
  setLed(BLT_TRUE);
729
730
  shutdownToDeepsleep(BLT_TRUE);
731
732
  return;
733
} /*** end of blCallbackShutdownDeepsleep ***/
734
735
/*
736
 * Callback function that handles the system shutdown and enters hibernate mode.
737
 * When called from a multithreaded environment, it must be ensured that no other thread will preempt this function.
738
 */
739
void blCallbackShutdownHibernate(void) {
740
  /* make sure that the required clocks are activated */
741
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);
742
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOC | RCC_APB2Periph_GPIOD, ENABLE);
743
744
  /* set/keep the SYS_SYNC and SYS_PD signals active */
745
  GPIO_ResetBits(SYS_SYNC_N_GPIO, SYS_SYNC_N_PIN);
746
  GPIO_ResetBits(SYS_PD_N_GPIO, SYS_PD_N_PIN);
747
748
  saTimerInit();
749
750
  setLed(BLT_TRUE);
751
752
  shutdownToHibernate(BLT_TRUE);
753
754
  return;
755
} /*** end of blCallbackShutdownHibernate ***/
756
757
/*
758
 * Callback function that handles the system shutdown and initializes a restart.
759
 * When called from a multithreaded environment, it must be ensured that no other thread will preempt this function.
760
 */
761
void blCallbackShutdownRestart(void) {
762
  /* make sure that the required clocks are activated */
763
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);
764
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOC | RCC_APB2Periph_GPIOD, ENABLE);
765
766
  /* set/keep the SYS_SYNC and SYS_PD signals active */
767
  GPIO_ResetBits(SYS_SYNC_N_GPIO, SYS_SYNC_N_PIN);
768
  GPIO_ResetBits(SYS_PD_N_GPIO, SYS_PD_N_PIN);
769
770
  /* ensure that all modules had a chance to detect the pulse on SYS_PD_N */
771
  saTimerInit();
772
  msleep(1);
773
  GPIO_SetBits(SYS_PD_N_GPIO, SYS_PD_N_PIN);
774
  msleep(1);
775
776
  shutdownAndRestart(BLT_TRUE);
777
778
  return;
779
} /** end of blCallbackShutdownRestart ***/
780
781
/*
782
 * Callback function that handles a system shutdown/restart request from another module.
783
 * Depending on the result of the disambiguation procedure, the module will enter the according low-power mode or restart.
784
 * When called from a multithreaded environment, it must be ensured that no other thread will preempt this function.
785
 */
786
void blCallbackHandleShutdownRequest(void) {
787
  /* make sure that the required clocks are activated */
788
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);
789
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOC | RCC_APB2Periph_GPIOD, ENABLE);
790
791
  /* set/keep the SYS_SYNC and SYS_PD signals active */
792
  GPIO_ResetBits(SYS_SYNC_N_GPIO, SYS_SYNC_N_PIN);
793
  GPIO_ResetBits(SYS_PD_N_GPIO, SYS_PD_N_PIN);
794
795
  /* ensure that all modules had a chance to detect the pulse on SYS_PD_N */
796
  saTimerInit();
797
  msleep(1);
798
  GPIO_SetBits(SYS_PD_N_GPIO, SYS_PD_N_PIN);
799
  msleep(1);
800
801
  /* wait for all boards to be ready for shutdown */
802
  GPIO_SetBits(SYS_SYNC_N_GPIO, SYS_SYNC_N_PIN);
803
  // this must not be skipped, since the pull-up voltage for SYS_SYNC_N (VIO3.3) must be configured at this point by definition.
804
  setLed(BLT_TRUE);
805
  waitForSignal(SYS_SYNC_N_GPIO, SYS_SYNC_N_PIN, Bit_SET);
806
  setLed(BLT_FALSE);
807
808
  /* check ths SYS_PD_N signal, whether the system shall shutdown or restart */
809
  blt_bool shutdown_nrestart = (GPIO_ReadInputDataBit(SYS_PD_N_GPIO, SYS_PD_N_PIN) == Bit_RESET) ? BLT_TRUE : BLT_FALSE;
810
811
  /* disambiguation procedure (passive) */
812
  uint32_t pulse_counter = 0;
813
  while (waitForSignalTimeout(SYS_SYNC_N_GPIO, SYS_SYNC_N_PIN, Bit_RESET, 10)) {
814
    waitForSignal(SYS_SYNC_N_GPIO, SYS_SYNC_N_PIN, Bit_SET);
815
    ++pulse_counter;
816
  }
817
818
  /* evaluate and hanlde disambiguation result */
819
  if (shutdown_nrestart == BLT_TRUE) {
820
    /* shutdown request */
821
822
    /* handle special cases */
823
    if (pulse_counter == BL_SHUTDOWN_PRI_RSN_UNKNOWN) {
824
      /* no pulse at all was received */
825
      pulse_counter = BL_SHUTDOWN_PRI_RSN_DEFAULT;
826
    } else if (pulse_counter != BL_SHUTDOWN_PRI_RSN_HIBERNATE &&
827
               pulse_counter != BL_SHUTDOWN_PRI_RSN_DEEPSLEEP &&
828
               pulse_counter != BL_SHUTDOWN_PRI_RSN_TRANSPORT) {
829
      /* invalid number of pulses received */
830
      blinkSOS(1);
831
      pulse_counter = BL_SHUTDOWN_PRI_RSN_DEFAULT;
832
    }
833
834
    switch (pulse_counter) {
835
      case BL_SHUTDOWN_PRI_RSN_HIBERNATE:
836
        shutdownToHibernate(BLT_FALSE);
837
        break;
838
      case BL_SHUTDOWN_PRI_RSN_DEEPSLEEP:
839
        shutdownToDeepsleep(BLT_FALSE);
840
        break;
841
      case BL_SHUTDOWN_PRI_RSN_TRANSPORT:
842
        shutdownToTransportation(BLT_FALSE);
843
        break;
844
    }
845
  } else {
846
    /* restart request */
847
848
    /* there is no ambiguity for restart, so it is ignored */
849
    shutdownAndRestart(BLT_FALSE);
850
  }
851
852
  /* if this code is reached, the system did neither shut down, nor restart.
853
   * This must never be the case!
854
   */
855
  blinkSOSinf();
856
  return;
857
} /*** end of blCallbackHandleShutdownRequest ***/
858
859
/*********************************** end of main.c *************************************/