Statistics
| Branch: | Tag: | Revision:

amiro-blt / Target / Modules / PowerManagement_1-2 / Boot / main.c @ 2b9a14a2

History | View | Annotate | Download (57.492 KB)

1
/************************************************************************************//**
2
* \file         Demo\ARMCM4_STM32_Olimex_STM32E407_GCC\Boot\main.c
3
* \brief        Bootloader application source file.
4
* \ingroup      Boot_ARMCM4_STM32_Olimex_STM32E407_GCC
5
* \internal
6
*----------------------------------------------------------------------------------------
7
*                          C O P Y R I G H T
8
*----------------------------------------------------------------------------------------
9
*   Copyright (c) 2013  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
* 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
* proprietary components. The exception text is included at the bottom of the license
29
* file <license.html>.
30
*
31
* \endinternal
32
****************************************************************************************/
33

    
34
/****************************************************************************************
35
* Include files
36
****************************************************************************************/
37
#include "boot.h"                                /* bootloader generic header          */
38
#include "com.h"
39
#include "ARMCM4_STM32/types.h"
40
#include "AMiRo/amiroblt.h"
41
#include "helper.h"
42
#include "iodef.h"
43

    
44
/****************************************************************************************
45
* Defines
46
****************************************************************************************/
47
#define HIBERNATE_TIME_MS       5000
48

    
49
/****************************************************************************************
50
* Function prototypes and static variables
51
****************************************************************************************/
52
static void Init(void);
53

    
54
static void initGpio(void);
55
static void initExti(void);
56
void configGpioForShutdown(void);
57
void systemPowerDown(void);
58

    
59
ErrorStatus handleColdReset(void);
60
ErrorStatus handleSoftwareReset(void);
61
ErrorStatus handleUartDnWakeup(void);
62
ErrorStatus handlePathDcWakeup(void);
63
ErrorStatus handleTouchWakeup(void);
64
ErrorStatus handleIwdgWakeup(void);
65

    
66
static void indicateHibernate(void);
67
static void AdcSingleMeasurement(void);
68

    
69
ADC_TypeDef* setupADC(ADC_TypeDef* adc, const uint16_t low_th, const uint16_t high_th);
70
uint16_t configIwdg(const uint16_t ms);
71

    
72
ErrorStatus shutdownDisambiguationProcedure(const uint8_t type);
73
void shutdownToTransportation(void);
74
void shutdownToDeepsleep(void);
75
void shutdownToHibernate(void);
76
void shutdownAndRestart(void);
77

    
78
volatile blBackupRegister_t backup_reg;
79

    
80
/****************************************************************************************
81
* Callback configuration
82
****************************************************************************************/
83
void blCallbackShutdownTransportation(void);
84
void blCallbackShutdownDeepsleep(void);
85
void blCallbackShutdownHibernate(void);
86
void blCallbackShutdownRestart(void);
87
void blCallbackHandleShutdownRequest(void);
88

    
89
const blCallbackTable_t cbtable __attribute__ ((section ("_callback_table"))) = {
90
  .magicNumber = BL_MAGIC_NUMBER,
91
  .vBootloader = {BL_VERSION_ID_AMiRoBLT_Beta, BL_VERSION_MAJOR, BL_VERSION_MINOR, 4},
92
  .vSSSP = {BL_VERSION_ID_SSSP, BL_SSSP_VERSION_MAJOR, BL_SSSP_VERSION_MINOR, 0},
93
  .vCompiler = {BL_VERSION_ID_GCC, __GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__},  // currently only GCC is supported
94
  .cbShutdownHibernate = blCallbackShutdownHibernate,
95
  .cbShutdownDeepsleep = blCallbackShutdownDeepsleep,
96
  .cbShutdownTransportation = blCallbackShutdownTransportation,
97
  .cbShutdownRestart = blCallbackShutdownRestart,
98
  .cbHandleShutdownRequest = blCallbackHandleShutdownRequest,
99
  .cb5 = (void*)0,
100
  .cb6 = (void*)0,
101
  .cb7 = (void*)0,
102
  .cb8 = (void*)0,
103
  .cb9 = (void*)0,
104
  .cb10 = (void*)0,
105
  .cb11 = (void*)0
106
};
107

    
108
/************************************************************************************//**
109
** \brief     This is the entry point for the bootloader application and is called
110
**            by the reset interrupt vector after the C-startup routines executed.
111
** \return    none.
112
**
113
****************************************************************************************/
114
void main(void)
115
{
116
  /* initialize the microcontroller */
117
  Init();
118

    
119
  /* activate some required clocks */
120
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOB | RCC_AHB1Periph_GPIOC | RCC_AHB1Periph_GPIOD, ENABLE);
121
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);
122
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
123

    
124
  /* initialize GPIOs and EXTI lines */
