Statistics
| Branch: | Tag: | Revision:

amiro-blt / Target / Modules / PowerManagement_1-1 / Boot / hooks.c @ 09ad5212

History | View | Annotate | Download (23.707 KB)

1
/************************************************************************************//**
2
* \file         Demo\ARMCM3_STM32_Olimex_STM32P103_GCC\Boot\hooks.c
3
* \brief        Bootloader callback 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
* 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
#if (BOOT_FILE_LOGGING_ENABLE > 0)
39
#include "stm32f4xx.h"                           /* STM32 registers                    */
40
#include "stm32f4xx_conf.h"                      /* STM32 peripheral drivers           */
41
#endif
42

    
43

    
44
/****************************************************************************************
45
*   B A C K D O O R   E N T R Y   H O O K   F U N C T I O N S
46
****************************************************************************************/
47

    
48
#if (BOOT_BACKDOOR_HOOKS_ENABLE > 0)
49

    
50
static blt_int32u backdoorOpenTime;
51
#define BACKDOOR_ENTRY_TIMEOUT_MS 500
52
static blt_bool timeRanOut = BLT_FALSE;
53
static blt_int32u osSyncTime;
54
#define OS_SYNC_MS 1
55
#define OS_WAIT_MS 1
56
enum BOOT_STATE {BOOT_FLASH_CHECK,
57
                 BOOT_FLASH_WAIT,
58
                 BOOT_OS_SYNC,
59
                 BOOT_OS_START,
60
                 BOOT_OS_WAIT
61
                } boot_state;
