openblt/Target/Source/ARMCM0_STM32/cpu.c

161 lines
6.8 KiB
C

/************************************************************************************//**
* \file Source\ARMCM0_STM32\cpu.c
* \brief Bootloader cpu module source file.
* \ingroup Target_ARMCM0_STM32
* \internal
*----------------------------------------------------------------------------------------
* C O P Y R I G H T
*----------------------------------------------------------------------------------------
* Copyright (c) 2016 by Feaser http://www.feaser.com All rights reserved
*
*----------------------------------------------------------------------------------------
* L I C E N S E
*----------------------------------------------------------------------------------------
* This file is part of OpenBLT. OpenBLT is free software: you can redistribute it and/or
* modify it under the terms of the GNU General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any later
* version.
*
* OpenBLT is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You have received a copy of the GNU General Public License along with OpenBLT. It
* should be located in ".\Doc\license.html". If not, contact Feaser to obtain a copy.
*
* \endinternal
****************************************************************************************/
/****************************************************************************************
* Include files
****************************************************************************************/
#include "boot.h" /* bootloader generic header */
#include "stm32f0xx.h" /* for STM32F0 registers and drivers */
/****************************************************************************************
* Macro definitions
****************************************************************************************/
/** \brief Pointer to the user program's reset vector. */
#define CPU_USER_PROGRAM_STARTADDR_PTR ((blt_addr)(NvmGetUserProgBaseAddress() + 0x00000004))
/** \brief Pointer to the user program's vector table. */
#define CPU_USER_PROGRAM_VECTABLE_OFFSET ((blt_int32u)NvmGetUserProgBaseAddress())
/** \brief Size in bytes of the user program's vector table */
#define CPU_USER_PROGRAM_VECTABLE_SIZE (0xC0u)
/** \brief Start address of the user program's RAM where its vector table will be copied
* to.
*/
#define CPU_USER_PROGRAM_RAM_BASEADDR ((blt_addr)(0x20000000))
/****************************************************************************************
* Hook functions
****************************************************************************************/
#if (BOOT_CPU_USER_PROGRAM_START_HOOK > 0)
extern blt_bool CpuUserProgramStartHook(void);
#endif
/****************************************************************************************
* External functions
****************************************************************************************/
extern void Reset_Handler(void); /* implemented in C-startup */
/************************************************************************************//**
** \brief Starts the user program, if one is present. In this case this function
** does not return.
** \return none.
**
****************************************************************************************/
void CpuStartUserProgram(void)
{
void (*pProgResetHandler)(void);
/* check if a user program is present by verifying the checksum */
if (NvmVerifyChecksum() == BLT_FALSE)
{
/* not a valid user program so it cannot be started */
return;
}
#if (BOOT_CPU_USER_PROGRAM_START_HOOK > 0)
/* invoke callback */
if (CpuUserProgramStartHook() == BLT_FALSE)
{
/* callback requests the user program to not be started */
return;
}
#endif
#if (BOOT_COM_ENABLE > 0)
/* release the communication interface */
ComFree();
#endif
/* reset the timer */
TimerReset();
/* enable system configuration peripheral, which is needed to remap the RAM later on */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
/* copy user program vector's to RAM */
CpuMemCopy(CPU_USER_PROGRAM_RAM_BASEADDR, CPU_USER_PROGRAM_VECTABLE_OFFSET,
CPU_USER_PROGRAM_VECTABLE_SIZE);
/* remap RAM so that it also appears at address 0x00000000. this way the user program's
* vector table in RAM is used instead of the bootloader's vector table in flash.
*/
SYSCFG_MemoryRemapConfig(SYSCFG_MemoryRemap_SRAM);
/* set the address where the bootloader needs to jump to. this is the address of
* the 2nd entry in the user program's vector table. this address points to the
* user program's reset handler.
*/
pProgResetHandler = (void(*)(void))(*((blt_addr *)CPU_USER_PROGRAM_STARTADDR_PTR));
/* The Cortex-M0 core has interrupts enabled out of reset. the bootloader
* explicitly disables these for security reasons in the C-startup.
* Enable them here again, so it does not have to be done by the user
* program.
*/
__enable_irq();
/* start the user program by activating its reset interrupt service routine */
pProgResetHandler();
} /*** end of CpuStartUserProgram ***/
/************************************************************************************//**
** \brief Copies data from the source to the destination address.
** \param dest Destination address for the data.
** \param src Source address of the data.
** \param len length of the data in bytes.
** \return none.
**
****************************************************************************************/
void CpuMemCopy(blt_addr dest, blt_addr src, blt_int16u len)
{
blt_int8u *from, *to;
/* set casted pointers */
from = (blt_int8u *)src;
to = (blt_int8u *)dest;
/* copy all bytes from source address to destination address */
while (len-- > 0)
{
/* store byte value from source to destination */
*to++ = *from++;
/* keep the watchdog happy */
CopService();
}
} /*** end of CpuMemCopy ***/
/************************************************************************************//**
** \brief Perform a soft reset of the microcontroller by starting from the reset ISR.
** \return none.
**
****************************************************************************************/
void CpuReset(void)
{
/* perform a software reset by calling the reset ISR routine */
Reset_Handler();
} /*** end of CpuReset ***/
/*********************************** end of cpu.c **************************************/