125
  initGpio();
126
  setLed(BLT_TRUE);
127
  initExti();
128

    
129
  /* initialize the timer */
130
  TimerInit(); // do not use saTimerInit() in order to initialize the static variable.
131

    
132
  /* read the backup register */
133
  backup_reg.raw = RTC_ReadBackupRegister(BL_RTC_BACKUP_REG);
134

    
135
  /* detect the primary reason for this wakeup/restart */
136
  backup_reg.wakeup_pri_reason =
137
      ((RCC_GetFlagStatus(RCC_FLAG_LPWRRST) == SET) ? BL_WAKEUP_PRI_RSN_LPWRRST : 0) |
138
      ((RCC_GetFlagStatus(RCC_FLAG_WWDGRST) == SET) ? BL_WAKEUP_PRI_RSN_WWDGRST : 0) |
139
      ((RCC_GetFlagStatus(RCC_FLAG_IWDGRST) == SET) ? BL_WAKEUP_PRI_RSN_IWDGRST : 0) |
140
      ((RCC_GetFlagStatus(RCC_FLAG_SFTRST) == SET) ? BL_WAKEUP_PRI_RSN_SFTRST : 0)   |
141
      ((RCC_GetFlagStatus(RCC_FLAG_PORRST) == SET) ? BL_WAKEUP_PRI_RSN_PORRST : 0)   |
142
      ((RCC_GetFlagStatus(RCC_FLAG_PINRST) == SET) ? BL_WAKEUP_PRI_RSN_PINRST : 0)   |
143
      ((RCC_GetFlagStatus(RCC_FLAG_BORRST) == SET) ? BL_WAKEUP_PRI_RSN_BORRST : 0)   |
144
      ((PWR_GetFlagStatus(PWR_FLAG_WU) == SET) ? BL_WAKEUP_PRI_RSN_WKUP : 0);
145

    
146
  /* when woken from standby mode, detect the secondary reason for this wakeup/reset */
147
  if ( (backup_reg.wakeup_pri_reason & BL_WAKEUP_PRI_RSN_WKUP) && (PWR_GetFlagStatus(PWR_FLAG_SB) == SET) ) {
148
    if (GPIO_ReadInputDataBit(SYS_UART_DN_GPIO, SYS_UART_DN_PIN) == Bit_RESET) {
149
      backup_reg.wakeup_sec_reason = BL_WAKEUP_SEC_RSN_UART;
150
    } else if (GPIO_ReadInputDataBit(PATH_DC_GPIO, PATH_DC_PIN) == Bit_SET) {
151
      backup_reg.wakeup_sec_reason = BL_WAKEUP_SEC_RSN_PWRPLUG;
152
    } else {
153
      backup_reg.wakeup_sec_reason = BL_WAKEUP_SEC_RSN_TOUCH;
154
    }
155
  } else {
156
    backup_reg.wakeup_sec_reason = BL_WAKEUP_SEC_RSN_UNKNOWN;
157
  }
158

    
159
  /* store the information about this wakeup/restart in the backup register */
160
  PWR_BackupAccessCmd(ENABLE);
161
  RTC_WriteBackupRegister(BL_RTC_BACKUP_REG, backup_reg.raw);
162

    
163
  /* clear the flags */
164
  RCC_ClearFlag();
165
  PWR_ClearFlag(PWR_FLAG_WU);
166

    
167
  setLed(BLT_FALSE);
168

    
169
  /*
170
   * Measure the current voltage of VSYS and enable the chargers if it was found to be > 9V.
171
   */
172
  AdcSingleMeasurement();
173
  if ( (((float)(ADC_GetConversionValue(ADC1)) / (float)0x0FFF) * 3.3f * 5.33f) > 9.0f ) {
174
    /* VSYS was found to be > 9V */
175
    setLed(BLT_TRUE);
176
    GPIO_ResetBits(CHARGE_EN1_N_GPIO, CHARGE_EN1_N_PIN);
177
    GPIO_ResetBits(CHARGE_EN2_N_GPIO, CHARGE_EN2_N_PIN);
178
  }