62

    
63
#define SYS_PD_N_PIN        GPIO_Pin_13
64
#define SYS_PD_N_GPIO       GPIOC
65
#define SYS_SYNC_N_PIN      GPIO_Pin_12
66
#define SYS_SYNC_N_GPIO     GPIOC
67
#define BT_RST_PIN          GPIO_Pin_15
68
#define BT_RST_GPIO         GPIOC
69

    
70
/************************************************************************************//**
71
** \brief     Initializes the backdoor entry option.
72
** \return    none.
73
**
74
****************************************************************************************/
75
void BackDoorInitHook(void)
76
{
77
  backdoorOpenTime = TimerGet();
78
  boot_state = BOOT_FLASH_CHECK;
79
} /*** end of BackDoorInitHook ***/
80

    
81

    
82
/************************************************************************************//**
83
** \brief     Checks if it has to stay in backdoor.
84
** \return    BLT_TRUE if the backdoor entry is requested, BLT_FALSE otherwise.
85
**
86
****************************************************************************************/
87
blt_bool BackDoorEntryCheck(void) {
88
  /* evaluate the fsm state */
89
  switch (boot_state) {
90
    case BOOT_FLASH_CHECK:
91
    {
92
      /* wait for a timeout */
93
      if (timeRanOut == BLT_FALSE) {
94
        if (TimerGet() > backdoorOpenTime+BACKDOOR_ENTRY_TIMEOUT_MS) {
95
          timeRanOut = BLT_TRUE;
96
          boot_state = BOOT_FLASH_WAIT;
97
          GPIO_SetBits(SYS_SYNC_N_GPIO, SYS_SYNC_N_PIN);
98
        }
99
      }
100
      return BLT_TRUE;
101
      break;
102
    }
103
    case BOOT_FLASH_WAIT:
104
    {
105
      /* wait for the SYS_SYNC_N signal to go up */
106
      if (GPIO_ReadInputDataBit(SYS_SYNC_N_GPIO, SYS_SYNC_N_PIN) == Bit_RESET) {
107
        return BLT_TRUE;
108
      } else {
109
        osSyncTime = TimerGet();
110
        boot_state = BOOT_OS_SYNC;
111
        return BLT_FALSE;
112
      }
113
      break;
114
    }
115
    default:
116
      return BLT_FALSE;
117
      break;
118
  }
119
  return BLT_FALSE;
120
}
121

    
122
/************************************************************************************//**
123
** \brief     Checks if a backdoor entry is requested.
124
** \return    BLT_TRUE if the backdoor entry is requested, BLT_FALSE otherwise.
125
**
126
****************************************************************************************/
127
blt_bool BackDoorEntryHook(void)
128
{
129
  /* default implementation always activates the bootloader after a reset */
130
  return BLT_TRUE;
131
} /*** end of BackDoorEntryHook ***/
132
#endif /* BOOT_BACKDOOR_HOOKS_ENABLE > 0 */
133

    
134

    
135
/************************************************************************************//**
136
** \brief     Notice that there is still an open connection over COM 
137
** \return    -
138
**
139
****************************************************************************************/
140
void BackDoorComIsConnected(void)
141
{
142
  backdoorOpenTime = TimerGet();
143
}
144

    
145

    
146
/****************************************************************************************
147
*   C P U   D R I V E R   H O O K   F U N C T I O N S
148
****************************************************************************************/
149

    
150
#if (BOOT_CPU_USER_PROGRAM_START_HOOK > 0)
151

    
152
#if (BOOT_COM_BLUETOOTH_UART_CHANNEL_INDEX == 0)
153
/** \brief Set BLUETOOTH UART base address to USART1. */
154
#define BLUETOOTH_USART_CHANNEL   USART1
155
#elif (BOOT_COM_BLUETOOTH_UART_CHANNEL_INDEX == 1)
156
/** \brief Set BLUETOOTH UART base address to USART2. */
157
#define BLUETOOTH_USART_CHANNEL   USART2
158
#elif (BOOT_COM_BLUETOOTH_UART_CHANNEL_INDEX == 2)
159
/** \brief Set BLUETOOTH UART base address to USART3. */
160
#define BLUETOOTH_USART_CHANNEL   USART3
161
#elif (BOOT_COM_BLUETOOTH_UART_CHANNEL_INDEX == 3)
162
/** \brief Set BLUETOOTH UART base address to USART4. */
163
#define BLUETOOTH_USART_CHANNEL   USART4
164
#elif (BOOT_COM_BLUETOOTH_UART_CHANNEL_INDEX == 4)
165
/** \brief Set BLUETOOTH UART base address to USART5. */
166
#define BLUETOOTH_USART_CHANNEL   USART5
167
#elif (BOOT_COM_BLUETOOTH_UART_CHANNEL_INDEX == 5)
168
/** \brief Set BLUETOOTH UART base address to USART6. */
169
#define BLUETOOTH_USART_CHANNEL   USART6
170
#endif
171
/************************************************************************************//**
172
** \brief     Callback that gets called when the bootloader is about to exit and
173
**            hand over control to the user program. This is the last moment that
174
**            some final checking can be performed and if necessary prevent the
175
**            bootloader from activiting the user program.
176
** \return    BLT_TRUE if it is okay to start the user program, BLT_FALSE to keep
177
**            keep the bootloader active.
178
**
179
****************************************************************************************/
180
blt_bool CpuUserProgramStartHook(void)
181
{
182
  /* evaluate the fsm state */
183
  switch (boot_state) {
184
    case BOOT_OS_SYNC:
185
    {
186
      /* wait some time so all modules can detect the high SYS_SYNC_N signal */
187

    
188
      GPIO_SetBits(BT_RST_GPIO, BT_RST_PIN);
189
      USART_Cmd(BLUETOOTH_USART_CHANNEL, DISABLE);
190
      USART_DeInit(BLUETOOTH_USART_CHANNEL);
191

    
192
      if (TimerGet() > osSyncTime + OS_SYNC_MS) {
193
        boot_state = BOOT_OS_START;
194
      }
195
      return BLT_FALSE;
196
      break;
197
    }
198
    case BOOT_OS_START:
199
    {
200
      /* pull down SYS_SYNC_N to indicate that all modules shall exit the bootloader and start the OS */
201

    
202
      GPIO_ResetBits(SYS_SYNC_N_GPIO, SYS_SYNC_N_PIN);
203
      osSyncTime = TimerGet();
204
      boot_state = BOOT_OS_WAIT;
205

    
206
      return BLT_FALSE;
207
      break;
208
    }
209
    case BOOT_OS_WAIT:
210
    {
211
      /* wait some time so all module can detect the low SYS_SYNC_N signal */
212

    
213
      if (TimerGet() > osSyncTime + OS_WAIT_MS) {
214
        return BLT_TRUE;
215
      } else {
216
        return BLT_FALSE;
217
      }
218
    }
219
    default:
220
      return BLT_FALSE;
221
      break;
222
  }
223

    
224
  /* okay to start the user program */
225
  return BLT_TRUE;
226
} /*** end of CpuUserProgramStartHook ***/
227
#endif /* BOOT_CPU_USER_PROGRAM_START_HOOK > 0 */
228

    
229

    
230
/****************************************************************************************
231
*   N O N - V O L A T I L E   M E M O R Y   D R I V E R   H O O K   F U N C T I O N S
232
****************************************************************************************/
233

    
234
#if (BOOT_NVM_HOOKS_ENABLE > 0)
235
/************************************************************************************//**
236
** \brief     Callback that gets called at the start of the internal NVM driver
237
**            initialization routine. 
238
** \return    none.
239
**
240
****************************************************************************************/
241
void NvmInitHook(void)
242
{
243
} /*** end of NvmInitHook ***/
244

    
245

    
246
/************************************************************************************//**
247
** \brief     Callback that gets called at the start of the NVM driver write 
248
**            routine. It allows additional memory to be operated on. If the address
249
**            is not within the range of the additional memory, then 
250
**            BLT_NVM_NOT_IN_RANGE must be returned to indicate that the data hasn't
251
**            been written yet.
252
** \param     addr Start address.
253
** \param     len  Length in bytes.
254
** \param     data Pointer to the data buffer.
255
** \return    BLT_NVM_OKAY if successful, BLT_NVM_NOT_IN_RANGE if the address is
256
**            not within the supported memory range, or BLT_NVM_ERROR is the write
257
**            operation failed.
258
**
259
****************************************************************************************/
260
blt_int8u NvmWriteHook(blt_addr addr, blt_int32u len, blt_int8u *data)
261
{
262
  return BLT_NVM_NOT_IN_RANGE;
263
} /*** end of NvmWriteHook ***/
264

    
265

    
266
/************************************************************************************//**
267
** \brief     Callback that gets called at the start of the NVM driver erase 
268
**            routine. It allows additional memory to be operated on. If the address
269
**            is not within the range of the additional memory, then
270
**            BLT_NVM_NOT_IN_RANGE must be returned to indicate that the memory
271
**            hasn't been erased yet.
272
** \param     addr Start address.
273
** \param     len  Length in bytes.
274
** \return    BLT_NVM_OKAY if successful, BLT_NVM_NOT_IN_RANGE if the address is
275
**            not within the supported memory range, or BLT_NVM_ERROR is the erase
276
**            operation failed.
277
**
278
****************************************************************************************/
279
blt_int8u NvmEraseHook(blt_addr addr, blt_int32u len)
280
{
281
  return BLT_NVM_NOT_IN_RANGE;
282
} /*** end of NvmEraseHook ***/
283

    
284

    
285
/************************************************************************************//**
286
** \brief     Callback that gets called at the end of the NVM programming session.
287
** \return    BLT_TRUE is successful, BLT_FALSE otherwise.
288
**
289
****************************************************************************************/
290
blt_bool NvmDoneHook(void)
291
{
292
  return BLT_TRUE;
293
} /*** end of NvmDoneHook ***/
294
#endif /* BOOT_NVM_HOOKS_ENABLE > 0 */
295

    
296

    
297
#if (BOOT_NVM_CHECKSUM_HOOKS_ENABLE > 0)
298
/************************************************************************************//**
299
** \brief     Verifies the checksum, which indicates that a valid user program is
300
**            present and can be started.
301
** \return    BLT_TRUE if successful, BLT_FALSE otherwise.
302
**
303
****************************************************************************************/
304
blt_bool NvmVerifyChecksumHook(void)
305
{
306
  return BLT_TRUE;
307
} /*** end of NvmVerifyChecksum ***/
308

    
309

    
310
/************************************************************************************//**
311
** \brief     Writes a checksum of the user program to non-volatile memory. This is
312
**            performed once the entire user program has been programmed. Through
313
**            the checksum, the bootloader can check if a valid user programming is
314
**            present and can be started.
315
** \return    BLT_TRUE if successful, BLT_FALSE otherwise. 
316
**
317
****************************************************************************************/
318
blt_bool NvmWriteChecksumHook(void)
319
{
320
  return BLT_TRUE;
321
}
322
#endif /* BOOT_NVM_CHECKSUM_HOOKS_ENABLE > 0 */
323

    
324

    
325
/****************************************************************************************
326
*   W A T C H D O G   D R I V E R   H O O K   F U N C T I O N S
327
****************************************************************************************/
328

    
329
#if (BOOT_COP_HOOKS_ENABLE > 0)
330
/************************************************************************************//**
331
** \brief     Callback that gets called at the end of the internal COP driver
332
**            initialization routine. It can be used to configure and enable the
333
**            watchdog.
334
** \return    none.
335
**
336
****************************************************************************************/
337
void CopInitHook(void)
338
{
339
} /*** end of CopInitHook ***/
340

    
341

    
342
/************************************************************************************//**
343
** \brief     Callback that gets called at the end of the internal COP driver
344
**            service routine. This gets called upon initialization and during
345
**            potential long lasting loops and routine. It can be used to service
346
**            the watchdog to prevent a watchdog reset.
347
** \return    none.
348
**
349
****************************************************************************************/
350
void CopServiceHook(void)
351
{
352
} /*** end of CopServiceHook ***/
353
#endif /* BOOT_COP_HOOKS_ENABLE > 0 */
354

    
355

    
356
/****************************************************************************************
357
*   F I L E   S Y S T E M   I N T E R F A C E   H O O K   F U N C T I O N S
358
****************************************************************************************/
359

    
360
#if (BOOT_FILE_SYS_ENABLE > 0)
361

    
362
/****************************************************************************************
363
* Constant data declarations
364
****************************************************************************************/
365
/** \brief Firmware filename. */
366
static const blt_char firmwareFilename[] = "/demoprog_olimex_stm32p103.srec";
367

    
368

    
369
/****************************************************************************************
370
* Local data declarations
371
****************************************************************************************/
372
#if (BOOT_FILE_LOGGING_ENABLE > 0)
373
/** \brief Data structure for grouping log-file related information. */
374
static struct 
375
{
376
  FIL      handle;                  /**< FatFS handle to the log-file.                 */
377
  blt_bool canUse;                  /**< Flag to indicate if the log-file can be used. */
378
} logfile;
379
#endif
380

    
381

    
382
/************************************************************************************//**
383
** \brief     Callback that gets called to check whether a firmware update from 
384
**            local file storage should be started. This could for example be when
385
**            a switch is pressed, when a certain file is found on the local file 
386
**            storage, etc.
387
** \return    BLT_TRUE if a firmware update is requested, BLT_FALSE otherwise.
388
**
389
****************************************************************************************/
390
blt_bool FileIsFirmwareUpdateRequestedHook(void)
391
{
392
  FILINFO fileInfoObject = { 0 }; /* needs to be zeroed according to f_stat docs */;
393

    
394
  /* Current example implementation looks for a predetermined firmware file on the 
395
   * SD-card. If the SD-card is accessible and the firmware file was found the firmware
396
   * update is started. When successfully completed, the firmware file is deleted.
397
   * During the firmware update, progress information is written to a file called
398
   * bootlog.txt and additionally outputted on UART @57600 bps for debugging purposes.
399
   */
400
  /* check if firmware file is present and SD-card is accessible */
401
  if (f_stat(firmwareFilename, &fileInfoObject) == FR_OK) 
402
  {
403
    /* check if the filesize is valid and that it is not a directory */
404
    if ( (fileInfoObject.fsize > 0) && (!(fileInfoObject.fattrib & AM_DIR)) )
405
    {
406
      /* all conditions are met to start a firmware update from local file storage */
407
      return BLT_TRUE;
408
    }
409
  }
410
  /* still here so no firmware update request is pending */  
411
  return BLT_FALSE;
412
} /*** end of FileIsFirmwareUpdateRequestedHook ***/
413

    
414

    
415
/************************************************************************************//**
416
** \brief     Callback to obtain the filename of the firmware file that should be
417
**            used during the firmware update from the local file storage. This 
418
**            hook function is called at the beginning of the firmware update from
419
**            local storage sequence. 
420
** \return    valid firmware filename with full path or BLT_NULL.
421
**
422
****************************************************************************************/
423
const blt_char *FileGetFirmwareFilenameHook(void)
424
{
425
  return firmwareFilename;
426
} /*** end of FileGetFirmwareFilenameHook ***/
427

    
428

    
429
#if (BOOT_FILE_STARTED_HOOK_ENABLE > 0)
430
/************************************************************************************//**
431
** \brief     Callback that gets called to inform the application that a firmware
432
**            update from local storage just started. 
433
** \return    none.
434
**
435
****************************************************************************************/
436
void FileFirmwareUpdateStartedHook(void)
437
{
438
  #if (BOOT_FILE_LOGGING_ENABLE > 0)
439
  /* create/overwrite the logfile */
440
  logfile.canUse = BLT_FALSE;
441
  if (f_open(&logfile.handle, "/bootlog.txt", FA_CREATE_ALWAYS | FA_WRITE) == FR_OK)
442
  {
443
    logfile.canUse = BLT_TRUE;
444
  }
445
  #endif
446
} /*** end of FileFirmwareUpdateStartedHook ***/
447
#endif /* BOOT_FILE_STARTED_HOOK_ENABLE > 0 */
448

    
449

    
450
#if (BOOT_FILE_COMPLETED_HOOK_ENABLE > 0)
451
/************************************************************************************//**
452
** \brief     Callback that gets called to inform the application that a firmware
453
**            update was successfully completed.
454
** \return    none.
455
**
456
****************************************************************************************/
457
void FileFirmwareUpdateCompletedHook(void)
458
{
459
  #if (BOOT_FILE_LOGGING_ENABLE > 0)
460
  /* close the log file */
461
  if (logfile.canUse == BLT_TRUE)
462
  {
463
    f_close(&logfile.handle);
464
  }
465
  /* wait for all logging related transmission to complete */
466
  while(USART_GetFlagStatus(USART2, USART_FLAG_TC) == RESET);
467
  #endif
468
  /* now delete the firmware file from the disk since the update was successful */
469
  f_unlink(firmwareFilename);
470
} /*** end of FileFirmwareUpdateCompletedHook ***/
471
#endif /* BOOT_FILE_COMPLETED_HOOK_ENABLE > 0 */
472

    
473

    
474
#if (BOOT_FILE_ERROR_HOOK_ENABLE > 0)
475
/************************************************************************************//**
476
** \brief     Callback that gets called in case an error occurred during a firmware
477
**            update. Refer to <file.h> for a list of available error codes.
478
** \return    none.
479
**
480
****************************************************************************************/
481
void FileFirmwareUpdateErrorHook(blt_int8u error_code)
482
{
483
  #if (BOOT_FILE_LOGGING_ENABLE > 0)
484
  /* error detected which stops the firmware update, so close the log file */
485
  if (logfile.canUse == BLT_TRUE)
486
  {
487
    f_close(&logfile.handle);
488
  }
489
  #endif
490
} /*** end of FileFirmwareUpdateErrorHook ***/
491
#endif /* BOOT_FILE_ERROR_HOOK_ENABLE > 0 */
492

    
493

    
494
#if (BOOT_FILE_LOGGING_ENABLE > 0)
495
/************************************************************************************//**
496
** \brief     Callback that gets called each time new log information becomes 
497
**            available during a firmware update.
498
** \param     info_string Pointer to a character array with the log entry info.
499
** \return    none.
500
**
501
****************************************************************************************/
502
void FileFirmwareUpdateLogHook(blt_char *info_string)
503
{
504
  /* write the string to the log file */
505
  if (logfile.canUse == BLT_TRUE)
506
  {
507
    if (f_puts(info_string, &logfile.handle) < 0)
508
    {
509
      logfile.canUse = BLT_FALSE;
510
      f_close(&logfile.handle);
511
    }
512
  }
513
  /* echo all characters in the string on UART */
514
  while(*info_string != '\0')
515
  {
516
    /* write character to transmit holding register */
517
    USART_SendData(USART2, *info_string);
518
    /* wait for tx holding register to be empty */
519
    while(USART_GetFlagStatus(USART2, USART_FLAG_TXE) == RESET);
520
    /* point to the next character in the string */
521
    info_string++;
522
  }
523
} /*** end of FileFirmwareUpdateLogHook ***/
524
#endif /* BOOT_FILE_LOGGING_ENABLE > 0 */
525

    
526

    
527
#endif /* BOOT_FILE_SYS_ENABLE > 0 */
528

    
529

    
530
/****************************************************************************************
531
*   S E E D / K E Y   S E C U R I T Y   H O O K   F U N C T I O N S
532
****************************************************************************************/
533

    
534
#if (BOOT_XCP_SEED_KEY_ENABLE > 0)
535
/************************************************************************************//**
536
** \brief     Provides a seed to the XCP master that will be used for the key 
537
**            generation when the master attempts to unlock the specified resource. 
538
**            Called by the GET_SEED command.
539
** \param     resource  Resource that the seed if requested for (XCP_RES_XXX).
540
** \param     seed      Pointer to byte buffer wher the seed will be stored.
541
** \return    Length of the seed in bytes.
542
**
543
****************************************************************************************/
544
blt_int8u XcpGetSeedHook(blt_int8u resource, blt_int8u *seed)
545
{
546
  /* request seed for unlocking ProGraMming resource */
547
  if ((resource & XCP_RES_PGM) != 0)
548
  {
549
    seed[0] = 0x55;
550
  }
551

    
552
  /* return seed length */
553
  return 1;
554
} /*** end of XcpGetSeedHook ***/
555

    
556

    
557
/************************************************************************************//**
558
** \brief     Called by the UNLOCK command and checks if the key to unlock the 
559
**            specified resource was correct. If so, then the resource protection 
560
**            will be removed.
561
** \param     resource  resource to unlock (XCP_RES_XXX).
562
** \param     key       pointer to the byte buffer holding the key.
563
** \param     len       length of the key in bytes.
564
** \return    1 if the key was correct, 0 otherwise.
565
**
566
****************************************************************************************/
567
blt_int8u XcpVerifyKeyHook(blt_int8u resource, blt_int8u *key, blt_int8u len)
568
{
569
  /* suppress compiler warning for unused parameter */
570
  len = len;
571

    
572
  /* the example key algorithm in "FeaserKey.dll" works as follows:
573
   *  - PGM will be unlocked if key = seed - 1
574
   */
575

    
576
  /* check key for unlocking ProGraMming resource */
577
  if ((resource == XCP_RES_PGM) && (key[0] == (0x55-1)))
578
  {
579
    /* correct key received for unlocking PGM resource */
580
    return 1;
581
  }
582

    
583
  /* still here so key incorrect */
584
  return 0;
585
} /*** end of XcpVerifyKeyHook ***/
586
#endif /* BOOT_XCP_SEED_KEY_ENABLE > 0 */
587

    
588

    
589
/*********************************** end of hooks.c ************************************/