179

    
180
  /* handle different wakeup/reset reasons */
181
  ErrorStatus status = ERROR;
182
  if (backup_reg.wakeup_pri_reason & BL_WAKEUP_PRI_RSN_SFTRST) {
183
    /* system was reset by software */
184
    status = handleSoftwareReset();
185
  } else if (backup_reg.wakeup_pri_reason & BL_WAKEUP_PRI_RSN_WKUP) {
186
    /* system was woken via WKUP pin */
187
    /* differeciate between thre wakeup types */
188
    switch (backup_reg.wakeup_sec_reason) {
189
      case BL_WAKEUP_SEC_RSN_UART:
190
        status = handleUartDnWakeup();
191
        break;
192
      case BL_WAKEUP_SEC_RSN_PWRPLUG:
193
        status = handlePathDcWakeup();
194
        break;
195
      case BL_WAKEUP_SEC_RSN_TOUCH:
196
        status = handleTouchWakeup();
197
        break;
198
      default:
199
        status = ERROR;
200
        break;
201
    }
202
  } else if (backup_reg.wakeup_pri_reason & BL_WAKEUP_PRI_RSN_IWDGRST) {
203
    /* system was woken by IWDG */
204
    status = handleIwdgWakeup();
205
  } else if (backup_reg.wakeup_pri_reason == BL_WAKEUP_PRI_RSN_PINRST) {
206
    /* system was reset via NRST pin */
207
    status = handleColdReset();
208
  } else {
209
    /* system was woken/reset for an unexpected reason.
210
     * In this case the LED blinks "SOS" (... --- ...) and the system resets.
211
     */
212
    blinkSOS(1);
213
    status = ERROR;
214
    backup_reg.shutdown_pri_reason = BL_SHUTDOWN_PRI_RSN_RESTART;
215
    backup_reg.shutdown_sec_reason = BL_SHUTDOWN_SEC_RSN_UNKNOWN;
216
    RTC_WriteBackupRegister(BL_RTC_BACKUP_REG, backup_reg.raw);
217
    NVIC_SystemReset();
218
  }
219

    
220
  /* if something went wrong, signal this failure */
221
  if (status != SUCCESS) {
222
    blinkSOSinf();
223
  }
224

    
225
  return;
226
} /*** end of main ***/
227

    
228

    
229
/************************************************************************************//**
230
** \brief     Initializes the microcontroller.
231
** \return    none.
232
**
233
****************************************************************************************/
234
static void Init(void)
235
{
236
#if (BOOT_COM_UART_ENABLE > 0 || BOOT_GATE_UART_ENABLE > 0)
237
  GPIO_InitTypeDef  GPIO_InitStructure;
238
#elif (BOOT_FILE_SYS_ENABLE > 0)
239
  GPIO_InitTypeDef  GPIO_InitStructure;
240
  USART_InitTypeDef USART_InitStructure;
241
#elif (BOOT_COM_CAN_ENABLE > 0 || BOOT_GATE_CAN_ENABLE > 0)
242
  GPIO_InitTypeDef  GPIO_InitStructure;
243
#endif
244

    
245
  /* initialize the system and its clocks */
246
  SystemInit();
247
#if (BOOT_COM_UART_ENABLE > 0 || BOOT_GATE_UART_ENABLE > 0)
248
  /* enable UART peripheral clock */
249
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
250
  /* enable GPIO peripheral clock for transmitter and receiver pins */
251
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
252
  /* connect the pin to the peripherals alternate function */
253
  GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_USART1);
254
  GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_USART1);
255
  /* configure USART Tx as alternate function  */
256
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
257
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
258
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
259
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
260
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
261
  GPIO_Init(GPIOA, &GPIO_InitStructure);
262
  /* configure USART Rx as alternate function */
263
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
264
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
265
  GPIO_Init(GPIOA, &GPIO_InitStructure);
266
#endif
267

    
268
#if (BOOT_COM_BLUETOOTH_UART_ENABLE > 0)
269
  /* enable UART peripheral clock */
270
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);
271

    
272
  /* enable GPIO peripheral clock for transmitter and receiver pins */
273
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE);
274
  /* connect the pin to the peripherals alternate function */
275
  GPIO_PinAFConfig(GPIOC, GPIO_PinSource10, GPIO_AF_USART3);
276
  GPIO_PinAFConfig(GPIOC, GPIO_PinSource11, GPIO_AF_USART3);
277
  /* configure USART Tx as alternate function  */
278
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
279
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
280
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
281
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
282
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
283
  GPIO_Init(GPIOC, &GPIO_InitStructure);
284
  /* configure USART Rx as alternate function */
285
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
286
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
287
  GPIO_Init(GPIOC, &GPIO_InitStructure);
288

    
289
  /* Configure Bluetooth reset pin */
290
  GPIO_InitTypeDef  gpio_init;
291
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE);
292
  gpio_init.GPIO_Pin   = BT_RST_PIN;
293
  gpio_init.GPIO_OType = GPIO_OType_OD;
294
  gpio_init.GPIO_PuPd = GPIO_PuPd_NOPULL;
295
  gpio_init.GPIO_Mode = GPIO_Mode_OUT;
296
  gpio_init.GPIO_Speed = GPIO_Speed_50MHz;
297
  GPIO_Init(BT_RST_GPIO, &gpio_init);
298
  /* Reset Bluetooth reset pin */
299
  GPIO_ResetBits(BT_RST_GPIO, BT_RST_PIN);
300
#endif
301

    
302

    
303
#if (BOOT_COM_CAN_ENABLE > 0 || BOOT_GATE_CAN_ENABLE > 0)
304
  /* enable clocks for CAN transmitter and receiver pins */
305
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
306
  /* select alternate function for the CAN pins */
307
  GPIO_PinAFConfig(GPIOA, GPIO_PinSource11, GPIO_AF_CAN1);
308
  GPIO_PinAFConfig(GPIOA, GPIO_PinSource12, GPIO_AF_CAN1);
309
  /* configure CAN RX and TX pins */
310
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
311
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
312
  GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF;
313
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
314
  GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_NOPULL;
315
  GPIO_Init(GPIOA, &GPIO_InitStructure);
316
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
317
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
318
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
319
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
320
  GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_NOPULL;
321
  GPIO_Init(GPIOA, &GPIO_InitStructure);
322
#endif
323
} /*** end of Init ***/
324

    
325
/*
326
 * Initializes all GPIO used by the bootloader
327
 */
328
static void initGpio(void) {
329
  GPIO_InitTypeDef gpio_init;
330

    
331
  /*
332
   * OUTPUTS
333
   */
334

    
335
  /* initialize LED and push it up (inactive) */
336
  GPIO_SetBits(LED_GPIO, LED_PIN);
337
  gpio_init.GPIO_Pin    = LED_PIN;
338
  gpio_init.GPIO_Mode   = GPIO_Mode_OUT;
339
  gpio_init.GPIO_Speed  = GPIO_Speed_50MHz;
340
  gpio_init.GPIO_OType  = GPIO_OType_PP;
341
  gpio_init.GPIO_PuPd   = GPIO_PuPd_NOPULL;
342
  GPIO_Init(LED_GPIO, &gpio_init);
343

    
344
  /* initialize SYS_PD_N and push it up (inactive) */
345
  GPIO_SetBits(SYS_PD_N_GPIO, SYS_PD_N_PIN);
346
  gpio_init.GPIO_Pin    = SYS_PD_N_PIN;
347
  gpio_init.GPIO_Mode   = GPIO_Mode_OUT;
348
  gpio_init.GPIO_Speed  = GPIO_Speed_50MHz;
349
  gpio_init.GPIO_OType  = GPIO_OType_OD;
350
  gpio_init.GPIO_PuPd   = GPIO_PuPd_NOPULL;
351
  GPIO_Init(SYS_PD_N_GPIO, &gpio_init);
352

    
353
  /* initialize SYS_SYNC_N and pull it down (active) */
354
  GPIO_ResetBits(SYS_SYNC_N_GPIO, SYS_SYNC_N_PIN);
355
  gpio_init.GPIO_Pin    = SYS_SYNC_N_PIN;
356
  gpio_init.GPIO_Mode   = GPIO_Mode_OUT;
357
  gpio_init.GPIO_Speed  = GPIO_Speed_50MHz;
358
  gpio_init.GPIO_OType  = GPIO_OType_OD;
359
  gpio_init.GPIO_