This commit is contained in:
2022-12-20 16:18:47 +01:00
commit b10a4500d2
141 changed files with 142607 additions and 0 deletions

View File

@@ -0,0 +1,56 @@
/************************************************************************************//**
* \file Source/ARMCM4_STM32L4/GCC/cpu_comp.c
* \brief Bootloader cpu module source file.
* \ingroup Target_ARMCM4_STM32L4
* \internal
*----------------------------------------------------------------------------------------
* C O P Y R I G H T
*----------------------------------------------------------------------------------------
* Copyright (c) 2018 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 */
/************************************************************************************//**
** \brief Disable global interrupts.
** \return none.
**
****************************************************************************************/
void CpuIrqDisable(void)
{
__asm volatile ("cpsid i");
} /*** end of CpuIrqDisable ***/
/************************************************************************************//**
** \brief Enable global interrupts.
** \return none.
**
****************************************************************************************/
void CpuIrqEnable(void)
{
__asm volatile ("cpsie i");
} /*** end of CpuIrqEnable ***/
/*********************************** end of cpu_comp.c *********************************/

View File

@@ -0,0 +1,350 @@
/************************************************************************************//**
* \file Source/ARMCM4_STM32L4/can.c
* \brief Bootloader CAN communication interface source file.
* \ingroup Target_ARMCM4_STM32L4
* \internal
*----------------------------------------------------------------------------------------
* C O P Y R I G H T
*----------------------------------------------------------------------------------------
* Copyright (c) 2018 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 */
#if (BOOT_COM_CAN_ENABLE > 0)
#include "stm32l4xx.h" /* STM32 CPU and HAL header */
#include "stm32l4xx_ll_gpio.h" /* STM32 LL GPIO header */
/****************************************************************************************
* Macro definitions
****************************************************************************************/
/** \brief Timeout for transmitting a CAN message in milliseconds. */
#define CAN_MSG_TX_TIMEOUT_MS (50u)
/****************************************************************************************
* Type definitions
****************************************************************************************/
/** \brief Structure type for grouping CAN bus timing related information. */
typedef struct t_can_bus_timing
{
blt_int8u tseg1; /**< CAN time segment 1 */
blt_int8u tseg2; /**< CAN time segment 2 */
} tCanBusTiming;
/****************************************************************************************
* Local constant declarations
****************************************************************************************/
/** \brief CAN bittiming table for dynamically calculating the bittiming settings.
* \details According to the CAN protocol 1 bit-time can be made up of between 8..25
* time quanta (TQ). The total TQ in a bit is SYNC + TSEG1 + TSEG2 with SYNC
* always being 1. The sample point is (SYNC + TSEG1) / (SYNC + TSEG1 + SEG2) *
* 100%. This array contains possible and valid time quanta configurations with
* a sample point between 68..78%.
*/
static const tCanBusTiming canTiming[] =
{
/* TQ | TSEG1 | TSEG2 | SP */
/* ------------------------- */
{ 5, 2 }, /* 8 | 5 | 2 | 75% */
{ 6, 2 }, /* 9 | 6 | 2 | 78% */
{ 6, 3 }, /* 10 | 6 | 3 | 70% */
{ 7, 3 }, /* 11 | 7 | 3 | 73% */
{ 8, 3 }, /* 12 | 8 | 3 | 75% */
{ 9, 3 }, /* 13 | 9 | 3 | 77% */
{ 9, 4 }, /* 14 | 9 | 4 | 71% */
{ 10, 4 }, /* 15 | 10 | 4 | 73% */
{ 11, 4 }, /* 16 | 11 | 4 | 75% */
{ 12, 4 }, /* 17 | 12 | 4 | 76% */
{ 12, 5 }, /* 18 | 12 | 5 | 72% */
{ 13, 5 }, /* 19 | 13 | 5 | 74% */
{ 14, 5 }, /* 20 | 14 | 5 | 75% */
{ 15, 5 }, /* 21 | 15 | 5 | 76% */
{ 15, 6 }, /* 22 | 15 | 6 | 73% */
{ 16, 6 }, /* 23 | 16 | 6 | 74% */
{ 16, 7 }, /* 24 | 16 | 7 | 71% */
{ 16, 8 } /* 25 | 16 | 8 | 68% */
};
/****************************************************************************************
* Local data declarations
****************************************************************************************/
/** \brief CAN handle to be used in API calls. */
static CAN_HandleTypeDef canHandle;
static uint8_t TECID = 0x00;
/************************************************************************************//**
** \brief Search algorithm to match the desired baudrate to a possible bus
** timing configuration.
** \param baud The desired baudrate in kbps. Valid values are 10..1000.
** \param prescaler Pointer to where the value for the prescaler will be stored.
** \param tseg1 Pointer to where the value for TSEG2 will be stored.
** \param tseg2 Pointer to where the value for TSEG2 will be stored.
** \return BLT_TRUE if the CAN bustiming register values were found, BLT_FALSE
** otherwise.
**
****************************************************************************************/
static blt_bool CanGetSpeedConfig(blt_int16u baud, blt_int16u *prescaler,
blt_int8u *tseg1, blt_int8u *tseg2)
{
blt_int8u cnt;
blt_int32u canClockFreqkHz;
/* store CAN peripheral clock speed in kHz */
canClockFreqkHz = HAL_RCC_GetPCLK1Freq() / 1000u;
/* loop through all possible time quanta configurations to find a match */
for (cnt=0; cnt < sizeof(canTiming)/sizeof(canTiming[0]); cnt++)
{
if ((canClockFreqkHz % (baud*(canTiming[cnt].tseg1+canTiming[cnt].tseg2+1))) == 0)
{
/* compute the prescaler that goes with this TQ configuration */
*prescaler = canClockFreqkHz/(baud*(canTiming[cnt].tseg1+canTiming[cnt].tseg2+1));
/* make sure the prescaler is valid */
if ((*prescaler > 0) && (*prescaler <= 1024))
{
/* store the bustiming configuration */
*tseg1 = canTiming[cnt].tseg1;
*tseg2 = canTiming[cnt].tseg2;
/* found a good bus timing configuration */
return BLT_TRUE;
}
}
}
/* could not find a good bus timing configuration */
return BLT_FALSE;
} /*** end of CanGetSpeedConfig ***/
/************************************************************************************//**
** \brief Initializes the CAN controller and synchronizes it to the CAN bus.
** \return none.
**
****************************************************************************************/
void CanInit(void)
{
blt_int16u prescaler = 0;
blt_int8u tseg1 = 0, tseg2 = 0;
CAN_FilterTypeDef filterConfig;
blt_int32u rxMsgId = BOOT_COM_CAN_RX_MSG_ID;
blt_int32u rxFilterId, rxFilterMask;
/* the current implementation supports CAN1. throw an assertion error in case a
* different CAN channel is configured.
*/
ASSERT_CT(BOOT_COM_CAN_CHANNEL_INDEX == 0);
/* obtain bittiming configuration information. */
if (CanGetSpeedConfig(BOOT_COM_CAN_BAUDRATE/1000, &prescaler, &tseg1, &tseg2) == BLT_FALSE)
{
/* Incorrect configuration. The specified baudrate is not supported for the given
* clock configuration. Verify the following settings in blt_conf.h:
* - BOOT_COM_CAN_BAUDRATE
* - BOOT_CPU_XTAL_SPEED_KHZ
* - BOOT_CPU_SYSTEM_SPEED_KHZ
*/
ASSERT_RT(BLT_FALSE);
}
/* set the CAN controller configuration. */
canHandle.Instance = CAN;
canHandle.Init.TimeTriggeredMode = DISABLE;
canHandle.Init.AutoBusOff = DISABLE;
canHandle.Init.AutoWakeUp = DISABLE;
canHandle.Init.AutoRetransmission = ENABLE;
canHandle.Init.ReceiveFifoLocked = DISABLE;
canHandle.Init.TransmitFifoPriority = DISABLE;
canHandle.Init.Mode = CAN_MODE_NORMAL;
canHandle.Init.SyncJumpWidth = CAN_SJW_1TQ;
canHandle.Init.TimeSeg1 = ((blt_int32u)tseg1 - 1) << CAN_BTR_TS1_Pos;
canHandle.Init.TimeSeg2 = ((blt_int32u)tseg2 - 1) << CAN_BTR_TS2_Pos;
canHandle.Init.Prescaler = prescaler;
/* initialize the CAN controller. this only fails if the CAN controller hardware is
* faulty. no need to evaluate the return value as there is nothing we can do about
* a faulty CAN controller.
*/
(void)HAL_CAN_Init(&canHandle);
/* determine the reception filter mask and id values such that it only leaves one
* CAN identifier through (BOOT_COM_CAN_RX_MSG_ID).
*/
/*
* Read TEC ID
*/
uint8_t BIT0, BIT1, BIT2, BIT3;
BIT0 = LL_GPIO_IsInputPinSet(GPIOA, LL_GPIO_PIN_15);
BIT1 = LL_GPIO_IsInputPinSet(GPIOB, LL_GPIO_PIN_4);
BIT2 = LL_GPIO_IsInputPinSet(GPIOB, LL_GPIO_PIN_3);
BIT3 = LL_GPIO_IsInputPinSet(GPIOC, LL_GPIO_PIN_15);
TECID = (BIT0 <<0) | (BIT1 <<1) | (BIT2 <<2) | (BIT3 <<3);
rxMsgId |= TECID;
if ((rxMsgId & 0x80000000) == 0)
{
rxFilterId = rxMsgId << CAN_RI0R_STID_Pos;
rxFilterMask = (CAN_RI0R_STID_Msk) | CAN_RI0R_IDE;
}
else
{
/* negate the ID-type bit */
rxMsgId &= ~0x80000000;
rxFilterId = (rxMsgId << CAN_RI0R_EXID_Pos) | CAN_RI0R_IDE;
rxFilterMask = (CAN_RI0R_EXID_Msk) | CAN_RI0R_IDE;
}
/* configure the reception filter. note that the implementation of this function
* always returns HAL_OK, so no need to evaluate the return value.
*/
filterConfig.FilterBank = 0;
filterConfig.FilterMode = CAN_FILTERMODE_IDMASK;
filterConfig.FilterScale = CAN_FILTERSCALE_32BIT;
filterConfig.FilterIdHigh = (rxFilterId >> 16) & 0x0000FFFFu;
filterConfig.FilterIdLow = rxFilterId & 0x0000FFFFu;
filterConfig.FilterMaskIdHigh = (rxFilterMask >> 16) & 0x0000FFFFu;
filterConfig.FilterMaskIdLow = rxFilterMask & 0x0000FFFFu;
filterConfig.FilterFIFOAssignment = CAN_RX_FIFO0;
filterConfig.FilterActivation = ENABLE;
filterConfig.SlaveStartFilterBank = 14;
(void)HAL_CAN_ConfigFilter(&canHandle, &filterConfig);
/* start the CAN peripheral. no need to evaluate the return value as there is nothing
* we can do about a faulty CAN controller. */
(void)HAL_CAN_Start(&canHandle);
} /*** end of CanInit ***/
/************************************************************************************//**
** \brief Transmits a packet formatted for the communication interface.
** \param data Pointer to byte array with data that it to be transmitted.
** \param len Number of bytes that are to be transmitted.
** \return none.
**
****************************************************************************************/
void CanTransmitPacket(blt_int8u *data, blt_int8u len)
{
blt_int32u txMsgId = BOOT_COM_CAN_TX_MSG_ID;
CAN_TxHeaderTypeDef txMsgHeader;
blt_int32u txMsgMailbox;
blt_int32u timeout;
HAL_StatusTypeDef txStatus;
txMsgId |= TECID;
/* configure the message that should be transmitted. */
if ((txMsgId & 0x80000000) == 0)
{
/* set the 11-bit CAN identifier. */
txMsgHeader.StdId = txMsgId;
txMsgHeader.IDE = CAN_ID_STD;
}
else
{
/* negate the ID-type bit */
txMsgId &= ~0x80000000;
/* set the 29-bit CAN identifier. */
txMsgHeader.ExtId = txMsgId;
txMsgHeader.IDE = CAN_ID_EXT;
}
txMsgHeader.RTR = CAN_RTR_DATA;
txMsgHeader.DLC = len;
/* submit the message for transmission. */
txStatus = HAL_CAN_AddTxMessage(&canHandle, &txMsgHeader, data,
(uint32_t *)&txMsgMailbox);
if (txStatus == HAL_OK)
{
/* determine timeout time for the transmit completion. */
timeout = TimerGet() + CAN_MSG_TX_TIMEOUT_MS;
/* poll for completion of the transmit operation. */
while (HAL_CAN_IsTxMessagePending(&canHandle, txMsgMailbox) != 0)
{
/* service the watchdog. */
CopService();
/* break loop upon timeout. this would indicate a hardware failure or no other
* nodes connected to the bus.
*/
if (TimerGet() > timeout)
{
break;
}
}
}
} /*** end of CanTransmitPacket ***/
/************************************************************************************//**
** \brief Receives a communication interface packet if one is present.
** \param data Pointer to byte array where the data is to be stored.
** \param len Pointer where the length of the packet is to be stored.
** \return BLT_TRUE is a packet was received, BLT_FALSE otherwise.
**
****************************************************************************************/
blt_bool CanReceivePacket(blt_int8u *data, blt_int8u *len)
{
blt_int32u rxMsgId = BOOT_COM_CAN_RX_MSG_ID;
blt_bool result = BLT_FALSE;
CAN_RxHeaderTypeDef rxMsgHeader;
rxMsgId |= TECID;
if (HAL_CAN_GetRxMessage(&canHandle, CAN_RX_FIFO0, &rxMsgHeader, data) == HAL_OK)
{
/* check if this message has the configured CAN packet identifier. */
if ((rxMsgId & 0x80000000) == 0)
{
/* was an 11-bit CAN message received that matches? */
if ( (rxMsgHeader.StdId == rxMsgId) &&
(rxMsgHeader.IDE == CAN_ID_STD) )
{
/* set flag that a packet with a matching CAN identifier was received. */
result = BLT_TRUE;
}
}
else
{
/* negate the ID-type bit. */
rxMsgId &= ~0x80000000;
/* was an 29-bit CAN message received that matches? */
if ( (rxMsgHeader.ExtId == rxMsgId) &&
(rxMsgHeader.IDE == CAN_ID_EXT) )
{
/* set flag that a packet with a matching CAN identifier was received. */
result = BLT_TRUE;
}
}
}
/* store the data length. */
if (result == BLT_TRUE)
{
*len = rxMsgHeader.DLC;
}
/* Give the result back to the caller. */
return result;
} /*** end of CanReceivePacket ***/
#endif /* BOOT_COM_CAN_ENABLE > 0 */
/*********************************** end of can.c **************************************/

View File

@@ -0,0 +1,195 @@
/************************************************************************************//**
* \file Source/ARMCM4_STM32L4/cpu.c
* \brief Bootloader cpu module source file.
* \ingroup Target_ARMCM4_STM32L4
* \internal
*----------------------------------------------------------------------------------------
* C O P Y R I G H T
*----------------------------------------------------------------------------------------
* Copyright (c) 2018 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 "stm32l4xx.h" /* STM32 CPU and HAL header */
/****************************************************************************************
* 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())
/****************************************************************************************
* Hook functions
****************************************************************************************/
#if (BOOT_CPU_USER_PROGRAM_START_HOOK > 0)
extern blt_bool CpuUserProgramStartHook(void);
#endif
/************************************************************************************//**
** \brief Initializes the CPU module.
** \return none.
**
****************************************************************************************/
void CpuInit(void)
{
/* bootloader runs in polling mode so disable the global interrupts. this is done for
* safety reasons. if the bootloader was started from a running user program, it could
* be that the user program did not properly disable the interrupt generation of
* peripherals.
*/
CpuIrqDisable();
} /*** end of CpuInit ***/
/************************************************************************************//**
** \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)
{
#if (BOOT_COM_DEFERRED_INIT_ENABLE > 0) && (BOOT_COM_ENABLE > 0)
/* bootloader will stay active so perform deferred initialization to make sure
* the communication interface that were not yet initialized are now initialized.
* this is needed to make sure firmware updates via these communication interfaces
* will be possible.
*/
ComDeferredInit();
#endif
/* 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)
{
#if (BOOT_COM_DEFERRED_INIT_ENABLE > 0) && (BOOT_COM_ENABLE > 0)
/* bootloader will stay active so perform deferred initialization to make sure
* the communication interface that were not yet initialized are now initialized.
* this is needed to make sure firmware updates via these communication interfaces
* will be possible.
*/
ComDeferredInit();
#endif
/* callback requests the user program to not be started */
return;
}
#endif
#if (BOOT_COM_ENABLE > 0)
/* release the communication interface */
ComFree();
#endif
/* reset the HAL */
HAL_DeInit();
/* reset the timer */
TimerReset();
/* remap user program's vector table */
SCB->VTOR = CPU_USER_PROGRAM_VECTABLE_OFFSET & (blt_int32u)0x1FFFFF80;
/* 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-M4 core has interrupts enabled out of reset. the bootloader
* explicitly disables these for security reasons. Enable them here again, so it does
* not have to be done by the user program.
*/
CpuIrqEnable();
/* start the user program by activating its reset interrupt service routine */
pProgResetHandler();
#if (BOOT_COM_DEFERRED_INIT_ENABLE > 0) && (BOOT_COM_ENABLE > 0)
/* theoretically, the code never gets here because the user program should now be
* running and the previous function call should not return. In case it did return
* for whatever reason, make sure all communication interfaces are initialized so that
* firmware updates can be started.
*/
ComDeferredInit();
#endif
} /*** 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 Sets the bytes at the destination address to the specified value.
** \param dest Destination address for the data.
** \param value Value to write.
** \param len Number of bytes to write.
** \return none.
**
****************************************************************************************/
void CpuMemSet(blt_addr dest, blt_int8u value, blt_int16u len)
{
blt_int8u *to;
/* set casted pointer */
to = (blt_int8u *)dest;
/* set all bytes at the destination address to the specified value */
while (len-- > 0)
{
/* set byte value */
*to++ = value;
/* keep the watchdog happy */
CopService();
}
} /*** end of CpuMemSet ***/
/*********************************** end of cpu.c **************************************/

View File

@@ -0,0 +1,821 @@
/************************************************************************************//**
* \file Source/ARMCM4_STM32L4/flash.c
* \brief Bootloader flash driver source file.
* \ingroup Target_ARMCM4_STM32L4
* \internal
*----------------------------------------------------------------------------------------
* C O P Y R I G H T
*----------------------------------------------------------------------------------------
* Copyright (c) 2018 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 "stm32l4xx.h" /* STM32 CPU and HAL header */
/****************************************************************************************
* Macro definitions
****************************************************************************************/
/** \brief Value for an invalid flash address. */
#define FLASH_INVALID_ADDRESS (0xffffffff)
/** \brief Standard size of a flash block for writing. */
#define FLASH_WRITE_BLOCK_SIZE (512)
/** \brief Standard size of a flash sector for erasing. */
#define FLASH_ERASE_SECTOR_SIZE (2048)
/** \brief Total numbers of segments in array flashLayout[]. */
#define FLASH_TOTAL_SEGMENTS (sizeof(flashLayout)/sizeof(flashLayout[0]))
/** \brief Index of the last segment in array flashLayout[]. */
#define FLASH_LAST_SEGMENT_IDX (FLASH_TOTAL_SEGMENTS-1)
/** \brief Start address of the bootloader programmable flash. */
#define FLASH_START_ADDRESS (flashLayout[0].sector_start)
/** \brief End address of the bootloader programmable flash. */
#define FLASH_END_ADDRESS (flashLayout[FLASH_LAST_SEGMENT_IDX].sector_start + \
flashLayout[FLASH_LAST_SEGMENT_IDX].sector_size - 1)
/** \brief Offset into the user program's vector table where the checksum is located.
* For this target it is set to the end of the vector table. Note that the
* value can be overriden in blt_conf.h, because the size of the vector table
* could vary. When changing this value, don't forget to update the location
* of the checksum in the user program accordingly. Otherwise the checksum
* verification will always fail.
*/
#ifndef BOOT_FLASH_VECTOR_TABLE_CS_OFFSET
#define BOOT_FLASH_VECTOR_TABLE_CS_OFFSET (0x188)
#endif
/****************************************************************************************
* Plausibility checks
****************************************************************************************/
#if (BOOT_FLASH_VECTOR_TABLE_CS_OFFSET >= FLASH_WRITE_BLOCK_SIZE)
#error "BOOT_FLASH_VECTOR_TABLE_CS_OFFSET is set too high. It must be located in the first writable block."
#endif
#ifndef BOOT_FLASH_CUSTOM_LAYOUT_ENABLE
#define BOOT_FLASH_CUSTOM_LAYOUT_ENABLE (0u)
#endif
/****************************************************************************************
* Type definitions
****************************************************************************************/
/** \brief Flash sector descriptor type. */
typedef struct
{
blt_addr sector_start; /**< sector start address */
blt_int32u sector_size; /**< sector size in bytes */
} tFlashSector;
/** \brief Structure type for grouping flash block information.
* \details Programming is done per block of max FLASH_WRITE_BLOCK_SIZE. for this a
* flash block manager is implemented in this driver. this flash block manager
* depends on this flash block info structure. It holds the base address of
* the flash block and the data that should be programmed into the flash
* block. The .base_addr must be a multiple of FLASH_WRITE_BLOCK_SIZE.
*/
typedef struct
{
blt_addr base_addr;
blt_int8u data[FLASH_WRITE_BLOCK_SIZE];
} tFlashBlockInfo;
/****************************************************************************************
* Hook functions
****************************************************************************************/
#if (BOOT_FLASH_CRYPTO_HOOKS_ENABLE > 0)
extern blt_bool FlashCryptoDecryptDataHook(blt_int8u * data, blt_int32u size);
#endif
/****************************************************************************************
* Function prototypes
****************************************************************************************/
static blt_bool FlashInitBlock(tFlashBlockInfo *block, blt_addr address);
static tFlashBlockInfo *FlashSwitchBlock(tFlashBlockInfo *block, blt_addr base_addr);
static blt_bool FlashAddToBlock(tFlashBlockInfo *block, blt_addr address,
blt_int8u *data, blt_int32u len);
static blt_bool FlashWriteBlock(tFlashBlockInfo *block);
static blt_int32u FlashGetPage(blt_addr address);
static blt_int32u FlashGetBank(blt_addr address);
/****************************************************************************************
* Local constant declarations
****************************************************************************************/
/** \brief If desired, it is possible to set BOOT_FLASH_CUSTOM_LAYOUT_ENABLE to > 0
* in blt_conf.h and then implement your own version of the flashLayout[] table
* in a source-file with the name flash_layout.c. This way you customize the
* flash memory size reserved for the bootloader, without having to modify
* the flashLayout[] table in this file directly. This file will then include
* flash_layout.c so there is no need to compile it additionally with your
* project.
*/
#if (BOOT_FLASH_CUSTOM_LAYOUT_ENABLE == 0)
/** \brief Array wit the layout of the flash memory. Note that the current flash driver
* supports the STM32L4x1, STM32L4x5 and STM32L4x6 derivatives in the STM32L4
* family of microcontrollers.
* \details Also controls what part of the flash memory is reserved for the bootloader.
* If the bootloader size changes, the reserved sectors for the bootloader
* might need adjustment to make sure the bootloader doesn't get overwritten.
*/
static const tFlashSector flashLayout[] =
{
/* space is reserved for a bootloader configuration with all supported communication
* interfaces enabled. when for example only UART is needed, then the space required
* for the bootloader can be made a lot smaller here.
*/
/* { 0x08000000, 0x00800 }, flash sector 0 - 2kb (reserved for bootloader)*/
/* { 0x08000800, 0x00800 }, flash sector 1 - 2kb (reserved for bootloader)*/
/* { 0x08001000, 0x00800 }, flash sector 2 - 2kb (reserved for bootloader)*/
/* { 0x08001800, 0x00800 }, flash sector 3 - 2kb (reserved for bootloader)*/
/* { 0x08002000, 0x00800 }, flash sector 4 - 2kb (reserved for bootloader)*/
{ 0x08002800, 0x00800 }, /* flash sector 5 - 2kb */
{ 0x08003000, 0x00800 }, /* flash sector 6 - 2kb */
{ 0x08003800, 0x00800 }, /* flash sector 7 - 2kb */
{ 0x08004000, 0x00800 }, /* flash sector 8 - 2kb */
{ 0x08004800, 0x00800 }, /* flash sector 9 - 2kb */
{ 0x08005000, 0x00800 }, /* flash sector 10 - 2kb */
{ 0x08005800, 0x00800 }, /* flash sector 11 - 2kb */
{ 0x08006000, 0x00800 }, /* flash sector 12 - 2kb */
{ 0x08006800, 0x00800 }, /* flash sector 13 - 2kb */
{ 0x08007000, 0x00800 }, /* flash sector 14 - 2kb */
{ 0x08007800, 0x00800 }, /* flash sector 15 - 2kb */
{ 0x08008000, 0x00800 }, /* flash sector 16 - 2kb */
{ 0x08008800, 0x00800 }, /* flash sector 17 - 2kb */
{ 0x08009000, 0x00800 }, /* flash sector 18 - 2kb */
{ 0x08009800, 0x00800 }, /* flash sector 19 - 2kb */
{ 0x0800A000, 0x00800 }, /* flash sector 20 - 2kb */
{ 0x0800A800, 0x00800 }, /* flash sector 21 - 2kb */
{ 0x0800B000, 0x00800 }, /* flash sector 22 - 2kb */
{ 0x0800B800, 0x00800 }, /* flash sector 23 - 2kb */
{ 0x0800C000, 0x00800 }, /* flash sector 24 - 2kb */
{ 0x0800C800, 0x00800 }, /* flash sector 25 - 2kb */
{ 0x0800D000, 0x00800 }, /* flash sector 26 - 2kb */
{ 0x0800D800, 0x00800 }, /* flash sector 27 - 2kb */
{ 0x0800E000, 0x00800 }, /* flash sector 28 - 2kb */
{ 0x0800E800, 0x00800 }, /* flash sector 29 - 2kb */
{ 0x0800F000, 0x00800 }, /* flash sector 30 - 2kb */
{ 0x0800F800, 0x00800 }, /* flash sector 31 - 2kb */
{ 0x08010000, 0x10000 }, /* flash sectors 32 to 63 - 64kb */
{ 0x08020000, 0x20000 }, /* flash sectors 64 to 127 - 128kb */
#if (BOOT_NVM_SIZE_KB > 256)
{ 0x08040000, 0x40000 }, /* flash sectors 128 to 255 - 256kb */
#endif
#if (BOOT_NVM_SIZE_KB > 512)
{ 0x08080000, 0x80000 } /* flash sectors 256 to 511 - 512kb */
#endif
#if (BOOT_NVM_SIZE_KB > 1024)
#error "BOOT_NVM_SIZE_KB > 1024 is currently not supported."
#endif
};
#else
#include "flash_layout.c"
#endif /* BOOT_FLASH_CUSTOM_LAYOUT_ENABLE == 0 */
/****************************************************************************************
* Local data declarations
****************************************************************************************/
/** \brief Local variable with information about the flash block that is currently
* being operated on.
* \details The smallest amount of flash that can be programmed is
* FLASH_WRITE_BLOCK_SIZE. A flash block manager is implemented in this driver
* and stores info in this variable. Whenever new data should be flashed, it
* is first added to a RAM buffer, which is part of this variable. Whenever
* the RAM buffer, which has the size of a flash block, is full or data needs
* to be written to a different block, the contents of the RAM buffer are
* programmed to flash. The flash block manager requires some software
* overhead, yet results is faster flash programming because data is first
* harvested, ideally until there is enough to program an entire flash block,
* before the flash device is actually operated on.
*/
static tFlashBlockInfo blockInfo;
/** \brief Local variable with information about the flash boot block.
* \details The first block of the user program holds the vector table, which on the
* STM32 is also the where the checksum is written to. Is it likely that
* the vector table is first flashed and then, at the end of the programming
* sequence, the checksum. This means that this flash block need to be written
* to twice. Normally this is not a problem with flash memory, as long as you
* write the same values to those bytes that are not supposed to be changed
* and the locations where you do write to are still in the erased 0xFF state.
* Unfortunately, writing twice to flash this way, does not work reliably on
* all micros. This is why we need to have an extra block, the bootblock,
* placed under the management of the block manager. This way is it possible
* to implement functionality so that the bootblock is only written to once
* at the end of the programming sequence.
*/
static tFlashBlockInfo bootBlockInfo;
/************************************************************************************//**
** \brief Initializes the flash driver.
** \return none.
**
****************************************************************************************/
void FlashInit(void)
{
/* init the flash block info structs by setting the address to an invalid address */
blockInfo.base_addr = FLASH_INVALID_ADDRESS;
bootBlockInfo.base_addr = FLASH_INVALID_ADDRESS;
} /*** end of FlashInit ***/
/************************************************************************************//**
** \brief Reinitializes the flash driver.
** \return none.
**
****************************************************************************************/
void FlashReinit(void)
{
/* init the flash block info structs by setting the address to an invalid address */
blockInfo.base_addr = FLASH_INVALID_ADDRESS;
bootBlockInfo.base_addr = FLASH_INVALID_ADDRESS;
} /*** end of FlashReinit ***/
/************************************************************************************//**
** \brief Writes the data to flash through a flash block manager. Note that this
** function also checks that no data is programmed outside the flash
** memory region, so the bootloader can never be overwritten.
** \param addr Start address.
** \param len Length in bytes.
** \param data Pointer to the data buffer.
** \return BLT_TRUE if successful, BLT_FALSE otherwise.
**
****************************************************************************************/
blt_bool FlashWrite(blt_addr addr, blt_int32u len, blt_int8u *data)
{
blt_addr base_addr;
/* validate the len parameter */
if ((len - 1) > (FLASH_END_ADDRESS - addr))
{
return BLT_FALSE;
}
/* make sure the addresses are within the flash device */
if ((addr < FLASH_START_ADDRESS) || ((addr+len-1) > FLASH_END_ADDRESS))
{
return BLT_FALSE;
}
/* if this is the bootblock, then let the boot block manager handle it */
base_addr = (addr/FLASH_WRITE_BLOCK_SIZE)*FLASH_WRITE_BLOCK_SIZE;
if (base_addr == flashLayout[0].sector_start)
{
/* let the boot block manager handle it */
return FlashAddToBlock(&bootBlockInfo, addr, data, len);
}
/* let the block manager handle it */
return FlashAddToBlock(&blockInfo, addr, data, len);
} /*** end of FlashWrite ***/
/************************************************************************************//**
** \brief Erases the flash memory. Note that this function also checks that no
** data is erased outside the flash memory region, so the bootloader can
** never be erased. Note that the term sector used by this flash driver is
** equivalent to the term page in the STM32L4x reference manual.
** \param addr Start address.
** \param len Length in bytes.
** \return BLT_TRUE if successful, BLT_FALSE otherwise.
**
****************************************************************************************/
blt_bool FlashErase(blt_addr addr, blt_int32u len)
{
blt_addr erase_base_addr;
blt_addr erase_current_addr;
blt_int32u total_erase_len;
blt_int16u nr_of_erase_sectors;
blt_bool result = BLT_TRUE;
blt_int16u sector_cnt;
blt_int32u dummy;
FLASH_EraseInitTypeDef eraseInitStruct;
/* validate the len parameter */
if ((len - 1) > (FLASH_END_ADDRESS - addr))
{
return BLT_FALSE;
}
/* determine the base address for the erase operation, by aligning to
* FLASH_ERASE_SECTOR_SIZE.
*/
erase_base_addr = (addr/FLASH_ERASE_SECTOR_SIZE)*FLASH_ERASE_SECTOR_SIZE;
/* make sure the addresses are within the flash device */
if ((erase_base_addr < FLASH_START_ADDRESS) || ((addr+len-1) > FLASH_END_ADDRESS))
{
return BLT_FALSE;
}
/* determine number of bytes to erase from base address */
total_erase_len = len + (addr - erase_base_addr);
/* determine the number of sectors to erase */
nr_of_erase_sectors = (blt_int16u)(total_erase_len / FLASH_ERASE_SECTOR_SIZE);
if ((total_erase_len % FLASH_ERASE_SECTOR_SIZE) > 0)
{
nr_of_erase_sectors++;
}
/* unlock access to the flash device */
HAL_FLASH_Unlock();
/* clear OPTVERR bit set on virgin samples */
__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_OPTVERR);
/* prepare erase init structure */
eraseInitStruct.TypeErase = FLASH_TYPEERASE_PAGES;
eraseInitStruct.NbPages = 1;
/* erase all sectors one by one */
for (sector_cnt=0; sector_cnt<nr_of_erase_sectors; sector_cnt++)
{
/* keep the watchdog happy */
CopService();
/* set the sector base address */
erase_current_addr = erase_base_addr + (sector_cnt * FLASH_ERASE_SECTOR_SIZE);
/* update erase init structure */
eraseInitStruct.Page = FlashGetPage(erase_current_addr);
eraseInitStruct.Banks = FlashGetBank(erase_current_addr);
/* perform sector erase operation */
if (HAL_FLASHEx_Erase(&eraseInitStruct, (uint32_t *)&dummy) != HAL_OK)
{
/* error detected. flag it and stop */
result = BLT_FALSE;
break;
}
}
/* lock access to the flash device */
HAL_FLASH_Lock();
/* return the result */
return result;
} /*** end of FlashErase ***/
/************************************************************************************//**
** \brief Writes a checksum of the user program to non-volatile memory. This is
** performed once the entire user program has been programmed. Through
** the checksum, the bootloader can check if the programming session
** was completed, which indicates that a valid user programming is
** present and can be started.
** \return BLT_TRUE if successful, BLT_FALSE otherwise.
**
****************************************************************************************/
blt_bool FlashWriteChecksum(void)
{
blt_int32u signature_checksum = 0;
/* for the STM32 target we defined the checksum as the Two's complement value of the
* sum of the first 7 exception addresses.
*
* Layout of the vector table:
* 0x08000000 Initial stack pointer
* 0x08000004 Reset Handler
* 0x08000008 NMI Handler
* 0x0800000C Hard Fault Handler
* 0x08000010 MPU Fault Handler
* 0x08000014 Bus Fault Handler
* 0x08000018 Usage Fault Handler
*
* signature_checksum = Two's complement of (SUM(exception address values))
*
* the bootloader writes this 32-bit checksum value right after the vector table
* of the user program. note that this means one extra dummy entry must be added
* at the end of the user program's vector table to reserve storage space for the
* checksum.
*/
/* first check that the bootblock contains valid data. if not, this means the
* bootblock is not part of the reprogramming this time and therefore no
* new checksum needs to be written
*/
if (bootBlockInfo.base_addr == FLASH_INVALID_ADDRESS)
{
return BLT_TRUE;
}
#if (BOOT_FLASH_CRYPTO_HOOKS_ENABLE > 0)
/* perform decryption of the bootblock, before calculating the checksum and writing it
* to flash memory.
*/
if (FlashCryptoDecryptDataHook(bootBlockInfo.data, FLASH_WRITE_BLOCK_SIZE) == BLT_FALSE)
{
return BLT_FALSE;
}
#endif
/* compute the checksum. note that the user program's vectors are not yet written
* to flash but are present in the bootblock data structure at this point.
*/
signature_checksum += *((blt_int32u *)(&bootBlockInfo.data[0+0x00]));
signature_checksum += *((blt_int32u *)(&bootBlockInfo.data[0+0x04]));
signature_checksum += *((blt_int32u *)(&bootBlockInfo.data[0+0x08]));
signature_checksum += *((blt_int32u *)(&bootBlockInfo.data[0+0x0C]));
signature_checksum += *((blt_int32u *)(&bootBlockInfo.data[0+0x10]));
signature_checksum += *((blt_int32u *)(&bootBlockInfo.data[0+0x14]));
signature_checksum += *((blt_int32u *)(&bootBlockInfo.data[0+0x18]));
signature_checksum = ~signature_checksum; /* one's complement */
signature_checksum += 1; /* two's complement */
/* write the checksum */
return FlashWrite(flashLayout[0].sector_start+BOOT_FLASH_VECTOR_TABLE_CS_OFFSET,
sizeof(blt_addr), (blt_int8u *)&signature_checksum);
} /*** end of FlashWriteChecksum ***/
/************************************************************************************//**
** \brief Verifies the checksum, which indicates that a valid user program is
** present and can be started.
** \return BLT_TRUE if successful, BLT_FALSE otherwise.
**
****************************************************************************************/
blt_bool FlashVerifyChecksum(void)
{
blt_int32u signature_checksum = 0;
/* verify the checksum based on how it was written by CpuWriteChecksum() */
signature_checksum += *((blt_int32u *)(flashLayout[0].sector_start));
signature_checksum += *((blt_int32u *)(flashLayout[0].sector_start+0x04));
signature_checksum += *((blt_int32u *)(flashLayout[0].sector_start+0x08));
signature_checksum += *((blt_int32u *)(flashLayout[0].sector_start+0x0C));
signature_checksum += *((blt_int32u *)(flashLayout[0].sector_start+0x10));
signature_checksum += *((blt_int32u *)(flashLayout[0].sector_start+0x14));
signature_checksum += *((blt_int32u *)(flashLayout[0].sector_start+0x18));
signature_checksum += *((blt_int32u *)(flashLayout[0].sector_start+BOOT_FLASH_VECTOR_TABLE_CS_OFFSET));
/* sum should add up to an unsigned 32-bit value of 0 */
if (signature_checksum == 0)
{
/* checksum okay */
return BLT_TRUE;
}
/* checksum incorrect */
return BLT_FALSE;
} /*** end of FlashVerifyChecksum ***/
/************************************************************************************//**
** \brief Finalizes the flash driver operations. There could still be data in
** the currently active block that needs to be flashed.
** \return BLT_TRUE if successful, BLT_FALSE otherwise.
**
****************************************************************************************/
blt_bool FlashDone(void)
{
/* check if there is still data waiting to be programmed in the boot block */
if (bootBlockInfo.base_addr != FLASH_INVALID_ADDRESS)
{
if (FlashWriteBlock(&bootBlockInfo) == BLT_FALSE)
{
return BLT_FALSE;
}
}
/* check if there is still data waiting to be programmed */
if (blockInfo.base_addr != FLASH_INVALID_ADDRESS)
{
if (FlashWriteBlock(&blockInfo) == BLT_FALSE)
{
return BLT_FALSE;
}
}
/* still here so all is okay */
return BLT_TRUE;
} /*** end of FlashDone ***/
/************************************************************************************//**
** \brief Obtains the base address of the flash memory available to the user program.
** This is basically the first address in the flashLayout table.
** \return Base address.
**
****************************************************************************************/
blt_addr FlashGetUserProgBaseAddress(void)
{
return flashLayout[0].sector_start;
} /*** end of FlashGetUserProgBaseAddress ***/
/************************************************************************************//**
** \brief Copies data currently in flash to the block->data and sets the
** base address.
** \param block Pointer to flash block info structure to operate on.
** \param address Base address of the block data.
** \return BLT_TRUE if successful, BLT_FALSE otherwise.
**
****************************************************************************************/
static blt_bool FlashInitBlock(tFlashBlockInfo *block, blt_addr address)
{
/* check address alignment */
if ((address % FLASH_WRITE_BLOCK_SIZE) != 0)
{
return BLT_FALSE;
}
/* make sure that we are initializing a new block and not the same one */
if (block->base_addr == address)
{
/* block already initialized, so nothing to do */
return BLT_TRUE;
}
/* set the base address and copies the current data from flash */
block->base_addr = address;
CpuMemCopy((blt_addr)block->data, address, FLASH_WRITE_BLOCK_SIZE);
return BLT_TRUE;
} /*** end of FlashInitBlock ***/
/************************************************************************************//**
** \brief Switches blocks by programming the current one and initializing the
** next.
** \param block Pointer to flash block info structure to operate on.
** \param base_addr Base address of the next block.
** \return The pointer of the block info struct that is no being used, or a NULL
** pointer in case of error.
**
****************************************************************************************/
static tFlashBlockInfo *FlashSwitchBlock(tFlashBlockInfo *block, blt_addr base_addr)
{
/* check if a switch needs to be made away from the boot block. in this case the boot
* block shouldn't be written yet, because this is done at the end of the programming
* session by FlashDone(), this is right after the checksum was written.
*/
if (block == &bootBlockInfo)
{
/* switch from the boot block to the generic block info structure */
block = &blockInfo;
}
/* check if a switch back into the bootblock is needed. in this case the generic block
* doesn't need to be written here yet.
*/
else if (base_addr == flashLayout[0].sector_start)
{
/* switch from the generic block to the boot block info structure */
block = &bootBlockInfo;
base_addr = flashLayout[0].sector_start;
}
else
{
/* need to switch to a new block, so program the current one and init the next */
if (FlashWriteBlock(block) == BLT_FALSE)
{
return BLT_NULL;
}
}
/* initialize tne new block when necessary */
if (FlashInitBlock(block, base_addr) == BLT_FALSE)
{
return BLT_NULL;
}
/* still here to all is okay */
return block;
} /*** end of FlashSwitchBlock ***/
/************************************************************************************//**
** \brief Programming is done per block. This function adds data to the block
** that is currently collecting data to be written to flash. If the
** address is outside of the current block, the current block is written
** to flash an a new block is initialized.
** \param block Pointer to flash block info structure to operate on.
** \param address Flash destination address.
** \param data Pointer to the byte array with data.
** \param len Number of bytes to add to the block.
** \return BLT_TRUE if successful, BLT_FALSE otherwise.
**
****************************************************************************************/
static blt_bool FlashAddToBlock(tFlashBlockInfo *block, blt_addr address,
blt_int8u *data, blt_int32u len)
{
blt_addr current_base_addr;
blt_int8u *dst;
blt_int8u *src;
/* determine the current base address */
current_base_addr = (address/FLASH_WRITE_BLOCK_SIZE)*FLASH_WRITE_BLOCK_SIZE;
/* make sure the blockInfo is not uninitialized */
if (block->base_addr == FLASH_INVALID_ADDRESS)
{
/* initialize the blockInfo struct for the current block */
if (FlashInitBlock(block, current_base_addr) == BLT_FALSE)
{
return BLT_FALSE;
}
}
/* check if the new data fits in the current block */
if (block->base_addr != current_base_addr)
{
/* need to switch to a new block, so program the current one and init the next */
block = FlashSwitchBlock(block, current_base_addr);
if (block == BLT_NULL)
{
return BLT_FALSE;
}
}
/* add the data to the current block, but check for block overflow */
dst = &(block->data[address - block->base_addr]);
src = data;
do
{
/* keep the watchdog happy */
CopService();
/* buffer overflow? */
if ((blt_addr)(dst-&(block->data[0])) >= FLASH_WRITE_BLOCK_SIZE)
{
/* need to switch to a new block, so program the current one and init the next */
block = FlashSwitchBlock(block, current_base_addr+FLASH_WRITE_BLOCK_SIZE);
if (block == BLT_NULL)
{
return BLT_FALSE;
}
/* reset destination pointer */
dst = &(block->data[0]);
}
/* write the data to the buffer */
*dst = *src;
/* update pointers */
dst++;
src++;
/* decrement byte counter */
len--;
}
while (len > 0);
/* still here so all is good */
return BLT_TRUE;
} /*** end of FlashAddToBlock ***/
/************************************************************************************//**
** \brief Programs FLASH_WRITE_BLOCK_SIZE bytes to flash from the block->data
** array.
** \param block Pointer to flash block info structure to operate on.
** \return BLT_TRUE if successful, BLT_FALSE otherwise.
**
****************************************************************************************/
static blt_bool FlashWriteBlock(tFlashBlockInfo *block)
{
blt_addr prog_addr;
uint64_t prog_data;
blt_int32u doubleword_cnt;
blt_bool result = BLT_TRUE;
#if (BOOT_FLASH_CRYPTO_HOOKS_ENABLE > 0)
#if (BOOT_NVM_CHECKSUM_HOOKS_ENABLE == 0)
/* note that the bootblock is already decrypted in FlashWriteChecksum(), if the
* internal checksum mechanism is used. Therefore don't decrypt it again.
*/
if (block != &bootBlockInfo)
#endif
{
/* perform decryption of the program data before writing it to flash memory. */
if (FlashCryptoDecryptDataHook(block->data, FLASH_WRITE_BLOCK_SIZE) == BLT_FALSE)
{
return BLT_FALSE;
}
}
#endif
/* unlock access to the flash device */
HAL_FLASH_Unlock();
/* clear OPTVERR bit set on virgin samples */
__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_OPTVERR);
/* program all double words in the block one by one */
for (doubleword_cnt=0; doubleword_cnt<(FLASH_WRITE_BLOCK_SIZE/sizeof(uint64_t)); doubleword_cnt++)
{
prog_addr = block->base_addr + (doubleword_cnt * sizeof(uint64_t));
prog_data = *(volatile uint64_t *)(&block->data[doubleword_cnt * sizeof(uint64_t)]);
/* keep the watchdog happy */
CopService();
/* program the double word */
if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, prog_addr, prog_data) != HAL_OK)
{
/* error detected. flag it and stop */
result = BLT_FALSE;
break;
}
/* verify that the written data is actually there */
if (*(volatile uint64_t *)prog_addr != prog_data)
{
result = BLT_FALSE;
break;
}
}
/* lock access to the flash device */
HAL_FLASH_Lock();
/* return the result */
return result;
} /*** end of FlashWriteBlock ***/
/************************************************************************************//**
** \brief Gets the page number of the address relative to the bank.
** \param address Address in the flash bank.
** \return The page of the given address: 0..255.
**
****************************************************************************************/
static blt_int32u FlashGetPage(blt_addr address)
{
blt_int32u page = 0;
/* is the address in the first bank? note that this can be either FLASH_BANK_1 or
* FLASH_BANK_2, due to the flash swap feature.
*/
if (address < (FLASH_BASE + FLASH_BANK_SIZE))
{
page = (address - FLASH_BASE) / FLASH_PAGE_SIZE;
}
/* address is in the second bank */
else
{
page = (address - (FLASH_BASE + FLASH_BANK_SIZE)) / FLASH_PAGE_SIZE;
}
return page;
} /*** end of FlashGetPage ***/
/************************************************************************************//**
** \brief Obtains the bank of the given address. The 1024kb version of the flash
** device contains 2 banks that can be swapped. This feature breaks the link
** between a bank number and flash addresses. This function obtains the
** bank number that is currently at the given address.
** \param address Address in the flash bank.
** \return The flash bank of the given address: FLASH_BANK_1 or FLASH_BANK_2.
**
****************************************************************************************/
static blt_int32u FlashGetBank(blt_addr address)
{
blt_int32u bank = FLASH_BANK_1;
/* multiple banks is only supported on certain STM32L4xx derivatives. */
#if defined (STM32L471xx) || defined (STM32L475xx) || defined (STM32L476xx) || \
defined (STM32L485xx) || defined (STM32L486xx) || defined (STM32L496xx) || \
defined (STM32L4A6xx) || defined (STM32L4R5xx) || defined (STM32L4R7xx) || \
defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || \
defined (STM32L4S9xx)
/* check flash bank mode selection bit to determine if banks 1 and 2 are swapped */
if (READ_BIT(SYSCFG->MEMRMP, SYSCFG_MEMRMP_FB_MODE) == 0)
{
/* no bank swap active */
if (address < (FLASH_BASE + FLASH_BANK_SIZE))
{
bank = FLASH_BANK_1;
}
else
{
bank = FLASH_BANK_2;
}
}
else
{
/* bank swap active */
if (address < (FLASH_BASE + FLASH_BANK_SIZE))
{
bank = FLASH_BANK_2;
}
else
{
bank = FLASH_BANK_1;
}
}
#endif
return bank;
} /*** end of FlashGetBank ***/
/*********************************** end of flash.c ************************************/

View File

@@ -0,0 +1,45 @@
/************************************************************************************//**
* \file Source/ARMCM4_STM32L4/flash.h
* \brief Bootloader flash driver header file.
* \ingroup Target_ARMCM4_STM32L4
* \internal
*----------------------------------------------------------------------------------------
* C O P Y R I G H T
*----------------------------------------------------------------------------------------
* Copyright (c) 2018 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
****************************************************************************************/
#ifndef FLASH_H
#define FLASH_H
/****************************************************************************************
* Function prototypes
****************************************************************************************/
void FlashInit(void);
void FlashReinit(void);
blt_bool FlashWrite(blt_addr addr, blt_int32u len, blt_int8u *data);
blt_bool FlashErase(blt_addr addr, blt_int32u len);
blt_bool FlashWriteChecksum(void);
blt_bool FlashVerifyChecksum(void);
blt_bool FlashDone(void);
blt_addr FlashGetUserProgBaseAddress(void);
#endif /* FLASH_H */
/*********************************** end of flash.h ************************************/

View File

@@ -0,0 +1,245 @@
/************************************************************************************//**
* \file Source/ARMCM4_STM32L4/nvm.c
* \brief Bootloader non-volatile memory driver source file.
* \ingroup Target_ARMCM4_STM32L4
* \internal
*----------------------------------------------------------------------------------------
* C O P Y R I G H T
*----------------------------------------------------------------------------------------
* Copyright (c) 2018 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 "flash.h"
/****************************************************************************************
* Hook functions
****************************************************************************************/
#if (BOOT_NVM_HOOKS_ENABLE > 0)
extern void NvmInitHook(void);
extern void NvmReinitHook(void);
extern blt_int8u NvmWriteHook(blt_addr addr, blt_int32u len, blt_int8u *data);
extern blt_int8u NvmEraseHook(blt_addr addr, blt_int32u len);
extern blt_bool NvmDoneHook(void);
#endif
#if (BOOT_NVM_CHECKSUM_HOOKS_ENABLE > 0)
extern blt_bool NvmWriteChecksumHook(void);
extern blt_bool NvmVerifyChecksumHook(void);
#endif
/************************************************************************************//**
** \brief Initializes the NVM driver.
** \return none.
**
****************************************************************************************/
void NvmInit(void)
{
#if (BOOT_NVM_HOOKS_ENABLE > 0)
/* give the application a chance to initialize a driver for operating on NVM
* that is not by default supported by this driver.
*/
NvmInitHook();
#endif
/* init the internal driver */
FlashInit();
} /*** end of NvmInit ***/
/************************************************************************************//**
** \brief Reinitializes the NVM driver. This function is called at the start of each
** firmware update as opposed to NvmInit, which is only called once during
** power on.
** \return none.
**
****************************************************************************************/
void NvmReinit(void)
{
#if (BOOT_NVM_HOOKS_ENABLE > 0)
/* give the application a chance to re-initialize a driver for operating on NVM
* that is not by default supported by this driver.
*/
NvmReinitHook();
#endif
/* reinitialize the internal driver */
FlashReinit();
} /*** end of NvmReinit ***/
/************************************************************************************//**
** \brief Programs the non-volatile memory.
** \param addr Start address.
** \param len Length in bytes.
** \param data Pointer to the data buffer.
** \return BLT_TRUE if successful, BLT_FALSE otherwise.
**
****************************************************************************************/
blt_bool NvmWrite(blt_addr addr, blt_int32u len, blt_int8u *data)
{
#if (BOOT_NVM_HOOKS_ENABLE > 0)
blt_int8u result = BLT_NVM_NOT_IN_RANGE;
#endif
#if (BOOT_NVM_HOOKS_ENABLE > 0)
/* give the application a chance to operate on memory that is not by default supported
* by this driver.
*/
result = NvmWriteHook(addr, len, data);
/* process the return code */
if (result == BLT_NVM_OKAY)
{
/* data was within range of the additionally supported memory and succesfully
* programmed, so we are all done.
*/
return BLT_TRUE;
}
else if (result == BLT_NVM_ERROR)
{
/* data was within range of the additionally supported memory and attempted to be
* programmed, but an error occurred, so we can't continue.
*/
return BLT_FALSE;
}
#endif
/* still here so the internal driver should try and perform the program operation */
return FlashWrite(addr, len, data);
} /*** end of NvmWrite ***/
/************************************************************************************//**
** \brief Erases the non-volatile memory.
** \param addr Start address.
** \param len Length in bytes.
** \return BLT_TRUE if successful, BLT_FALSE otherwise.
**
****************************************************************************************/
blt_bool NvmErase(blt_addr addr, blt_int32u len)
{
#if (BOOT_NVM_HOOKS_ENABLE > 0)
blt_int8u result = BLT_NVM_NOT_IN_RANGE;
#endif
#if (BOOT_NVM_HOOKS_ENABLE > 0)
/* give the application a chance to operate on memory that is not by default supported
* by this driver.
*/
result = NvmEraseHook(addr, len);
/* process the return code */
if (result == BLT_NVM_OKAY)
{
/* address was within range of the additionally supported memory and succesfully
* erased, so we are all done.
*/
return BLT_TRUE;
}
else if (result == BLT_NVM_ERROR)
{
/* address was within range of the additionally supported memory and attempted to be
* erased, but an error occurred, so we can't continue.
*/
return BLT_FALSE;
}
#endif
/* still here so the internal driver should try and perform the erase operation */
return FlashErase(addr, len);
} /*** end of NvmErase ***/
/************************************************************************************//**
** \brief Verifies the checksum, which indicates that a valid user program is
** present and can be started.
** \return BLT_TRUE if successful, BLT_FALSE otherwise.
**
****************************************************************************************/
blt_bool NvmVerifyChecksum(void)
{
#if (BOOT_NVM_CHECKSUM_HOOKS_ENABLE > 0)
/* check checksum using the application specific method. */
return NvmVerifyChecksumHook();
#else
/* check checksum using the interally supported method. */
return FlashVerifyChecksum();
#endif
} /*** end of NvmVerifyChecksum ***/
/************************************************************************************//**
** \brief Obtains the base address of the non-volatile memory available to the user
** program. This is typically that start of the vector table.
** \return Base address.
**
****************************************************************************************/
blt_addr NvmGetUserProgBaseAddress(void)
{
return FlashGetUserProgBaseAddress();
} /*** end of NvmGetUserProgBaseAddress ***/
/************************************************************************************//**
** \brief Once all erase and programming operations are completed, this
** function is called, so at the end of the programming session and
** right before a software reset is performed. It is used to calculate
** a checksum and program this into flash. This checksum is later used
** to determine if a valid user program is present in flash.
** \return BLT_TRUE if successful, BLT_FALSE otherwise.
**
****************************************************************************************/
blt_bool NvmDone(void)
{
#if (BOOT_NVM_HOOKS_ENABLE > 0)
/* give the application's NVM driver a chance to finish up */
if (NvmDoneHook() == BLT_FALSE)
{
/* error so no need to continue */
return BLT_FALSE;
}
#endif
#if (BOOT_NVM_CHECKSUM_HOOKS_ENABLE > 0)
/* compute and write checksum, using the application specific method. */
if (NvmWriteChecksumHook() == BLT_FALSE)
{
return BLT_FALSE;
}
#else
/* compute and write checksum, which is programmed by the internal driver. */
if (FlashWriteChecksum() == BLT_FALSE)
{
return BLT_FALSE;
}
#endif
/* finish up internal driver operations */
return FlashDone();
} /*** end of NvmDone ***/
/*********************************** end of nvm.c **************************************/

View File

@@ -0,0 +1,316 @@
/************************************************************************************//**
* \file Source/ARMCM4_STM32L4/rs232.c
* \brief Bootloader RS232 communication interface source file.
* \ingroup Target_ARMCM4_STM32L4
* \internal
*----------------------------------------------------------------------------------------
* C O P Y R I G H T
*----------------------------------------------------------------------------------------
* Copyright (c) 2018 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 */
#if (BOOT_COM_RS232_ENABLE > 0)
#include "stm32l4xx.h" /* STM32 CPU and HAL header */
#if (BOOT_COM_RS232_CHANNEL_INDEX < 5) /* USART or UART channel */
#include "stm32l4xx_ll_usart.h" /* STM32 LL USART header */
#else /* LPUART channel */
#include "stm32l4xx_ll_lpuart.h" /* STM32 LL LPUART header */
#endif
/****************************************************************************************
* Macro definitions
****************************************************************************************/
/** \brief Timeout time for the reception of a CTO packet. The timer is started upon
* reception of the first packet byte.
*/
#define RS232_CTO_RX_PACKET_TIMEOUT_MS (100u)
/** \brief Timeout for transmitting a byte in milliseconds. */
#define RS232_BYTE_TX_TIMEOUT_MS (10u)
/* map the configured UART channel index to the STM32's USART peripheral. note that the
* LPUART peripheral is mapped after the regular U(S)ART peripherals.
*/
#if (BOOT_COM_RS232_CHANNEL_INDEX == 0)
/** \brief Set UART base address to USART1. */
#define USART_CHANNEL USART1
#elif (BOOT_COM_RS232_CHANNEL_INDEX == 1)
/** \brief Set UART base address to USART2. */
#define USART_CHANNEL USART2
#elif (BOOT_COM_RS232_CHANNEL_INDEX == 2)
/** \brief Set UART base address to USART3. */
#define USART_CHANNEL USART3
#elif (BOOT_COM_RS232_CHANNEL_INDEX == 3)
/** \brief Set UART base address to UART4. */
#define USART_CHANNEL UART4
#elif (BOOT_COM_RS232_CHANNEL_INDEX == 4)
/** \brief Set UART base address to UART5. */
#define USART_CHANNEL UART5
#elif (BOOT_COM_RS232_CHANNEL_INDEX == 5)
/** \brief Set UART base address to LPUART1. */
#define USART_CHANNEL LPUART1
#endif
/****************************************************************************************
* Function prototypes
****************************************************************************************/
static blt_bool Rs232ReceiveByte(blt_int8u *data);
static void Rs232TransmitByte(blt_int8u data);
/************************************************************************************//**
** \brief Initializes the RS232 communication interface.
** \return none.
**
****************************************************************************************/
void Rs232Init(void)
{
#if (BOOT_COM_RS232_CHANNEL_INDEX < 5) /* USART or UART channel */
LL_USART_InitTypeDef USART_InitStruct = {0};
#else /* LPUART channel */
LL_LPUART_InitTypeDef LPUART_InitStruct = {0};
#endif
/* The current implementation supports USART1 - UART5 and LPUART1. throw an assertion
* error in case a different UART channel is configured.
*/
ASSERT_CT((BOOT_COM_RS232_CHANNEL_INDEX == 0) ||
(BOOT_COM_RS232_CHANNEL_INDEX == 1) ||
(BOOT_COM_RS232_CHANNEL_INDEX == 2) ||
(BOOT_COM_RS232_CHANNEL_INDEX == 3) ||
(BOOT_COM_RS232_CHANNEL_INDEX == 4) ||
(BOOT_COM_RS232_CHANNEL_INDEX == 5));
#if (BOOT_COM_RS232_CHANNEL_INDEX < 5) /* USART or UART channel */
/* disable the UART peripheral */
LL_USART_Disable(USART_CHANNEL);
/* configure UART peripheral */
USART_InitStruct.BaudRate = BOOT_COM_RS232_BAUDRATE;
USART_InitStruct.DataWidth = LL_USART_DATAWIDTH_8B;
USART_InitStruct.StopBits = LL_USART_STOPBITS_1;
USART_InitStruct.Parity = LL_USART_PARITY_NONE;
USART_InitStruct.TransferDirection = LL_USART_DIRECTION_TX_RX;
USART_InitStruct.HardwareFlowControl = LL_USART_HWCONTROL_NONE;
USART_InitStruct.OverSampling = LL_USART_OVERSAMPLING_16;
/* initialize the UART peripheral */
LL_USART_Init(USART_CHANNEL, &USART_InitStruct);
LL_USART_Enable(USART_CHANNEL);
#else /* LPUART channel */
/* disable the peripheral */
LL_LPUART_Disable(USART_CHANNEL);
/* configure UART peripheral */
LPUART_InitStruct.BaudRate = BOOT_COM_RS232_BAUDRATE;
LPUART_InitStruct.DataWidth = LL_LPUART_DATAWIDTH_8B;
LPUART_InitStruct.StopBits = LL_LPUART_STOPBITS_1;
LPUART_InitStruct.Parity = LL_LPUART_PARITY_NONE;
LPUART_InitStruct.TransferDirection = LL_LPUART_DIRECTION_TX_RX;
LPUART_InitStruct.HardwareFlowControl = LL_LPUART_HWCONTROL_NONE;
/* initialize the UART peripheral */
LL_LPUART_Init(USART_CHANNEL, &LPUART_InitStruct);
LL_LPUART_Enable(USART_CHANNEL);
#endif
} /*** end of Rs232Init ***/
/************************************************************************************//**
** \brief Transmits a packet formatted for the communication interface.
** \param data Pointer to byte array with data that it to be transmitted.
** \param len Number of bytes that are to be transmitted.
** \return none.
**
****************************************************************************************/
void Rs232TransmitPacket(blt_int8u *data, blt_int8u len)
{
blt_int16u data_index;
/* verify validity of the len-paramenter */
ASSERT_RT(len <= BOOT_COM_RS232_TX_MAX_DATA);
/* first transmit the length of the packet */
Rs232TransmitByte(len);
/* transmit all the packet bytes one-by-one */
for (data_index = 0; data_index < len; data_index++)
{
/* keep the watchdog happy */
CopService();
/* write byte */
Rs232TransmitByte(data[data_index]);
}
} /*** end of Rs232TransmitPacket ***/
/************************************************************************************//**
** \brief Receives a communication interface packet if one is present.
** \param data Pointer to byte array where the data is to be stored.
** \param len Pointer where the length of the packet is to be stored.
** \return BLT_TRUE if a packet was received, BLT_FALSE otherwise.
**
****************************************************************************************/
blt_bool Rs232ReceivePacket(blt_int8u *data, blt_int8u *len)
{
static blt_int8u xcpCtoReqPacket[BOOT_COM_RS232_RX_MAX_DATA+1]; /* one extra for length */
static blt_int8u xcpCtoRxLength;
static blt_bool xcpCtoRxInProgress = BLT_FALSE;
static blt_int32u xcpCtoRxStartTime = 0;
/* start of cto packet received? */
if (xcpCtoRxInProgress == BLT_FALSE)
{
/* store the message length when received */
if (Rs232ReceiveByte(&xcpCtoReqPacket[0]) == BLT_TRUE)
{
if ( (xcpCtoReqPacket[0] > 0) &&
(xcpCtoReqPacket[0] <= BOOT_COM_RS232_RX_MAX_DATA) )
{
/* store the start time */
xcpCtoRxStartTime = TimerGet();
/* reset packet data count */
xcpCtoRxLength = 0;
/* indicate that a cto packet is being received */
xcpCtoRxInProgress = BLT_TRUE;
}
}
}
else
{
/* store the next packet byte */
if (Rs232ReceiveByte(&xcpCtoReqPacket[xcpCtoRxLength+1]) == BLT_TRUE)
{
/* increment the packet data count */
xcpCtoRxLength++;
/* check to see if the entire packet was received */
if (xcpCtoRxLength == xcpCtoReqPacket[0])
{
/* copy the packet data */
CpuMemCopy((blt_int32u)data, (blt_int32u)&xcpCtoReqPacket[1], xcpCtoRxLength);
/* done with cto packet reception */
xcpCtoRxInProgress = BLT_FALSE;
/* set the packet length */
*len = xcpCtoRxLength;
/* packet reception complete */
return BLT_TRUE;
}
}
else
{
/* check packet reception timeout */
if (TimerGet() > (xcpCtoRxStartTime + RS232_CTO_RX_PACKET_TIMEOUT_MS))
{
/* cancel cto packet reception due to timeout. note that that automaticaly
* discards the already received packet bytes, allowing the host to retry.
*/
xcpCtoRxInProgress = BLT_FALSE;
}
}
}
/* packet reception not yet complete */
return BLT_FALSE;
} /*** end of Rs232ReceivePacket ***/
/************************************************************************************//**
** \brief Receives a communication interface byte if one is present.
** \param data Pointer to byte where the data is to be stored.
** \return BLT_TRUE if a byte was received, BLT_FALSE otherwise.
**
****************************************************************************************/
static blt_bool Rs232ReceiveByte(blt_int8u *data)
{
blt_bool result = BLT_FALSE;
#if (BOOT_COM_RS232_CHANNEL_INDEX < 5) /* USART or UART channel */
/* check if a new byte was received on the configured channel */
if (LL_USART_IsActiveFlag_RXNE(USART_CHANNEL) != 0)
{
/* retrieve and store the newly received byte */
*data = LL_USART_ReceiveData8(USART_CHANNEL);
/* update the result */
result = BLT_TRUE;
}
#else /* LPUART channel */
/* check if a new byte was received on the configured channel */
if (LL_LPUART_IsActiveFlag_RXNE(USART_CHANNEL) != 0)
{
/* retrieve and store the newly received byte */
*data = LL_LPUART_ReceiveData8(USART_CHANNEL);
/* update the result */
result = BLT_TRUE;
}
#endif
/* give the result back to the caller */
return result;
} /*** end of Rs232ReceiveByte ***/
/************************************************************************************//**
** \brief Transmits a communication interface byte.
** \param data Value of byte that is to be transmitted.
** \return none.
**
****************************************************************************************/
static void Rs232TransmitByte(blt_int8u data)
{
blt_int32u timeout;
#if (BOOT_COM_RS232_CHANNEL_INDEX < 5) /* USART or UART channel */
/* write byte to transmit holding register */
LL_USART_TransmitData8(USART_CHANNEL, data);
/* set timeout time to wait for transmit completion. */
timeout = TimerGet() + RS232_BYTE_TX_TIMEOUT_MS;
/* wait for tx holding register to be empty */
while (LL_USART_IsActiveFlag_TXE(USART_CHANNEL) == 0)
{
/* keep the watchdog happy */
CopService();
/* break loop upon timeout. this would indicate a hardware failure. */
if (TimerGet() > timeout)
{
break;
}
}
#else /* LPUART channel */
/* write byte to transmit holding register */
LL_LPUART_TransmitData8(USART_CHANNEL, data);
/* set timeout time to wait for transmit completion. */
timeout = TimerGet() + RS232_BYTE_TX_TIMEOUT_MS;
/* wait for tx holding register to be empty */
while (LL_LPUART_IsActiveFlag_TXE(USART_CHANNEL) == 0)
{
/* keep the watchdog happy */
CopService();
/* break loop upon timeout. this would indicate a hardware failure. */
if (TimerGet() > timeout)
{
break;
}
}
#endif
} /*** end of Rs232TransmitByte ***/
#endif /* BOOT_COM_RS232_ENABLE > 0 */
/*********************************** end of rs232.c ************************************/

View File

@@ -0,0 +1,129 @@
/************************************************************************************//**
* \file Source/ARMCM4_STM32L4/timer.c
* \brief Bootloader timer driver source file.
* \ingroup Target_ARMCM4_STM32L4
* \internal
*----------------------------------------------------------------------------------------
* C O P Y R I G H T
*----------------------------------------------------------------------------------------
* Copyright (c) 2018 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 "stm32l4xx.h" /* STM32 CPU and HAL header */
/****************************************************************************************
* Local data declarations
****************************************************************************************/
/** \brief Local variable for storing the number of milliseconds that have elapsed since
* startup.
*/
static blt_int32u millisecond_counter;
/************************************************************************************//**
** \brief Initializes the polling based millisecond timer driver.
** \return none.
**
****************************************************************************************/
void TimerInit(void)
{
/* Reset the timer configuration. */
TimerReset();
/* Configure the systick frequency as a 1 ms event generator. */
SysTick->LOAD = BOOT_CPU_SYSTEM_SPEED_KHZ - 1;
/* Reset the current counter value. */
SysTick->VAL = 0;
/* Select core clock as source and enable the timer. */
SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | SysTick_CTRL_ENABLE_Msk;
/* Reset the millisecond counter value. */
millisecond_counter = 0;
} /*** end of TimerInit ***/
/************************************************************************************//**
** \brief Reset the timer by placing the timer back into it's default reset
** configuration.
** \return none.
**
****************************************************************************************/
void TimerReset(void)
{
/* Set the systick's registers back into the default reset value. */
SysTick->CTRL = 0;
SysTick->LOAD = 0;
SysTick->VAL = 0;
} /* end of TimerReset */
/************************************************************************************//**
** \brief Updates the millisecond timer.
** \return none.
**
****************************************************************************************/
void TimerUpdate(void)
{
/* Check if the millisecond event occurred. */
if ((SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk) != 0)
{
/* Increment the millisecond counter. */
millisecond_counter++;
}
} /*** end of TimerUpdate ***/
/************************************************************************************//**
** \brief Obtains the counter value of the millisecond timer.
** \return Current value of the millisecond timer.
**
****************************************************************************************/
blt_int32u TimerGet(void)
{
/* Updating timer here allows this function to be called in a loop with timeout
* detection.
*/
TimerUpdate();
/* Read and return the amount of milliseconds that passed since initialization. */
return millisecond_counter;
} /*** end of TimerGet ***/
/************************************************************************************//**
** \brief Override for the HAL driver's GetTick() functionality. This is needed
** because the bootloader doesn't use interrupts, but the HAL's tick
** functionality assumes that it does. This will cause the HAL_Delay()
** function to not work properly. As a result of this override, the HAL's
** tick functionality works in polling mode.
** \return Current value of the millisecond timer.
**
****************************************************************************************/
uint32_t HAL_GetTick(void)
{
/* Link to the bootloader's 1ms timer. */
return TimerGet();
} /*** end of HAL_GetTick ***/
/*********************************** end of timer.c ************************************/

View File

@@ -0,0 +1,58 @@
/************************************************************************************//**
* \file Source/ARMCM4_STM32L4/types.h
* \brief Bootloader types header file.
* \ingroup Target_ARMCM4_STM32L4
* \internal
*----------------------------------------------------------------------------------------
* C O P Y R I G H T
*----------------------------------------------------------------------------------------
* Copyright (c) 2018 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
****************************************************************************************/
#ifndef TYPES_H
#define TYPES_H
/****************************************************************************************
* Macro definitions
****************************************************************************************/
/** \brief Boolean true value. */
#define BLT_TRUE (1)
/** \brief Boolean false value. */
#define BLT_FALSE (0)
/** \brief NULL pointer value. */
#define BLT_NULL ((void *)0)
/****************************************************************************************
* Type definitions
****************************************************************************************/
typedef unsigned char blt_bool; /**< boolean type */
typedef char blt_char; /**< character type */
typedef unsigned long blt_addr; /**< memory address type */
typedef unsigned char blt_int8u; /**< 8-bit unsigned integer */
typedef signed char blt_int8s; /**< 8-bit signed integer */
typedef unsigned short blt_int16u; /**< 16-bit unsigned integer */
typedef signed short blt_int16s; /**< 16-bit signed integer */
typedef unsigned int blt_int32u; /**< 32-bit unsigned integer */
typedef signed int blt_int32s; /**< 32-bit signed integer */
#endif /* TYPES_H */
/*********************************** end of types.h ************************************/

View File

@@ -0,0 +1,521 @@
/************************************************************************************//**
* \file Source/ARMCM4_STM32L4/usb.c
* \brief Bootloader USB communication interface source file.
* \ingroup Target_ARMCM4_STM32L4
* \internal
*----------------------------------------------------------------------------------------
* C O P Y R I G H T
*----------------------------------------------------------------------------------------
* Copyright (c) 2021 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 */
#if (BOOT_COM_USB_ENABLE > 0)
#include "usb.h" /* USB bootloader driver */
#include "usbd_core.h" /* USB driver core */
#include "usbd_desc.h" /* USB driver descriptor */
#include "usbd_bulk.h" /* USB driver bulk device */
/****************************************************************************************
* Configuration macros
****************************************************************************************/
/* For a USB bootloader, the backdoor needs to stay open long enough for the USB device
* to enumerate on the host PC. Therefore the default backdoor open time needs to be
* extended. Note that this won't be long enough for a first time USB driver install
* on the host PC. In this case the bootloader should be started with the backup backdoor
* that uses, for example, a digital input to force the bootloader to stay active. This
* can be implemented in CpuUserProgramStartHook(). Feel free to shorten/lengthen this
* time for finetuning. Note that adding this configuration macro to blt_conf.h overrides
* the value here.
*/
#ifndef BOOT_COM_USB_BACKDOOR_EXTENSION_MS
#define BOOT_COM_USB_BACKDOOR_EXTENSION_MS (2000)
#endif
/****************************************************************************************
* Macro definitions
****************************************************************************************/
/** \brief Total number of fifo buffers. */
#define FIFO_MAX_BUFFERS (2)
/** \brief Invalid value for a fifo buffer handle. */
#define FIFO_ERR_INVALID_HANDLE (255)
/** \brief Number of bytes that fit in the fifo pipe. */
#define FIFO_PIPE_SIZE (64)
/****************************************************************************************
* Type definitions
****************************************************************************************/
/** \brief Structure type for fifo control. */
typedef struct t_fifo_ctrl
{
blt_int8u *startptr; /**< pointer to start of buffer */
blt_int8u *endptr; /**< pointer to end of buffer */
blt_int8u *readptr; /**< pointer to next read location */
blt_int8u *writeptr; /**< pointer to next free location */
blt_int8u length; /**< number of buffer elements */
blt_int8u entries; /**< # of full buffer elements */
blt_int8u handle; /**< handle of the buffer */
struct t_fifo_ctrl *fifoctrlptr; /**< pointer to free buffer control */
} tFifoCtrl;
/** \brief Structure type for a fifo pipe. */
typedef struct
{
blt_int8u handle; /**< fifo handle */
blt_int8u data[FIFO_PIPE_SIZE]; /**< fifo data buffer */
} tFifoPipe; /**< USB pipe fifo type */
/****************************************************************************************
* Function prototypes
****************************************************************************************/
static blt_bool UsbReceiveByte(blt_int8u *data);
static blt_bool UsbTransmitByte(blt_int8u data);
static void UsbFifoMgrInit(void);
static blt_int8u UsbFifoMgrCreate(blt_int8u *buffer, blt_int8u length);
static blt_bool UsbFifoMgrWrite(blt_int8u handle, blt_int8u data);
static blt_bool UsbFifoMgrRead(blt_int8u handle, blt_int8u *data);
static blt_int8u UsbFifoMgrScan(blt_int8u handle);
/****************************************************************************************
* Local data declarations
****************************************************************************************/
/** \brief Local variable that holds the fifo control structures. */
static tFifoCtrl fifoCtrl[FIFO_MAX_BUFFERS];
/** \brief Local pointer that points to the next free fifo control structure. */
static tFifoCtrl *fifoCtrlFree;
/** \brief Fifo pipe used for the bulk in endpoint. */
static tFifoPipe fifoPipeBulkIN;
/** \brief Fifo pipe used for the bulk out endpoint. */
static tFifoPipe fifoPipeBulkOUT;
/** \brief USB device handle. */
static USBD_HandleTypeDef hUsbDeviceFS;
/************************************************************************************//**
** \brief Initializes the USB communication interface.
** \return none.
**
****************************************************************************************/
void UsbInit(void)
{
/* initialize the FIFO manager */
UsbFifoMgrInit();
/* place 2 buffers under FIFO management */
fifoPipeBulkIN.handle = UsbFifoMgrCreate(fifoPipeBulkIN.data, FIFO_PIPE_SIZE);
fifoPipeBulkOUT.handle = UsbFifoMgrCreate(fifoPipeBulkOUT.data, FIFO_PIPE_SIZE);
/* validate fifo handles */
ASSERT_RT((fifoPipeBulkIN.handle != FIFO_ERR_INVALID_HANDLE) && \
(fifoPipeBulkOUT.handle != FIFO_ERR_INVALID_HANDLE));
/* initialize the USB device libary */
USBD_Init(&hUsbDeviceFS, &FS_Desc, DEVICE_FS);
/* register the bootloader's custom USB Bulk based class */
USBD_RegisterClass(&hUsbDeviceFS, &USBD_Bulk);
/* inform application about the connect event */
UsbConnectHook(BLT_TRUE);
/* start the USB device */
USBD_Start(&hUsbDeviceFS);
/* perform low level connect of the device */
HAL_PCD_DevConnect((PCD_HandleTypeDef *)hUsbDeviceFS.pData);
/* extend the time that the backdoor is open in case the default timed backdoor
* mechanism is used.
*/
#if (BOOT_BACKDOOR_HOOKS_ENABLE == 0)
if (BackDoorGetExtension() < BOOT_COM_USB_BACKDOOR_EXTENSION_MS)
{
BackDoorSetExtension(BOOT_COM_USB_BACKDOOR_EXTENSION_MS);
}
#endif /* BOOT_BACKDOOR_HOOKS_ENABLE == 0 */
} /*** end of UsbInit ***/
/************************************************************************************//**
** \brief Releases the USB communication interface.
** \return none.
**
****************************************************************************************/
void UsbFree(void)
{
/* perform low level disconnect of the device */
HAL_PCD_DevDisconnect((PCD_HandleTypeDef *)hUsbDeviceFS.pData);
/* uninitialize the device */
USBD_DeInit(&hUsbDeviceFS);
/* inform application about the disconnect event */
UsbConnectHook(BLT_FALSE);
} /*** end of UsbFree ***/
/************************************************************************************//**
** \brief Transmits a packet formatted for the communication interface.
** \param data Pointer to byte array with data that it to be transmitted.
** \param len Number of bytes that are to be transmitted.
** \return none.
**
****************************************************************************************/
void UsbTransmitPacket(blt_int8u *data, blt_int8u len)
{
blt_int16u data_index;
blt_bool result;
/* verify validity of the len-paramenter */
ASSERT_RT(len <= BOOT_COM_USB_TX_MAX_DATA);
/* first transmit the length of the packet */
result = UsbTransmitByte(len);
ASSERT_RT(result == BLT_TRUE);
/* transmit all the packet bytes one-by-one */
for (data_index = 0; data_index < len; data_index++)
{
/* keep the watchdog happy */
CopService();
/* write byte */
result = UsbTransmitByte(data[data_index]);
ASSERT_RT(result == BLT_TRUE);
}
} /*** end of UsbTransmitPacket ***/
/************************************************************************************//**
** \brief Receives a communication interface packet if one is present.
** \param data Pointer to byte array where the data is to be stored.
** \param len Pointer where the length of the packet is to be stored.
** \return BLT_TRUE if a packet was received, BLT_FALSE otherwise.
**
****************************************************************************************/
blt_bool UsbReceivePacket(blt_int8u *data, blt_int8u *len)
{
static blt_int8u xcpCtoReqPacket[BOOT_COM_USB_RX_MAX_DATA+1]; /* one extra for length */
static blt_int8u xcpCtoRxLength;
static blt_bool xcpCtoRxInProgress = BLT_FALSE;
/* poll USB interrupt flags to process USB related events */
HAL_PCD_IRQHandler((PCD_HandleTypeDef *)hUsbDeviceFS.pData);
/* start of cto packet received? */
if (xcpCtoRxInProgress == BLT_FALSE)
{
/* store the message length when received */
if (UsbReceiveByte(&xcpCtoReqPacket[0]) == BLT_TRUE)
{
if ( (xcpCtoReqPacket[0] > 0) &&
(xcpCtoReqPacket[0] <= BOOT_COM_USB_RX_MAX_DATA) )
{
/* indicate that a cto packet is being received */
xcpCtoRxInProgress = BLT_TRUE;
/* reset packet data count */
xcpCtoRxLength = 0;
}
}
}
else
{
/* store the next packet byte */
if (UsbReceiveByte(&xcpCtoReqPacket[xcpCtoRxLength+1]) == BLT_TRUE)
{
/* increment the packet data count */
xcpCtoRxLength++;
/* check to see if the entire packet was received */
if (xcpCtoRxLength == xcpCtoReqPacket[0])
{
/* copy the packet data */
CpuMemCopy((blt_int32u)data, (blt_int32u)&xcpCtoReqPacket[1], xcpCtoRxLength);
/* done with cto packet reception */
xcpCtoRxInProgress = BLT_FALSE;
/* set the packet length */
*len = xcpCtoRxLength;
/* packet reception complete */
return BLT_TRUE;
}
}
}
/* packet reception not yet complete */
return BLT_FALSE;
} /*** end of UsbReceivePacket ***/
/************************************************************************************//**
** \brief Receives a communication interface byte if one is present.
** \param data Pointer to byte where the data is to be stored.
** \return BLT_TRUE if a byte was received, BLT_FALSE otherwise.
**
****************************************************************************************/
static blt_bool UsbReceiveByte(blt_int8u *data)
{
blt_bool result;
/* obtain data from the fifo */
result = UsbFifoMgrRead(fifoPipeBulkOUT.handle, data);
return result;
} /*** end of UsbReceiveByte ***/
/************************************************************************************//**
** \brief Transmits a communication interface byte.
** \param data Value of byte that is to be transmitted.
** \return BLT_TRUE if the byte was transmitted, BLT_FALSE otherwise.
**
****************************************************************************************/
static blt_bool UsbTransmitByte(blt_int8u data)
{
blt_bool result;
/* write data from to fifo */
result = UsbFifoMgrWrite(fifoPipeBulkIN.handle, data);
return result;
} /*** end of UsbTransmitByte ***/
/************************************************************************************//**
** \brief Checks if there is still data left to transmit and if so submits it
** for transmission with the USB endpoint.
** \return none.
**
****************************************************************************************/
void UsbTransmitPipeBulkIN(void)
{
/* USB_Tx_Buffer is static for run-time optimalization */
static uint8_t USB_Tx_Buffer[BULK_DATA_MAX_PACKET_SIZE];
blt_int8u nr_of_bytes_for_tx_endpoint;
blt_int8u byte_counter;
blt_int8u byte_value;
blt_bool result;
/* read how many bytes should be transmitted */
nr_of_bytes_for_tx_endpoint = UsbFifoMgrScan(fifoPipeBulkIN.handle);
/* only continue if there is actually data left to transmit */
if (nr_of_bytes_for_tx_endpoint == 0)
{
return;
}
/* make sure to not transmit more than the USB endpoint can handle */
if (nr_of_bytes_for_tx_endpoint > BULK_DATA_MAX_PACKET_SIZE)
{
nr_of_bytes_for_tx_endpoint = BULK_DATA_MAX_PACKET_SIZE;
}
/* copy the transmit data to the transmit buffer */
for (byte_counter=0; byte_counter < nr_of_bytes_for_tx_endpoint; byte_counter++)
{
/* obtain data from the fifo */
result = UsbFifoMgrRead(fifoPipeBulkIN.handle, &byte_value);
ASSERT_RT(result == BLT_TRUE);
/* store it in the endpoint's RAM */
USB_Tx_Buffer[byte_counter] = byte_value;
}
/* copy data to endpoint's RAM and start the transmission */
USBD_LL_Transmit(&hUsbDeviceFS, BULK_IN_EP, &USB_Tx_Buffer[0],
nr_of_bytes_for_tx_endpoint);
} /*** end of UsbTransmitPipeBulkIN ***/
/************************************************************************************//**
** \brief Stores data that was received on the Bulk OUT pipe in the fifo.
** \return none.
**
****************************************************************************************/
void UsbReceivePipeBulkOUT(blt_int8u epnum)
{
blt_int16u USB_Rx_Cnt=0;
blt_int8u *usbRxBufferPtr;
blt_int16u byte_counter;
blt_bool result;
/* Get the received data buffer and the number of received bytes */
usbRxBufferPtr = USBD_Bulk_GetRxBufferPtr();
USB_Rx_Cnt = USBD_LL_GetRxDataSize(&hUsbDeviceFS, epnum);
/* USB data will be immediately processed, this allow next USB traffic being
* NAKed till the end of the USART Xfer
*/
for (byte_counter=0; byte_counter<USB_Rx_Cnt; byte_counter++)
{
/* add the data to the fifo */
result = UsbFifoMgrWrite(fifoPipeBulkOUT.handle, usbRxBufferPtr[byte_counter]);
/* verify that the fifo wasn't full */
ASSERT_RT(result == BLT_TRUE);
}
/* Prepare Out endpoint to receive next packet */
USBD_LL_PrepareReceive(&hUsbDeviceFS,
BULK_OUT_EP,
USBD_Bulk_GetRxBufferPtr(),
BULK_DATA_FS_OUT_PACKET_SIZE);
} /*** end of UsbReceivePipeBulkOUT ***/
/************************************************************************************//**
** \brief Initializes the fifo manager. Each controlled fifo is assigned a
** unique handle, which is the same as its index into fifoCtrl[]. Each
** controlled fifo holds a pointer to the next free fifo control.
** For the last fifo in fifoCtrl[] this one is set to a null-pointer as
** an out of fifo control indicator. Function should be called once
** before any of the other fifo management functions are called.
** \return none.
**
****************************************************************************************/
static void UsbFifoMgrInit(void)
{
blt_int8u i;
tFifoCtrl *pbc1, *pbc2;
pbc1 = &fifoCtrl[0];
pbc2 = &fifoCtrl[1];
/* assign fifo handles and pointer to next free fifo */
for (i = 0; i < (FIFO_MAX_BUFFERS - 1); i++)
{
pbc1->handle = i;
pbc1->fifoctrlptr = pbc2;
pbc1++;
pbc2++;
}
/* initialize handle for the last one and use null-pointer for the next free fifo */
pbc1->handle = i;
pbc1->fifoctrlptr = (tFifoCtrl *)0;
fifoCtrlFree = &fifoCtrl[0];
} /*** end of UsbFifoMgrInit ***/
/************************************************************************************//**
** \brief Places a data storage array under fifo management control. A handle
** for identifying the fifo in subsequent fifo management function
** calls is returned, if successful.
** \param buffer Pointer to the first element in the data storage fifo.
** \param length Maximum number of data elements that can be stored in the fifo.
** \return Fifo handle if successfull, or FIFO_ERR_INVALID_HANDLE.
**
****************************************************************************************/
static blt_int8u UsbFifoMgrCreate(blt_int8u *buffer, blt_int8u length)
{
tFifoCtrl *pbc;
/* first determine if these is still a free fifo control available */
if (fifoCtrlFree == (tFifoCtrl *)0)
{
return FIFO_ERR_INVALID_HANDLE;
}
/* store pointer to free fifo and update pointer to next free one */
pbc = fifoCtrlFree;
fifoCtrlFree = pbc->fifoctrlptr;
/* initialize the buffer control */
pbc->length = length;
pbc->readptr = buffer;
pbc->writeptr = buffer;
pbc->entries = 0;
pbc->startptr = buffer;
pbc->endptr = (blt_int8u *)(buffer + length - 1);
/* return the handle to the successfully created fifo control */
return pbc->handle;
} /*** end of UsbFifoMgrCreate ***/
/************************************************************************************//**
** \brief Stores data in the fifo.
** \param handle Identifies the fifo to write data to.
** \param data Pointer to the data that is to be written to the fifo.
** \return BLT_TRUE if the data was successfully stored in the fifo, BLT_FALSE
** otherwise.
**
****************************************************************************************/
static blt_bool UsbFifoMgrWrite(blt_int8u handle, blt_int8u data)
{
/* check the validity of the handle parameter */
ASSERT_RT(handle < FIFO_MAX_BUFFERS);
/* check if fifo is full */
if (fifoCtrl[handle].entries == fifoCtrl[handle].length)
{
return BLT_FALSE;
}
/* copy data to fifo */
*fifoCtrl[handle].writeptr = data;
/* data written so update number of entries */
fifoCtrl[handle].entries++;
/* update write pointer */
fifoCtrl[handle].writeptr++;
/* check end of fifo */
if (fifoCtrl[handle].writeptr > fifoCtrl[handle].endptr)
{
/* set write pointer to start of the cyclic fifo */
fifoCtrl[handle].writeptr = fifoCtrl[handle].startptr;
}
/* still here so all is okay */
return BLT_TRUE;
} /*** end of UsbFifoMgrWrite ***/
/************************************************************************************//**
** \brief Retrieves data from the fifo.
** \param handle Identifies the fifo to read data from.
** \param data Pointer to where the read data is to be stored.
** \return BLT_TRUE if the data was successfully read from the fifo, BLT_FALSE
** otherwise.
**
****************************************************************************************/
static blt_bool UsbFifoMgrRead(blt_int8u handle, blt_int8u *data)
{
/* check the validity of the handle parameter */
ASSERT_RT(handle < FIFO_MAX_BUFFERS);
/* check if fifo is empty */
if (fifoCtrl[handle].entries == 0)
{
return BLT_FALSE;
}
/* read the data */
*data = *fifoCtrl[handle].readptr;
/* data read so update number of entries */
fifoCtrl[handle].entries--;
/* update read pointer */
fifoCtrl[handle].readptr++;
/* check end of fifo */
if (fifoCtrl[handle].readptr > fifoCtrl[handle].endptr)
{
/* set read pointer to start of the cyclic fifo */
fifoCtrl[handle].readptr = fifoCtrl[handle].startptr;
}
/* still here so all is good */
return BLT_TRUE;
} /*** end of UsbFifoMgrRead ***/
/************************************************************************************//**
** \brief Returns the number of data entries currently present in the fifo.
** \param handle Identifies the fifo that is to be scanned.
** \return Number of data entries in the fifo if successful, otherwise 0.
**
****************************************************************************************/
static blt_int8u UsbFifoMgrScan(blt_int8u handle)
{
/* check the validity of the handle parameter */
ASSERT_RT(handle < FIFO_MAX_BUFFERS);
/* read and return the number of data entries */
return fifoCtrl[handle].entries;
} /*** end of UsbFifoMgrScan ***/
#endif /* BOOT_COM_USB_ENABLE > 0 */
/*********************************** end of usb.c **************************************/

56
openblt/asserts.c Normal file
View File

@@ -0,0 +1,56 @@
/************************************************************************************//**
* \file Source/asserts.c
* \brief Bootloader assertion module source file.
* \ingroup Core
* \internal
*----------------------------------------------------------------------------------------
* C O P Y R I G H T
*----------------------------------------------------------------------------------------
* Copyright (c) 2011 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 */
#ifndef NDEBUG
/************************************************************************************//**
** \brief Called when a runtime assertion failed. It stores information about where
** the assertion occurred and halts the software program.
** \param file Name of the source file where the assertion occurred.
** \param line Linenumber in the source file where the assertion occurred.
** \return none
**
****************************************************************************************/
void AssertFailure(blt_char *file, blt_int32u line)
{
/* hang the software so that it requires a hard reset */
for (;;)
{
/* keep servicing the watchdog so that this one does not cause a reset */
CopService();
}
} /*** end of AssertFailure ***/
#endif /* !NDEBUG */
/*********************************** end of assert.c ***********************************/

62
openblt/asserts.h Normal file
View File

@@ -0,0 +1,62 @@
/************************************************************************************//**
* \file Source/asserts.h
* \brief Bootloader assertion module header file.
* \ingroup Core
* \internal
*----------------------------------------------------------------------------------------
* C O P Y R I G H T
*----------------------------------------------------------------------------------------
* Copyright (c) 2011 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
****************************************************************************************/
#ifndef ASSERT_H
#define ASSERT_H
/****************************************************************************************
* Macro definitions
****************************************************************************************/
/* declare assertion macro's. ASSERT_CT is for compile time assertions and ASSERT_RT is
* for runtime assertions.
*/
#ifdef NDEBUG
#define ASSERT_CT(cond) ((void)0)
#define ASSERT_RT(cond) ((void)0)
#else
#define ASSERT_CONCAT_(a, b) a##b
#define ASSERT_CONCAT(a, b) ASSERT_CONCAT_(a, b)
/** \brief Macro for assertions that can be performed at compile time. */
#define ASSERT_CT(cond) enum { ASSERT_CONCAT(assert_error_on_line_, __LINE__) = 1/(!!(cond)) }
/** \brief Macro for assertions that can only be performed at run time. */
#define ASSERT_RT(cond) \
if (cond) \
{ ; } \
else \
AssertFailure(__FILE__, __LINE__)
#endif /* NDEBUG */
/****************************************************************************************
* Function prototypes
****************************************************************************************/
#ifndef NDEBUG
void AssertFailure(blt_char *file, blt_int32u line);
#endif
#endif /* ASSERT_H */
/*********************************** end of assert.h ***********************************/

221
openblt/backdoor.c Normal file
View File

@@ -0,0 +1,221 @@
/************************************************************************************//**
* \file Source/backdoor.c
* \brief Bootloader backdoor entry source file.
* \ingroup Core
* \internal
*----------------------------------------------------------------------------------------
* C O P Y R I G H T
*----------------------------------------------------------------------------------------
* Copyright (c) 2011 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 */
/****************************************************************************************
* Macro definitions
****************************************************************************************/
#if (BOOT_BACKDOOR_HOOKS_ENABLE == 0)
#ifndef BOOT_BACKDOOR_ENTRY_TIMEOUT_MS
/** \brief Sets the time in milliseconds that the backdoor is open, but allow an
* override for this time. To change this value, simply add the macro
* BOOT_BACKDOOR_ENTRY_TIMEOUT_MS to blt_conf.h with your desired backdoor
* open time in milliseconds.
*/
#define BOOT_BACKDOOR_ENTRY_TIMEOUT_MS (1000)
#endif
#endif /* BOOT_BACKDOOR_HOOKS_ENABLE == 0 */
/****************************************************************************************
* Hook functions
****************************************************************************************/
#if (BOOT_BACKDOOR_HOOKS_ENABLE > 0)
extern void BackDoorInitHook(void);
extern blt_bool BackDoorEntryHook(void);
#endif
/****************************************************************************************
* Local data declarations
****************************************************************************************/
#if (BOOT_BACKDOOR_HOOKS_ENABLE == 0)
/** \brief To determine if the backdoor is open or closed. */
static blt_bool backdoorOpen;
/** \brief To determine how long the backdoor has been open in milliseconds. */
static blt_int32u backdoorOpenTime;
/** \brief In certain scenarios it is desired to be able to extend the default backdoor
* entry time at runtime. This variable holds the extension time in milliseconds.
* Note that this value must be initialized to zero here and not in function
* BackDoorInit(), because BackDoorInit() is one of the last functions called
* in BootInit(). This order should not be changed otherwise there is a chance
* that the timed backdoor partially or completely times out during BootInit().
* Initializing the variable here, allows function BackDoorSetExtension() to be
* called before BackDoorInit() was called.
*/
static blt_int32u backdoorExtensionTime = 0;
#endif
/************************************************************************************//**
** \brief Initializes the backdoor entry option.
** \return none
**
****************************************************************************************/
void BackDoorInit(void)
{
#if (BOOT_BACKDOOR_HOOKS_ENABLE > 0)
/* initialize application's backdoor functionality */
BackDoorInitHook();
/* attempt to start the user program when no backdoor entry is requested */
if (BackDoorEntryHook() == BLT_FALSE)
{
/* this function does not return if a valid user program is present */
CpuStartUserProgram();
}
#if (BOOT_FILE_SYS_ENABLE > 0)
else
{
/* the backdoor is open so we should check if a update from locally attached storage
* is requested and, if so, start it.
*/
FileHandleFirmwareUpdateRequest();
}
#endif
#else
/* open the backdoor after a reset */
backdoorOpen = BLT_TRUE;
BackDoorRestartTimer();
#endif
/* perform the first check that open/closes the backdoor */
BackDoorCheck();
} /*** end of BackDoorInit ***/
/************************************************************************************//**
** \brief The default backdoor entry feature keeps the bootloader active for a
** predetermined time after reset, allowing the host application to
** establish a connection and start a programming sequence. This function
** controls the opening/closing of the backdoor.
** \return none
**
****************************************************************************************/
void BackDoorCheck(void)
{
#if (BOOT_BACKDOOR_HOOKS_ENABLE == 0)
#if (BOOT_COM_ENABLE > 0)
/* check if a connection with the host was already established. in this case the
* backdoor stays open anyway, so no need to check if it needs to be closed.
*/
if (ComIsConnected() == BLT_TRUE)
{
return;
}
#endif
#if (BOOT_FILE_SYS_ENABLE > 0)
/* check if the file module is busy, indicating that a firmware update through the
* locally attached storage is in progress. in this case the backdoor stays open
* anyway, so no need to check if it needs to be closed.
*/
if (FileIsIdle() == BLT_FALSE)
{
return;
}
#endif
/* when the backdoor is still open, check if it's time to close it */
if (backdoorOpen == BLT_TRUE)
{
/* check if the backdoor entry time window elapsed */
if (TimerGet() >= (BOOT_BACKDOOR_ENTRY_TIMEOUT_MS + backdoorExtensionTime + backdoorOpenTime))
{
/* close the backdoor */
backdoorOpen = BLT_FALSE;
#if (BOOT_FILE_SYS_ENABLE > 0)
/* during the timed backdoor no remote update request was detected. now do one
* last check to see if a firmware update from locally attached storage is
* pending.
*/
if (FileHandleFirmwareUpdateRequest() == BLT_FALSE)
#endif
{
/* no firmware update requests detected, so attempt to start the user program.
* this function does not return if a valid user program is present.
*/
CpuStartUserProgram();
}
}
}
#endif
} /*** end of BackDoorCheck ***/
#if (BOOT_BACKDOOR_HOOKS_ENABLE == 0)
/************************************************************************************//**
** \brief Sets the amount of milliseconds that the default backdoor timeout time
** (BOOT_BACKDOOR_ENTRY_TIMEOUT_MS) is extended.
** \param extension_ms Extension time in milliseconds.
** \return none
**
****************************************************************************************/
void BackDoorSetExtension(blt_int32u extension_ms)
{
/* update the extension time */
backdoorExtensionTime = extension_ms;
} /*** end of BackDoorSetExtension ***/
/************************************************************************************//**
** \brief Gets the amount of milliseconds that the default backdoor timeout time
** (BOOT_BACKDOOR_ENTRY_TIMEOUT_MS) is extended.
** \return Extension time in milliseconds.
**
****************************************************************************************/
blt_int32u BackDoorGetExtension(void)
{
/* read out and reutrn the currently configured extension time */
return backdoorExtensionTime;
} /*** end of BackDoorGetExtension ***/
/************************************************************************************//**
** \brief Restarts the timed backdoor timer. It uses the current system time as the
** start time. The backdoor stays open for BOOT_BACKDOOR_ENTRY_TIMEOUT_MS
** after this start time, possibly extended in case BackDoorSetExtension() was
** called.
** \return none
**
****************************************************************************************/
void BackDoorRestartTimer(void)
{
/* only restart the time if the backdoor is actually still open */
if (backdoorOpen == BLT_TRUE)
{
backdoorOpenTime = TimerGet();
}
} /*** end of BackDoorRestartTimer ***/
#endif /* BOOT_BACKDOOR_HOOKS_ENABLE == 0 */
/*********************************** end of backdoor.c *********************************/

43
openblt/backdoor.h Normal file
View File

@@ -0,0 +1,43 @@
/************************************************************************************//**
* \file Source/backdoor.h
* \brief Bootloader backdoor entry header file.
* \ingroup Core
* \internal
*----------------------------------------------------------------------------------------
* C O P Y R I G H T
*----------------------------------------------------------------------------------------
* Copyright (c) 2011 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
****************************************************************************************/
#ifndef BACKDOOR_H
#define BACKDOOR_H
/****************************************************************************************
* Function prototypes
****************************************************************************************/
void BackDoorInit(void);
void BackDoorCheck(void);
#if (BOOT_BACKDOOR_HOOKS_ENABLE == 0)
void BackDoorSetExtension(blt_int32u extension_ms);
blt_int32u BackDoorGetExtension(void);
void BackDoorRestartTimer(void);
#endif
#endif /* BACKDOOR_H */
/*********************************** end of backdoor.h *********************************/

95
openblt/boot.c Normal file
View File

@@ -0,0 +1,95 @@
/************************************************************************************//**
* \file Source/boot.c
* \brief Bootloader core module source file.
* \ingroup Core
* \internal
*----------------------------------------------------------------------------------------
* C O P Y R I G H T
*----------------------------------------------------------------------------------------
* Copyright (c) 2011 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 */
/************************************************************************************//**
** \brief Initializes the bootloader core.
** \return none
**
****************************************************************************************/
void BootInit(void)
{
/* initialize the CPU */
CpuInit();
/* initialize the watchdog */
CopInit();
/* initialize the millisecond timer */
TimerInit();
/* initialize the non-volatile memory driver */
NvmInit();
#if (BOOT_FILE_SYS_ENABLE > 0)
/* initialize the file system module */
FileInit();
#endif
#if (BOOT_COM_ENABLE > 0)
/* initialize the communication module */
ComInit();
#endif
#if (ADDON_GATEWAY_MOD_ENABLE > 0)
/* initialize the gateway module */
GatewayInit();
#endif
/* initialize the backdoor entry */
BackDoorInit();
} /*** end of BootInit ***/
/************************************************************************************//**
** \brief Task function of the bootloader core that drives the program.
** \return none
**
****************************************************************************************/
void BootTask(void)
{
/* service the watchdog */
CopService();
/* update the millisecond timer */
TimerUpdate();
#if (BOOT_FILE_SYS_ENABLE > 0)
/* call worker task for updating firmware from locally attached file storage */
FileTask();
#endif /* BOOT_FILE_SYS_ENABLE > 0 */
#if (BOOT_COM_ENABLE > 0)
/* process possibly pending communication data */
ComTask();
#endif
#if (ADDON_GATEWAY_MOD_ENABLE > 0)
/* run the gateway */
GatewayTask();
#endif
/* control the backdoor */
BackDoorCheck();
} /*** end of BootTask ***/
/*********************************** end of boot.c *************************************/

79
openblt/boot.h Normal file
View File

@@ -0,0 +1,79 @@
/************************************************************************************//**
* \file Source/boot.h
* \brief Bootloader core module header file.
* \ingroup Core
* \internal
*----------------------------------------------------------------------------------------
* C O P Y R I G H T
*----------------------------------------------------------------------------------------
* Copyright (c) 2011 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
****************************************************************************************/
#ifndef BOOT_H
#define BOOT_H
/****************************************************************************************
* Defines
****************************************************************************************/
/** \brief Main version number of the bootloader core. */
#define BOOT_VERSION_CORE_MAIN (1u)
/** \brief Minor version number of the bootloader core. */
#define BOOT_VERSION_CORE_MINOR (14u)
/** \brief Patch number of the bootloader core. */
#define BOOT_VERSION_CORE_PATCH (1u)
/****************************************************************************************
* Include files
****************************************************************************************/
/* Note that it is possible to override the standard blt_conf.h configuration header
* file with a project specific one that is defined in the IDE/makefile. For example,
* the following define could be configured: PROJ_BLT_CONF_H="my_boot_config.h". This can
* be handy if you use the bootloader in several projects with a different configuration,
* and enables you to have just one bootloader source base.
*/
#include "types.h" /* variable types */
#include "asserts.h" /* assertion checks */
#ifdef PROJ_BLT_CONF_H
#include PROJ_BLT_CONF_H /* custom configuration */
#else
#include "blt_conf.h" /* bootloader configuration */
#endif /* PROJ_BLT_CONF_H */
#include "plausibility.h" /* plausibility checks */
#include "cpu.h" /* cpu driver module */
#include "cop.h" /* watchdog driver module */
#include "nvm.h" /* memory driver module */
#include "timer.h" /* timer driver module */
#include "backdoor.h" /* backdoor entry module */
#include "file.h" /* file system module */
#include "com.h" /* communication interface */
#if (ADDON_GATEWAY_MOD_ENABLE > 0)
#include "gateway.h" /* gateway add-on module */
#endif
/****************************************************************************************
* Function prototypes
****************************************************************************************/
void BootInit(void);
void BootTask(void);
#endif /* BOOT_H */
/*********************************** end of boot.h *************************************/

42
openblt/can.h Normal file
View File

@@ -0,0 +1,42 @@
/************************************************************************************//**
* \file Source/can.h
* \brief Bootloader CAN communication interface header file.
* \ingroup Core
* \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
****************************************************************************************/
#ifndef CAN_H
#define CAN_H
#if (BOOT_COM_CAN_ENABLE > 0)
/****************************************************************************************
* Function prototypes
****************************************************************************************/
void CanInit(void);
void CanTransmitPacket(blt_int8u *data, blt_int8u len);
blt_bool CanReceivePacket(blt_int8u *data, blt_int8u *len);
#endif /* BOOT_COM_CAN_ENABLE > 0 */
#endif /* CAN_H */
/*********************************** end of can.h **************************************/

356
openblt/com.c Normal file
View File

@@ -0,0 +1,356 @@
/************************************************************************************//**
* \file Source/com.c
* \brief Bootloader communication interface source file.
* \ingroup Core
* \internal
*----------------------------------------------------------------------------------------
* C O P Y R I G H T
*----------------------------------------------------------------------------------------
* Copyright (c) 2011 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 */
#if (BOOT_COM_CAN_ENABLE > 0)
#include "can.h" /* can driver module */
#endif
#if (BOOT_COM_RS232_ENABLE > 0)
#include "rs232.h" /* rs232 driver module */
#endif
#if (BOOT_COM_USB_ENABLE > 0)
#include "usb.h" /* usb driver module */
#endif
#if (BOOT_COM_NET_ENABLE > 0)
#include "net.h" /* tcp/ip driver module */
#endif
#if (BOOT_COM_ENABLE > 0)
/****************************************************************************************
* Local data declarations
****************************************************************************************/
/** \brief Holds the communication interface of the currently active interface. */
static tComInterfaceId comActiveInterface = COM_IF_OTHER;
/************************************************************************************//**
** \brief Initializes the communication module including the hardware needed for
** the communication.
** \return none
**
****************************************************************************************/
void ComInit(void)
{
/* initialize the XCP communication protocol */
XcpInit();
#if (BOOT_COM_CAN_ENABLE > 0)
/* initialize the CAN controller */
CanInit();
/* set it as active */
comActiveInterface = COM_IF_CAN;
#endif
#if (BOOT_COM_RS232_ENABLE > 0)
/* initialize the RS232 interface */
Rs232Init();
/* set it as active */
comActiveInterface = COM_IF_RS232;
#endif
#if (BOOT_COM_USB_ENABLE > 0)
/* initialize the USB interface */
UsbInit();
/* set it as active */
comActiveInterface = COM_IF_USB;
#endif
#if (BOOT_COM_NET_ENABLE > 0)
#if (BOOT_COM_NET_DEFERRED_INIT_ENABLE == 0)
/* initialize the TCP/IP interface */
NetInit();
/* set it as active */
comActiveInterface = COM_IF_NET;
#endif
#endif
} /*** end of ComInit ***/
/************************************************************************************//**
** \brief Updates the communication module by checking if new data was received
** and submitting the request to process newly received data.
** \return none
**
****************************************************************************************/
void ComTask(void)
{
blt_int8u xcpPacketLen;
/* make xcpCtoReqPacket static for runtime efficiency */
static blt_int8u xcpCtoReqPacket[BOOT_COM_RX_MAX_DATA];
#if (BOOT_COM_CAN_ENABLE > 0)
if (CanReceivePacket(&xcpCtoReqPacket[0], &xcpPacketLen) == BLT_TRUE)
{
/* make this the active interface */
comActiveInterface = COM_IF_CAN;
/* process packet */
XcpPacketReceived(&xcpCtoReqPacket[0], xcpPacketLen);
}
#endif
#if (BOOT_COM_RS232_ENABLE > 0)
if (Rs232ReceivePacket(&xcpCtoReqPacket[0], &xcpPacketLen) == BLT_TRUE)
{
/* make this the active interface */
comActiveInterface = COM_IF_RS232;
/* process packet */
XcpPacketReceived(&xcpCtoReqPacket[0], xcpPacketLen);
}
#endif
#if (BOOT_COM_USB_ENABLE > 0)
if (UsbReceivePacket(&xcpCtoReqPacket[0], &xcpPacketLen) == BLT_TRUE)
{
/* make this the active interface */
comActiveInterface = COM_IF_USB;
/* process packet */
XcpPacketReceived(&xcpCtoReqPacket[0], xcpPacketLen);
}
#endif
#if (BOOT_COM_NET_ENABLE > 0)
if (NetReceivePacket(&xcpCtoReqPacket[0], &xcpPacketLen) == BLT_TRUE)
{
/* make this the active interface */
comActiveInterface = COM_IF_NET;
/* process packet */
XcpPacketReceived(&xcpCtoReqPacket[0], xcpPacketLen);
}
#endif
} /*** end of ComTask ***/
/************************************************************************************//**
** \brief Releases the communication module.
** \return none
**
****************************************************************************************/
void ComFree(void)
{
#if (BOOT_COM_USB_ENABLE > 0)
/* disconnect the usb device from the usb host */
UsbFree();
#endif
} /*** end of ComFree ***/
/************************************************************************************//**
** \brief Transmits the packet using the xcp transport layer.
** \param data Pointer to the byte buffer with packet data.
** \param len Number of data bytes that need to be transmitted.
** \return none
**
****************************************************************************************/
void ComTransmitPacket(blt_int8u *data, blt_int16u len)
{
#if (BOOT_COM_CAN_ENABLE > 0)
/* transmit the packet. note that len is limited to 8 in the plausibility check,
* so cast is okay.
*/
if (comActiveInterface == COM_IF_CAN)
{
CanTransmitPacket(data, (blt_int8u)len);
}
#endif
#if (BOOT_COM_RS232_ENABLE > 0)
/* transmit the packet. note that len is limited to 255 in the plausibility check,
* so cast is okay.
*/
if (comActiveInterface == COM_IF_RS232)
{
Rs232TransmitPacket(data, (blt_int8u)len);
}
#endif
#if (BOOT_COM_USB_ENABLE > 0)
/* transmit the packet */
if (comActiveInterface == COM_IF_USB)
{
UsbTransmitPacket(data, len);
}
#endif
#if (BOOT_COM_NET_ENABLE > 0)
if (comActiveInterface == COM_IF_NET)
{
/* transmit the packet */
NetTransmitPacket(data, len);
}
#endif
/* send signal that the packet was transmitted */
XcpPacketTransmitted();
} /*** end of ComTransmitPacket ***/
/************************************************************************************//**
** \brief Obtains the maximum number of bytes that can be received on the specified
** communication interface.
** \return Maximum number of bytes that can be received.
**
****************************************************************************************/
blt_int16u ComGetActiveInterfaceMaxRxLen(void)
{
blt_int16u result;
/* filter on communication interface identifier */
switch (comActiveInterface)
{
case COM_IF_RS232:
result = BOOT_COM_RS232_RX_MAX_DATA;
break;
case COM_IF_CAN:
result = BOOT_COM_CAN_RX_MAX_DATA;
break;
case COM_IF_USB:
result = BOOT_COM_USB_RX_MAX_DATA;
break;
case COM_IF_NET:
result = BOOT_COM_NET_RX_MAX_DATA;
break;
default:
result = BOOT_COM_RX_MAX_DATA;
break;
}
return result;
} /*** end of ComGetActiveInterfaceMaxRxLen ***/
/************************************************************************************//**
** \brief Obtains the maximum number of bytes that can be transmitted on the
** specified communication interface.
** \return Maximum number of bytes that can be received.
**
****************************************************************************************/
blt_int16u ComGetActiveInterfaceMaxTxLen(void)
{
blt_int16u result;
/* filter on communication interface identifier */
switch (comActiveInterface)
{
case COM_IF_RS232:
result = BOOT_COM_RS232_TX_MAX_DATA;
break;
case COM_IF_CAN:
result = BOOT_COM_CAN_TX_MAX_DATA;
break;
case COM_IF_USB:
result = BOOT_COM_USB_TX_MAX_DATA;
break;
case COM_IF_NET:
result = BOOT_COM_NET_TX_MAX_DATA;
break;
default:
result = BOOT_COM_TX_MAX_DATA;
break;
}
return result;
} /*** end of ComGetActiveInterfaceMaxTxLen ***/
/************************************************************************************//**
** \brief This function obtains the XCP connection state.
** \return BLT_TRUE when an XCP connection is established, BLT_FALSE otherwise.
**
****************************************************************************************/
blt_bool ComIsConnected(void)
{
blt_bool result = BLT_FALSE;
/* Is there an active XCP connection? This indicates that the communication interface
* is in the connection state.
*/
if (XcpIsConnected())
{
result = BLT_TRUE;
}
#if (ADDON_GATEWAY_MOD_ENABLE > 0)
/* Is the gateway active? This indicates an XCP connection with a slave. */
if (GatewayIsActive())
{
result = BLT_TRUE;
}
#endif
/* give the result back to the caller. */
return result;
} /*** end of ComIsConnected ***/
#if (BOOT_COM_DEFERRED_INIT_ENABLE == 1)
/************************************************************************************//**
** \brief The deferred init feature makes it possible to bypass the initialization of
** a communication interface until this function is called. This feature can
** be enabled for a specific communication interface via macro
** BOOT_COM_XXX_DEFERRED_INIT_ENABLE in blt_conf.h. At this point only the NET
** communication interface supports this feature, as its initialization can
** take quite a long time. If there is a valid user program present, then this
** would cause an unwanted delay after each reset before the user program can
** be started.
** \attention Note that when this feature is enabled for a communication interface, the
** communication interface is only enabled when: (a) no valid user program is
** present or (b) when CpuUserProgramStartHook() returns BLT_FALSE. This means
** that after a normal reactivation of the bootloader from the user program,
** the communication interface is not initialized and firmware updates are
** not possible! In this case it is recommended to somehow pass on the
** communication initialization request from the user program to the
** bootloader. When this request detected by the bootloader application, this
** function should be called. EEPROM or shared RAM can be used to pass on such
** a request.
** \return none
**
****************************************************************************************/
void ComDeferredInit(void)
{
#if (BOOT_COM_NET_ENABLE > 0)
#if (BOOT_COM_NET_DEFERRED_INIT_ENABLE == 1)
/* perform deferred initialization the TCP/IP interface */
NetDeferredInit();
/* set it as active */
comActiveInterface = COM_IF_NET;
#endif
#endif
#if (BOOT_BACKDOOR_HOOKS_ENABLE == 0)
/* the default internal timed backdoor mechanism should start its timer after the
* communication interfaces are initialized. since a deferred initialization was now
* performed, the backdoor timer should be restarted.
*/
BackDoorRestartTimer();
#endif
} /*** end of ComDeferredInit ***/
#endif /* BOOT_COM_DEFERRED_INIT_ENABLE == 1 */
#endif /* BOOT_COM_ENABLE > 0 */
/*********************************** end of com.c **************************************/

145
openblt/com.h Normal file
View File

@@ -0,0 +1,145 @@
/************************************************************************************//**
* \file Source/com.h
* \brief Bootloader communication interface header file.
* \ingroup Core
* \internal
*----------------------------------------------------------------------------------------
* C O P Y R I G H T
*----------------------------------------------------------------------------------------
* Copyright (c) 2011 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
****************************************************************************************/
#ifndef COM_H
#define COM_H
#if (BOOT_COM_ENABLE > 0)
/****************************************************************************************
* Include files
****************************************************************************************/
#include "xcp.h" /* xcp communication layer */
/****************************************************************************************
* Macro definitions
****************************************************************************************/
/** \brief Defines the maximum number of bytes for transport layer reception
* depending on the activates interface(s).
*/
#define BOOT_COM_RX_MAX_DATA (1)
/* update in case CAN interface uses more */
#if (BOOT_COM_CAN_RX_MAX_DATA > BOOT_COM_RX_MAX_DATA)
#undef BOOT_COM_RX_MAX_DATA
#define BOOT_COM_RX_MAX_DATA (BOOT_COM_CAN_RX_MAX_DATA)
#endif
/* update in case RS232 interface uses more */
#if (BOOT_COM_RS232_RX_MAX_DATA > BOOT_COM_RX_MAX_DATA)
#undef BOOT_COM_RX_MAX_DATA
#define BOOT_COM_RX_MAX_DATA (BOOT_COM_RS232_RX_MAX_DATA)
#endif
/* update in case USB interface uses more */
#if (BOOT_COM_USB_RX_MAX_DATA > BOOT_COM_RX_MAX_DATA)
#undef BOOT_COM_RX_MAX_DATA
#define BOOT_COM_RX_MAX_DATA (BOOT_COM_USB_RX_MAX_DATA)
#endif
/* update in case NET interface uses more */
#if (BOOT_COM_NET_RX_MAX_DATA > BOOT_COM_RX_MAX_DATA)
#undef BOOT_COM_RX_MAX_DATA
#define BOOT_COM_RX_MAX_DATA (BOOT_COM_NET_RX_MAX_DATA)
#endif
/** \brief Defines the maximum number of bytes for transport layer transmission
* depending on the activates interface(s).
*/
#define BOOT_COM_TX_MAX_DATA (1)
/* update in case CAN interface uses more */
#if (BOOT_COM_CAN_TX_MAX_DATA > BOOT_COM_TX_MAX_DATA)
#undef BOOT_COM_TX_MAX_DATA
#define BOOT_COM_TX_MAX_DATA (BOOT_COM_CAN_TX_MAX_DATA)
#endif
/* update in case RS232 interface uses more */
#if (BOOT_COM_RS232_TX_MAX_DATA > BOOT_COM_TX_MAX_DATA)
#undef BOOT_COM_TX_MAX_DATA
#define BOOT_COM_TX_MAX_DATA (BOOT_COM_RS232_TX_MAX_DATA)
#endif
/* update in case USB interface uses more */
#if (BOOT_COM_USB_TX_MAX_DATA > BOOT_COM_TX_MAX_DATA)
#undef BOOT_COM_TX_MAX_DATA
#define BOOT_COM_TX_MAX_DATA (BOOT_COM_USB_TX_MAX_DATA)
#endif
/* update in case NET interface uses more */
#if (BOOT_COM_NET_TX_MAX_DATA > BOOT_COM_TX_MAX_DATA)
#undef BOOT_COM_TX_MAX_DATA
#define BOOT_COM_TX_MAX_DATA (BOOT_COM_NET_TX_MAX_DATA)
#endif
/****************************************************************************************
* Plausibility
****************************************************************************************/
#if (BOOT_COM_TX_MAX_DATA < 1)
#undef BOOT_COM_TX_MAX_DATA
#define BOOT_COM_TX_MAX_DATA (8)
#endif
#if (BOOT_COM_TX_MAX_DATA > 256)
#error "COM.H, BOOT_COM_TX_MAX_DATA cannot be larger than 256."
#endif
#if (BOOT_COM_RX_MAX_DATA < 1)
#undef BOOT_COM_RX_MAX_DATA
#define BOOT_COM_RX_MAX_DATA (8)
#endif
#if (BOOT_COM_RX_MAX_DATA > 65536)
#error "COM.H, BOOT_COM_RX_MAX_DATA cannot be larger than 65536."
#endif
/****************************************************************************************
* Type definitions
****************************************************************************************/
/** \brief Enumeration for the different communication interfaces. */
typedef enum
{
COM_IF_RS232, /**< RS232 interface */
COM_IF_CAN, /**< CAN interface */
COM_IF_USB, /**< USB interface */
COM_IF_NET, /**< NET interface */
COM_IF_OTHER /**< Other interface */
} tComInterfaceId;
/****************************************************************************************
* Function prototypes
****************************************************************************************/
void ComInit(void);
#if (BOOT_COM_DEFERRED_INIT_ENABLE == 1)
void ComDeferredInit(void);
#endif
void ComTask(void);
void ComFree(void);
blt_int16u ComGetActiveInterfaceMaxRxLen(void);
blt_int16u ComGetActiveInterfaceMaxTxLen(void);
void ComTransmitPacket(blt_int8u *data, blt_int16u len);
blt_bool ComIsConnected(void);
#endif /* BOOT_COM_ENABLE > 0 */
#endif /* COM_H */
/*********************************** end of com.h **************************************/

70
openblt/cop.c Normal file
View File

@@ -0,0 +1,70 @@
/************************************************************************************//**
* \file Source/cop.c
* \brief Bootloader watchdog module source file.
* \ingroup Core
* \internal
*----------------------------------------------------------------------------------------
* C O P Y R I G H T
*----------------------------------------------------------------------------------------
* Copyright (c) 2011 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 */
/****************************************************************************************
* Hook functions
****************************************************************************************/
#if (BOOT_COP_HOOKS_ENABLE > 0)
extern void CopInitHook(void);
extern void CopServiceHook(void);
#endif
/************************************************************************************//**
** \brief Watchdog initialization function.
** \return none
**
****************************************************************************************/
void CopInit(void)
{
#if (BOOT_COP_HOOKS_ENABLE > 0)
CopInitHook();
#endif
} /*** end of CopInit ***/
/************************************************************************************//**
** \brief Watchdog service function to prevent the watchdog from timing out.
** \return none
**
****************************************************************************************/
void CopService(void)
{
#if (BOOT_COP_HOOKS_ENABLE > 0)
CopServiceHook();
#endif
} /*** end of CopService ***/
/*********************************** end of cop.c **************************************/

39
openblt/cop.h Normal file
View File

@@ -0,0 +1,39 @@
/************************************************************************************//**
* \file Source/cop.h
* \brief Bootloader watchdog module header file.
* \ingroup Core
* \internal
*----------------------------------------------------------------------------------------
* C O P Y R I G H T
*----------------------------------------------------------------------------------------
* Copyright (c) 2011 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
****************************************************************************************/
#ifndef COP_H
#define COP_H
/****************************************************************************************
* Function prototypes
****************************************************************************************/
void CopInit(void);
void CopService(void);
#endif /* COP_H */
/*********************************** end of cop.h **************************************/

44
openblt/cpu.h Normal file
View File

@@ -0,0 +1,44 @@
/************************************************************************************//**
* \file Source/cpu.h
* \brief Bootloader cpu module header file.
* \ingroup Core
* \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
****************************************************************************************/
#ifndef CPU_H
#define CPU_H
/****************************************************************************************
* Function prototypes
****************************************************************************************/
void CpuInit(void);
void CpuStartUserProgram(void);
void CpuMemCopy(blt_addr dest, blt_addr src, blt_int16u len);
void CpuMemSet(blt_addr dest, blt_int8u value, blt_int16u len);
void CpuIrqDisable(void);
void CpuIrqEnable(void);
#endif /* CPU_H */
/*********************************** end of cpu.h **************************************/

853
openblt/file.c Normal file
View File

@@ -0,0 +1,853 @@
/************************************************************************************//**
* \file Source/file.c
* \brief Bootloader file system interface source file.
* \ingroup Core
* \internal
*----------------------------------------------------------------------------------------
* C O P Y R I G H T
*----------------------------------------------------------------------------------------
* Copyright (c) 2013 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 <string.h> /* for strcpy etc. */
#include <ctype.h> /* for toupper() etc. */
#if (BOOT_FILE_SYS_ENABLE > 0)
/****************************************************************************************
* Type definitions
****************************************************************************************/
/** \brief Enumeration for the different internal module states. */
typedef enum
{
FIRMWARE_UPDATE_STATE_IDLE, /**< idle state */
FIRMWARE_UPDATE_STATE_STARTING, /**< starting state */
FIRMWARE_UPDATE_STATE_ERASING, /**< erasing state */
FIRMWARE_UPDATE_STATE_PROGRAMMING /**< programming state */
} tFirmwareUpdateState;
/** \brief Structure type with information for the memory erase opeartion. */
typedef struct
{
blt_addr start_address; /**< erase start address */
blt_int32u total_size; /**< total number of bytes to erase */
} tFileEraseInfo;
/** \brief Structure type for grouping FATFS related objects used by this module. */
typedef struct
{
FATFS fs; /**< file system object for mouting */
FIL file; /**< file object for firmware file */
} tFatFsObjects;
/****************************************************************************************
* Function prototypes
****************************************************************************************/
#if (BOOT_FILE_LOGGING_ENABLE > 0)
static blt_char FileLibByteNibbleToChar(blt_int8u nibble);
static blt_char *FileLibByteToHexString(blt_int8u byte_val, blt_char *destination);
static blt_char *FileLibLongToIntString(blt_int32u long_val, blt_char *destination);
#endif
static blt_int8u FileLibHexStringToByte(const blt_char *hexstring);
/****************************************************************************************
* Hook functions
****************************************************************************************/
extern blt_bool FileIsFirmwareUpdateRequestedHook(void);
extern const blt_char *FileGetFirmwareFilenameHook(void);
extern void FileFirmwareUpdateStartedHook(void);
extern void FileFirmwareUpdateCompletedHook(void);
extern void FileFirmwareUpdateErrorHook(blt_int8u error_code);
extern void FileFirmwareUpdateLogHook(blt_char *info_string);
/****************************************************************************************
* Local data declarations
****************************************************************************************/
/** \brief Local variable that holds the internal module state. */
static tFirmwareUpdateState firmwareUpdateState;
/** \brief Local variable for the used FATFS objects in this module. */
static tFatFsObjects fatFsObjects;
/** \brief Local variable for storing S-record line parsing results. */
static tSrecLineParseObject lineParseObject;
/** \brief Local variable for storing information regarding the memory erase operation.*/
static tFileEraseInfo eraseInfo;
#if (BOOT_FILE_LOGGING_ENABLE > 0)
/** \brief Local character buffer for storing the string with log information. */
static blt_char loggingStr[64];
#endif
/***********************************************************************************//**
** \brief Initializes the file system interface module. The initial firmware
** update state is set to idle and the file system is mounted as
** logical disk 0.
** \return none
**
****************************************************************************************/
void FileInit(void)
{
FRESULT fresult;
/* set the initial state */
firmwareUpdateState = FIRMWARE_UPDATE_STATE_IDLE;
/* mount the file system, using logical disk 0 */
fresult = f_mount(&fatFsObjects.fs, "0:", 0);
/* mounting does not access the disk and should succeed unless misconfigured */
ASSERT_RT(fresult == FR_OK);
} /*** end of FileInit ***/
/***********************************************************************************//**
** \brief This function checks if a firmware update through the locally attached
** storage is in progress or not (idle).
** \return BLT_TRUE when in idle state, BLT_FALSE otherwise.
**
****************************************************************************************/
blt_bool FileIsIdle(void)
{
if (firmwareUpdateState == FIRMWARE_UPDATE_STATE_IDLE)
{
return BLT_TRUE;
}
return BLT_FALSE;
} /*** end of FileIsIdle ***/
/***********************************************************************************//**
** \brief This function checks if a firmware update through the locally attached
** storage is requested to be started and if so processes this request
** by transitioning from the IDLE to the STARTING state.
** \return BLT_TRUE when a firmware update is requested, BLT_FALSE otherwise.
**
****************************************************************************************/
blt_bool FileHandleFirmwareUpdateRequest(void)
{
#if (BOOT_COM_ENABLE > 0)
/* make sure that there is no connection with a remote host to prevent two firmware
* updates happening at the same time
*/
if (ComIsConnected() == BLT_TRUE)
{
return BLT_FALSE;
}
#endif
/* a new firmware update request can only be handled if not already busy with one */
if (firmwareUpdateState != FIRMWARE_UPDATE_STATE_IDLE)
{
return BLT_FALSE;
}
/* check if a firmware update is requested */
if (FileIsFirmwareUpdateRequestedHook() == BLT_TRUE)
{
/* transition from IDLE to STARTING state, which kicks off the update sequence */
firmwareUpdateState = FIRMWARE_UPDATE_STATE_STARTING;
return BLT_TRUE;
}
/* still here so no update request pending */
return BLT_FALSE;
} /*** end of FileHandleFirmwareUpdateRequest ***/
/***********************************************************************************//**
** \brief File system task function for managing the firmware updates from
** locally attached storage.
** \return none.
**
****************************************************************************************/
void FileTask(void)
{
blt_int16s parse_result = 0;
blt_char *read_line_ptr;
/* ------------------------------- idle -------------------------------------------- */
if (firmwareUpdateState == FIRMWARE_UPDATE_STATE_IDLE)
{
/* currently, nothings need to be done while idling */
}
/* ------------------------------- starting ---------------------------------------- */
else if (firmwareUpdateState == FIRMWARE_UPDATE_STATE_STARTING)
{
/* reinit the NVM driver because a new firmware update is about the start */
NvmInit();
#if (BOOT_FILE_STARTED_HOOK_ENABLE > 0)
/* inform application about update started event via hook function */
FileFirmwareUpdateStartedHook();
#endif
#if (BOOT_FILE_LOGGING_ENABLE > 0)
FileFirmwareUpdateLogHook("Firmware update request detected\n\r");
FileFirmwareUpdateLogHook("Opening firmware file for reading...");
#endif
/* attempt to obtain a file object for the firmware file */
if (f_open(&fatFsObjects.file, FileGetFirmwareFilenameHook(), FA_OPEN_EXISTING | FA_READ) != FR_OK)
{
/* cannot continue with firmware update so go back to idle state */
firmwareUpdateState = FIRMWARE_UPDATE_STATE_IDLE;
/* can't open file */
#if (BOOT_FILE_LOGGING_ENABLE > 0)
FileFirmwareUpdateLogHook("ERROR\n\r");
#endif
#if (BOOT_FILE_ERROR_HOOK_ENABLE > 0)
FileFirmwareUpdateErrorHook(FILE_ERROR_CANNOT_OPEN_FIRMWARE_FILE);
#endif
/* nothing left to do now */
return;
}
#if (BOOT_FILE_LOGGING_ENABLE > 0)
FileFirmwareUpdateLogHook("OK\n\r");
FileFirmwareUpdateLogHook("Starting the programming sequence\n\r");
FileFirmwareUpdateLogHook("Parsing firmware file to detect erase blocks...");
#endif
/* prepare data objects for the erasing state */
eraseInfo.start_address = 0;
eraseInfo.total_size = 0;
/* transition from idle to erasing state */
firmwareUpdateState = FIRMWARE_UPDATE_STATE_ERASING;
}
/* ------------------------------- erasing ----------------------------------------- */
else if (firmwareUpdateState == FIRMWARE_UPDATE_STATE_ERASING)
{
/* read a line from the file */
read_line_ptr = f_gets(lineParseObject.line, sizeof(lineParseObject.line), &fatFsObjects.file);
/* check if an error occurred */
if (f_error(&fatFsObjects.file) > 0)
{
/* cannot continue with firmware update so go back to idle state */
firmwareUpdateState = FIRMWARE_UPDATE_STATE_IDLE;
#if (BOOT_FILE_LOGGING_ENABLE > 0)
FileFirmwareUpdateLogHook("ERROR\n\r");
#endif
#if (BOOT_FILE_ERROR_HOOK_ENABLE > 0)
FileFirmwareUpdateErrorHook(FILE_ERROR_CANNOT_READ_FROM_FILE);
#endif
/* close the file */
f_close(&fatFsObjects.file);
return;
}
/* parse the S-Record line without copying the data values if the line is not empty */
if (read_line_ptr != BLT_NULL)
{
parse_result = FileSrecParseLine(lineParseObject.line, &lineParseObject.address, BLT_NULL);
/* check parsing result */
if (parse_result == ERROR_SREC_INVALID_CHECKSUM)
{
/* cannot continue with firmware update so go back to idle state */
firmwareUpdateState = FIRMWARE_UPDATE_STATE_IDLE;
#if (BOOT_FILE_LOGGING_ENABLE > 0)
FileFirmwareUpdateLogHook("ERROR\n\r");
#endif
#if (BOOT_FILE_ERROR_HOOK_ENABLE > 0)
FileFirmwareUpdateErrorHook(FILE_ERROR_INVALID_CHECKSUM_IN_FILE);
#endif
/* close the file */
f_close(&fatFsObjects.file);
return;
}
}
/* only process parsing results if the line contained address/data info */
if (parse_result > 0)
{
/* is this the first address/data info we encountered? */
if (eraseInfo.total_size == 0)
{
/* store the start_address and byte count */
eraseInfo.start_address = lineParseObject.address;
eraseInfo.total_size = parse_result;
}
else
{
/* does this data fit at the end of the previously detected program block? */
if (lineParseObject.address == (eraseInfo.start_address + eraseInfo.total_size))
{
/* update the byte count */
eraseInfo.total_size += parse_result;
}
else
{
/* data does not belong to the previously detected block so there must be a
* gap in the data. first erase the currently detected block and then start
* tracking a new block.
*/
#if (BOOT_FILE_LOGGING_ENABLE > 0)
FileFirmwareUpdateLogHook("OK\n\r");
FileFirmwareUpdateLogHook("Erasing ");
/* convert size to string */
FileLibLongToIntString(eraseInfo.total_size, loggingStr);
FileFirmwareUpdateLogHook(loggingStr);
FileFirmwareUpdateLogHook(" bytes from memory at 0x");
/* convert address to hex-string */
FileLibByteToHexString((blt_int8u)(eraseInfo.start_address >> 24), &loggingStr[0]);
FileLibByteToHexString((blt_int8u)(eraseInfo.start_address >> 16), &loggingStr[2]);
FileLibByteToHexString((blt_int8u)(eraseInfo.start_address >> 8), &loggingStr[4]);
FileLibByteToHexString((blt_int8u)eraseInfo.start_address, &loggingStr[6]);
FileFirmwareUpdateLogHook(loggingStr);
FileFirmwareUpdateLogHook("...");
#endif
/* still here so we are ready to perform the memory erase operation */
if (NvmErase(eraseInfo.start_address, eraseInfo.total_size) == BLT_FALSE)
{
/* cannot continue with firmware update so go back to idle state */
firmwareUpdateState = FIRMWARE_UPDATE_STATE_IDLE;
#if (BOOT_FILE_LOGGING_ENABLE > 0)
FileFirmwareUpdateLogHook("ERROR\n\r");
#endif
#if (BOOT_FILE_ERROR_HOOK_ENABLE > 0)
FileFirmwareUpdateErrorHook(FILE_ERROR_CANNOT_ERASE_MEMORY);
#endif
/* close the file */
f_close(&fatFsObjects.file);
return;
}
#if (BOOT_FILE_LOGGING_ENABLE > 0)
FileFirmwareUpdateLogHook("OK\n\r");
FileFirmwareUpdateLogHook("Parsing firmware file to detect erase blocks...");
#endif
/* store the start_address and element count */
eraseInfo.start_address = lineParseObject.address;
eraseInfo.total_size = parse_result;
}
}
}
/* check if the end of the file was reached */
if (f_eof(&fatFsObjects.file) > 0)
{
/* rewind the file in preparation for the programming state */
if (f_lseek(&fatFsObjects.file, 0) != FR_OK)
{
/* cannot continue with firmware update so go back to idle state */
firmwareUpdateState = FIRMWARE_UPDATE_STATE_IDLE;
#if (BOOT_FILE_LOGGING_ENABLE > 0)
FileFirmwareUpdateLogHook("ERROR\n\r");
#endif
#if (BOOT_FILE_ERROR_HOOK_ENABLE > 0)
FileFirmwareUpdateErrorHook(FILE_ERROR_REWINDING_FILE_READ_POINTER);
#endif
/* close the file */
f_close(&fatFsObjects.file);
return;
}
/* still here so we are ready to perform the last memory erase operation, if there
* is still something left to erase.
*/
if (eraseInfo.total_size > 0)
{
#if (BOOT_FILE_LOGGING_ENABLE > 0)
FileFirmwareUpdateLogHook("OK\n\r");
FileFirmwareUpdateLogHook("Erasing ");
/* convert size to string */
FileLibLongToIntString(eraseInfo.total_size, loggingStr);
FileFirmwareUpdateLogHook(loggingStr);
FileFirmwareUpdateLogHook(" bytes from memory at 0x");
/* convert address to hex-string */
FileLibByteToHexString((blt_int8u)(eraseInfo.start_address >> 24), &loggingStr[0]);
FileLibByteToHexString((blt_int8u)(eraseInfo.start_address >> 16), &loggingStr[2]);
FileLibByteToHexString((blt_int8u)(eraseInfo.start_address >> 8), &loggingStr[4]);
FileLibByteToHexString((blt_int8u)eraseInfo.start_address, &loggingStr[6]);
FileFirmwareUpdateLogHook(loggingStr);
FileFirmwareUpdateLogHook("...");
#endif
if (NvmErase(eraseInfo.start_address, eraseInfo.total_size) == BLT_FALSE)
{
/* cannot continue with firmware update so go back to idle state */
firmwareUpdateState = FIRMWARE_UPDATE_STATE_IDLE;
#if (BOOT_FILE_LOGGING_ENABLE > 0)
FileFirmwareUpdateLogHook("ERROR\n\r");
#endif
#if (BOOT_FILE_ERROR_HOOK_ENABLE > 0)
FileFirmwareUpdateErrorHook(FILE_ERROR_CANNOT_ERASE_MEMORY);
#endif
/* close the file */
f_close(&fatFsObjects.file);
return;
}
}
#if (BOOT_FILE_LOGGING_ENABLE > 0)
FileFirmwareUpdateLogHook("OK\n\r");
#endif
/* all okay, then go to programming state */
firmwareUpdateState = FIRMWARE_UPDATE_STATE_PROGRAMMING;
}
}
/* ------------------------------- programming ------------------------------------- */
else if (firmwareUpdateState == FIRMWARE_UPDATE_STATE_PROGRAMMING)
{
/* read a line from the file */
read_line_ptr = f_gets(lineParseObject.line, sizeof(lineParseObject.line), &fatFsObjects.file);
/* check if an error occurred */
if (f_error(&fatFsObjects.file) > 0)
{
/* cannot continue with firmware update so go back to idle state */
firmwareUpdateState = FIRMWARE_UPDATE_STATE_IDLE;
#if (BOOT_FILE_LOGGING_ENABLE > 0)
FileFirmwareUpdateLogHook("Reading line from file...ERROR\n\r");
#endif
#if (BOOT_FILE_ERROR_HOOK_ENABLE > 0)
FileFirmwareUpdateErrorHook(FILE_ERROR_CANNOT_READ_FROM_FILE);
#endif
/* close the file */
f_close(&fatFsObjects.file);
return;
}
/* parse the S-Record line if the line is not empty */
if (read_line_ptr != BLT_NULL)
{
parse_result = FileSrecParseLine(lineParseObject.line, &lineParseObject.address, lineParseObject.data);
/* check parsing result */
if (parse_result == ERROR_SREC_INVALID_CHECKSUM)
{
/* cannot continue with firmware update so go back to idle state */
firmwareUpdateState = FIRMWARE_UPDATE_STATE_IDLE;
#if (BOOT_FILE_LOGGING_ENABLE > 0)
FileFirmwareUpdateLogHook("Invalid checksum found...ERROR\n\r");
#endif
#if (BOOT_FILE_ERROR_HOOK_ENABLE > 0)
FileFirmwareUpdateErrorHook(FILE_ERROR_INVALID_CHECKSUM_IN_FILE);
#endif
/* close the file */
f_close(&fatFsObjects.file);
return;
}
}
/* only process parsing results if the line contained address/data info */
if (parse_result > 0)
{
#if (BOOT_FILE_LOGGING_ENABLE > 0)
FileFirmwareUpdateLogHook("Programming ");
/* convert size to string */
FileLibLongToIntString(parse_result, loggingStr);
FileFirmwareUpdateLogHook(loggingStr);
FileFirmwareUpdateLogHook(" bytes to memory at 0x");
/* convert address to hex-string */
FileLibByteToHexString((blt_int8u)(lineParseObject.address >> 24), &loggingStr[0]);
FileLibByteToHexString((blt_int8u)(lineParseObject.address >> 16), &loggingStr[2]);
FileLibByteToHexString((blt_int8u)(lineParseObject.address >> 8), &loggingStr[4]);
FileLibByteToHexString((blt_int8u)lineParseObject.address, &loggingStr[6]);
FileFirmwareUpdateLogHook(loggingStr);
FileFirmwareUpdateLogHook("...");
#endif
/* program the data */
if (NvmWrite(lineParseObject.address, parse_result, lineParseObject.data) == BLT_FALSE)
{
/* cannot continue with firmware update so go back to idle state */
firmwareUpdateState = FIRMWARE_UPDATE_STATE_IDLE;
#if (BOOT_FILE_LOGGING_ENABLE > 0)
FileFirmwareUpdateLogHook("ERROR\n\r");
#endif
#if (BOOT_FILE_ERROR_HOOK_ENABLE > 0)
FileFirmwareUpdateErrorHook(FILE_ERROR_CANNOT_PROGRAM_MEMORY);
#endif
/* close the file */
f_close(&fatFsObjects.file);
return;
}
#if (BOOT_FILE_LOGGING_ENABLE > 0)
FileFirmwareUpdateLogHook("OK\n\r");
#endif
}
/* check if the end of the file was reached */
if (f_eof(&fatFsObjects.file) > 0)
{
#if (BOOT_FILE_LOGGING_ENABLE > 0)
FileFirmwareUpdateLogHook("Writing program checksum...");
#endif
/* finish the programming by writing the checksum */
if (NvmDone() == BLT_FALSE)
{
/* cannot continue with firmware update so go back to idle state */
firmwareUpdateState = FIRMWARE_UPDATE_STATE_IDLE;
#if (BOOT_FILE_LOGGING_ENABLE > 0)
FileFirmwareUpdateLogHook("ERROR\n\r");
#endif
#if (BOOT_FILE_ERROR_HOOK_ENABLE > 0)
FileFirmwareUpdateErrorHook(FILE_ERROR_CANNOT_WRITE_CHECKSUM);
#endif
/* close the file */
f_close(&fatFsObjects.file);
return;
}
#if (BOOT_FILE_LOGGING_ENABLE > 0)
FileFirmwareUpdateLogHook("OK\n\r");
FileFirmwareUpdateLogHook("Closing firmware file\n\r");
#endif
/* close the file */
f_close(&fatFsObjects.file);
#if (BOOT_FILE_LOGGING_ENABLE > 0)
FileFirmwareUpdateLogHook("Firmware update successfully completed\n\r");
#endif
/* all done so transistion back to idle mode */
firmwareUpdateState = FIRMWARE_UPDATE_STATE_IDLE;
#if (BOOT_FILE_COMPLETED_HOOK_ENABLE > 0)
/* inform application about update completed event via hook function */
FileFirmwareUpdateCompletedHook();
#endif
/* attempt to start the user program now that programming is done */
CpuStartUserProgram();
}
}
} /*** end of FileTask ***/
/************************************************************************************//**
** \brief Inspects a line from a Motorola S-Record file to determine its type.
** \param line A line from the S-Record.
** \return the S-Record line type.
**
****************************************************************************************/
tSrecLineType FileSrecGetLineType(const blt_char *line)
{
/* check if the line starts with the 'S' character, followed by a digit */
if ((toupper((blt_int16s)(line[0])) != 'S') || (isdigit((blt_int16s)(line[1])) == 0))
{
/* not a valid S-Record line type */
return LINE_TYPE_UNSUPPORTED;
}
/* determine the line type */
if (line[1] == '1')
{
return LINE_TYPE_S1;
}
if (line[1] == '2')
{
return LINE_TYPE_S2;
}
if (line[1] == '3')
{
return LINE_TYPE_S3;
}
/* still here so not a supported line type found */
return LINE_TYPE_UNSUPPORTED;
} /*** end of FileSrecGetLineType ***/
/************************************************************************************//**
** \brief Inspects an S1, S2 or S3 line from a Motorola S-Record file to
** determine if the checksum at the end is corrrect.
** \param line An S1, S2 or S3 line from the S-Record.
** \return BLT_TRUE if the checksum is correct, BLT_FALSE otherwise.
**
****************************************************************************************/
blt_bool FileSrecVerifyChecksum(const blt_char *line)
{
blt_int16u bytes_on_line;
blt_int8u checksum = 0;
/* adjust pointer to point to byte count value */
line += 2;
/* read out the number of byte values that follow on the line */
bytes_on_line = FileLibHexStringToByte(line);
/* byte count is part of checksum */
checksum += bytes_on_line;
/* adjust pointer to the first byte of the address */
line += 2;
/* add byte values of address and data, but not the final checksum */
do
{
/* add the next byte value to the checksum */
checksum += FileLibHexStringToByte(line);
/* update counter */
bytes_on_line--;
/* point to next hex string in the line */
line += 2;
}
while (bytes_on_line > 1);
/* the checksum is calculated by summing up the values of the byte count, address and
* databytes and then taking the 1-complement of the sum's least signigicant byte */
checksum = ~checksum;
/* finally verify the calculated checksum with the one at the end of the line */
if (checksum != FileLibHexStringToByte(line))
{
/* checksum incorrect */
return BLT_FALSE;
}
/* still here so the checksum was correct */
return BLT_TRUE;
} /*** end of FileSrecVerifyChecksum ***/
/************************************************************************************//**
** \brief Parses a line from a Motorola S-Record file and looks for S1, S2 or S3
** lines with data. Note that if a null pointer is passed as the data
** parameter, then no data is extracted from the line.
** \param line A line from the S-Record.
** \param address Address found in the S-Record data line.
** \param data Byte array where the data bytes from the S-Record data line
** are stored.
** \return The number of data bytes found on the S-record data line, 0 in case
** the line is not an S1, S2 or S3 line or ERROR_SREC_INVALID_CHECKSUM
** in case the checksum validation failed.
**
****************************************************************************************/
blt_int16s FileSrecParseLine(const blt_char *line, blt_addr *address, blt_int8u *data)
{
tSrecLineType lineType;
blt_int16s data_byte_count = 0;
blt_int16u bytes_on_line;
blt_int16u i;
/* check pointers and not that data can be a null pointer */
ASSERT_RT((address != BLT_NULL) && (line != BLT_NULL));
/* figure out what type of line we are dealing with */
lineType = FileSrecGetLineType(line);
/* make sure it is one that we can parse */
if (lineType == LINE_TYPE_UNSUPPORTED)
{
/* not a parsing error, but simply no data on this line */
return 0;
}
/* verify the checksum */
if (FileSrecVerifyChecksum(line) == BLT_FALSE)
{
/* error on data line encountered */
return ERROR_SREC_INVALID_CHECKSUM;
}
/* all good so far, now read out the address and databytes for the line */
switch (lineType)
{
/* ---------------------------- S1 line type ------------------------------------- */
case LINE_TYPE_S1:
/* adjust pointer to point to byte count value */
line += 2;
/* read out the number of byte values that follow on the line */
bytes_on_line = FileLibHexStringToByte(line);
/* read out the 16-bit address */
line += 2;
*address = FileLibHexStringToByte(line) << 8;
line += 2;
*address += FileLibHexStringToByte(line);
/* adjust pointer to point to the first data byte after the address */
line += 2;
/* determine how many data bytes are on the line */
data_byte_count = bytes_on_line - 3; /* -2 bytes address, -1 byte checksum */
/* read and store data bytes if requested */
if (data != BLT_NULL)
{
for (i=0; i<data_byte_count; i++)
{
data[i] = FileLibHexStringToByte(line);
line += 2;
}
}
break;
/* ---------------------------- S2 line type ------------------------------------- */
case LINE_TYPE_S2:
/* adjust pointer to point to byte count value */
line += 2;
/* read out the number of byte values that follow on the line */
bytes_on_line = FileLibHexStringToByte(line);
/* read out the 32-bit address */
line += 2;
*address = FileLibHexStringToByte(line) << 16;
line += 2;
*address += FileLibHexStringToByte(line) << 8;
line += 2;
*address += FileLibHexStringToByte(line);
/* adjust pointer to point to the first data byte after the address */
line += 2;
/* determine how many data bytes are on the line */
data_byte_count = bytes_on_line - 4; /* -3 bytes address, -1 byte checksum */
/* read and store data bytes if requested */
if (data != BLT_NULL)
{
for (i=0; i<data_byte_count; i++)
{
data[i] = FileLibHexStringToByte(line);
line += 2;
}
}
break;
/* ---------------------------- S3 line type ------------------------------------- */
case LINE_TYPE_S3:
/* adjust pointer to point to byte count value */
line += 2;
/* read out the number of byte values that follow on the line */
bytes_on_line = FileLibHexStringToByte(line);
/* read out the 32-bit address */
line += 2;
*address = FileLibHexStringToByte(line) << 24;
line += 2;
*address += FileLibHexStringToByte(line) << 16;
line += 2;
*address += FileLibHexStringToByte(line) << 8;
line += 2;
*address += FileLibHexStringToByte(line);
/* adjust pointer to point to the first data byte after the address */
line += 2;
/* determine how many data bytes are on the line */
data_byte_count = bytes_on_line - 5; /* -4 bytes address, -1 byte checksum */
/* read and store data bytes if requested */
if (data != BLT_NULL)
{
for (i=0; i<data_byte_count; i++)
{
data[i] = FileLibHexStringToByte(line);
line += 2;
}
}
break;
default:
break;
}
return data_byte_count;
} /*** end of FileSrecParseLine ***/
#if (BOOT_FILE_LOGGING_ENABLE > 0)
/************************************************************************************//**
** \brief Helper function to convert a 4-bit value to a character that represents its
** value in hexadecimal format.
** Example: FileLibByteNibbleToChar(11) --> returns 'B'.
** \param nibble 4-bit value to convert.
** \return The resulting byte value.
**
****************************************************************************************/
static blt_char FileLibByteNibbleToChar(blt_int8u nibble)
{
blt_char c;
/* convert to ASCII value */
c = (nibble & 0x0f) + '0';
if (nibble > 9)
{
c += 7;
}
else
{
c = toupper((blt_int16s)c);
}
/* return the character */
return c;
} /*** end of FileLibByteNibbleToChar ***/
/************************************************************************************//**
** \brief Helper function to convert a byte value to a string representing the
** value in hexadecimal format.
** Example: FileLibByteToHexString(28, strBuffer) --> returns "1C".
** \param byte_val 8-bit value to convert.
** \param destination Pointer to character buffer for storing the results.
** \return The resulting string.
**
****************************************************************************************/
static blt_char *FileLibByteToHexString(blt_int8u byte_val, blt_char *destination)
{
/* first the most significant n-bit nibble */
destination[0] = FileLibByteNibbleToChar(byte_val >> 4);
/* next the least significant n-bit nibble */
destination[1] = FileLibByteNibbleToChar(byte_val & 0x0f);
/* add string termination */
destination[2] = '\0';
/* return pointer to resulting string */
return destination;
} /*** end of FileLibByteToHexString ***/
/************************************************************************************//**
** \brief Helper function to convert a 32-bit unsigned number to a string that
** represents its decimal value.
** Example: FileLibLongToIntString(1234, strBuffer) --> returns "1234".
** \param long_val 32-bit value to convert.
** \param destination Pointer to character buffer for storing the results.
** \return The resulting string.
**
****************************************************************************************/
static blt_char *FileLibLongToIntString(blt_int32u long_val, blt_char *destination)
{
blt_int32u long_val_cpy = long_val;
/* first determine how many digits there will be */
do
{
destination++;
long_val_cpy /= 10;
}
while (long_val_cpy > 0);
/* add space for the string termination and add it */
*destination = '\0';
/* now add the digits from right to left */
long_val_cpy = long_val;
do
{
/* set write pointer to where the next character should go */
destination--;
/* write digit in ASCII format */
*destination = long_val_cpy % 10 + '0';
/* move on to the next digit */
long_val_cpy /= 10;
}
while (long_val_cpy > 0);
return destination;
} /*** end of FileLibLongToIntString ***/
#endif /* (BOOT_FILE_LOGGING_ENABLE > 0) */
/************************************************************************************//**
** \brief Helper function to convert a sequence of 2 characters that represent
** a hexadecimal value to the actual byte value.
** Example: FileLibHexStringToByte("2f") --> returns 47.
** \param hexstring String beginning with 2 characters that represent a hexa-
** decimal value.
** \return The resulting byte value.
**
****************************************************************************************/
static blt_int8u FileLibHexStringToByte(const blt_char *hexstring)
{
blt_int8u result = 0;
blt_char c;
blt_int8u counter;
/* a hexadecimal character is 2 characters long (i.e 0x4F minus the 0x part) */
for (counter=0; counter < 2; counter++)
{
/* read out the character */
c = toupper((blt_int16s)(hexstring[counter]));
/* check that the character is 0..9 or A..F */
if ((c < '0') || (c > 'F') || ((c > '9') && (c < 'A')))
{
/* character not valid */
return 0;
}
/* convert character to 4-bit value (check ASCII table for more info) */
c -= '0';
if (c > 9)
{
c -= 7;
}
/* add it to the result */
result = (result << 4) + c;
}
/* return the results */
return result;
} /*** end of FileLibHexStringToByte ***/
#endif /* BOOT_FILE_SYS_ENABLE > 0 */
/*********************************** end of file.c *************************************/

103
openblt/file.h Normal file
View File

@@ -0,0 +1,103 @@
/************************************************************************************//**
* \file Source/file.h
* \brief Bootloader file system interface header file.
* \ingroup Core
* \internal
*----------------------------------------------------------------------------------------
* C O P Y R I G H T
*----------------------------------------------------------------------------------------
* Copyright (c) 2013 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
****************************************************************************************/
#ifndef FILE_H
#define FILE_H
#if (BOOT_FILE_SYS_ENABLE > 0)
/****************************************************************************************
* Include files
****************************************************************************************/
#include "ff.h" /* FATFS file system library */
/****************************************************************************************
* Defines
****************************************************************************************/
/** \brief Error code for not being able to open the firmware file. */
#define FILE_ERROR_CANNOT_OPEN_FIRMWARE_FILE (1)
/** \brief Error code for not being able to read from the firmware file. */
#define FILE_ERROR_CANNOT_READ_FROM_FILE (2)
/** \brief Error code because in incorrect checksum was found in the firmware file. */
#define FILE_ERROR_INVALID_CHECKSUM_IN_FILE (3)
/** \brief Error code because the file pointers read pointer could not be rewinded. */
#define FILE_ERROR_REWINDING_FILE_READ_POINTER (4)
/** \brief Error code because an error occurred during the memory erase operation. */
#define FILE_ERROR_CANNOT_ERASE_MEMORY (5)
/** \brief Error code because an error occurred during the memory write operation. */
#define FILE_ERROR_CANNOT_PROGRAM_MEMORY (6)
/** \brief Error code because the program's checksum could not be written to memory. */
#define FILE_ERROR_CANNOT_WRITE_CHECKSUM (7)
/** \brief Maximum number of characters that can be on a line in the firmware file. */
#define MAX_CHARS_PER_LINE (256)
/** \brief Maximum number of data bytes that can be on a line in the firmware file
* (S-record).
*/
#define MAX_DATA_BYTES_PER_LINE (MAX_CHARS_PER_LINE/2)
/** \brief Return code in case an invalid checksum was detected on an S-record line. */
#define ERROR_SREC_INVALID_CHECKSUM (-1)
/****************************************************************************************
* Type definitions
****************************************************************************************/
/** \brief Enumeration for the different S-record line types. */
typedef enum
{
LINE_TYPE_S1, /**< 16-bit address line */
LINE_TYPE_S2, /**< 24-bit address line */
LINE_TYPE_S3, /**< 32-bit address line */
LINE_TYPE_UNSUPPORTED /**< unsupported line */
} tSrecLineType;
/** \brief Structure type for grouping the parsing results of an S-record line. */
typedef struct
{
blt_char line[MAX_CHARS_PER_LINE]; /**< string buffer for the line chars */
blt_int8u data[MAX_DATA_BYTES_PER_LINE]; /**< array for S1, S2 or S3 data bytes*/
blt_addr address; /**< address on S1, S2 or S3 line */
} tSrecLineParseObject;
/****************************************************************************************
* Function prototypes
****************************************************************************************/
void FileInit(void);
void FileTask(void);
blt_bool FileIsIdle(void);
blt_bool FileHandleFirmwareUpdateRequest(void);
/* functions for reading data from a Motorola S-record file. */
tSrecLineType FileSrecGetLineType(const blt_char *line);
blt_bool FileSrecVerifyChecksum(const blt_char *line);
blt_int16s FileSrecParseLine(const blt_char *line, blt_addr *address, blt_int8u *data);
#endif /* BOOT_FILE_SYS_ENABLE > 0 */
#endif /* FILE_H */
/*********************************** end of file.h *************************************/

446
openblt/net.c Normal file
View File

@@ -0,0 +1,446 @@
/************************************************************************************//**
* \file Source/net.c
* \brief Bootloader TCP/IP network communication interface source file.
* \ingroup Core
* \internal
*----------------------------------------------------------------------------------------
* C O P Y R I G H T
*----------------------------------------------------------------------------------------
* Copyright (c) 2014 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 */
#if (BOOT_COM_NET_ENABLE > 0)
#include "netdev.h"
#include "uip.h"
#include "uip_arp.h"
#endif
#if (BOOT_COM_NET_ENABLE > 0)
/****************************************************************************************
* Configuration macros
****************************************************************************************/
/* Extend the default time that the backdoor is open if firmware updates via TCP/IP
* are supported. in this case an activation of the bootloader results in an
* initialization of the ethernet MAC. when connected to the network via a router this
* can take several seconds. Feel free to shorten/lengthen this time for finetuning,
* Note that adding this configuration macro to blt_conf.h overrides the value here.
*/
#ifndef BOOT_COM_NET_BACKDOOR_EXTENSION_MS
#define BOOT_COM_NET_BACKDOOR_EXTENSION_MS (10000)
#endif
/****************************************************************************************
* Macro definitions
****************************************************************************************/
/** \brief Delta time for the uIP periodic timer. */
#define NET_UIP_PERIODIC_TIMER_MS (500)
/** \brief Delta time for the uIP ARP timer. */
#define NET_UIP_ARP_TIMER_MS (10000)
/** \brief Macro for accessing the Ethernet header information in the buffer */
#define NET_UIP_HEADER_BUF ((struct uip_eth_hdr *)&uip_buf[0])
/****************************************************************************************
* Function prototypes
****************************************************************************************/
static void NetServerTask(void);
/****************************************************************************************
* Local data declarations
****************************************************************************************/
/** \brief Holds the time out value of the uIP periodic timer. */
static blt_int32u periodicTimerTimeOut;
/** \brief Holds the time out value of the uIP ARP timer. */
static blt_int32u ARPTimerTimeOut;
#if (BOOT_COM_NET_DHCP_ENABLE > 0)
/** \brief Holds the MAC address which is used by the DHCP client. */
static struct uip_eth_addr macAddress;
#endif
/** \brief Boolean flag to determine if the module was initialized or not. */
static blt_bool netInitializedFlag = BLT_FALSE;
#if (BOOT_COM_NET_DEFERRED_INIT_ENABLE == 1)
/** \brief Boolean flag initialized such that the normal initialization via NetInit()
* should be deferred. A called to NetDeferredInit() is need to do the actual
* initialization of this module.
*/
static blt_bool netInitializationDeferred = BLT_TRUE;
#else
/** \brief Boolean flag initialized such that the normal initialization via NetInit()
* proceeds as usual.
*/
static blt_bool netInitializationDeferred = BLT_FALSE;
#endif
/************************************************************************************//**
** \brief Initializes the TCP/IP network communication interface.
** \return none.
**
****************************************************************************************/
void NetInit(void)
{
uip_ipaddr_t ipaddr;
/* only perform the initialization if there is no request to defer it */
if (netInitializationDeferred == BLT_FALSE)
{
/* initialize the network device */
netdev_init();
/* initialize the timer variables */
periodicTimerTimeOut = TimerGet() + NET_UIP_PERIODIC_TIMER_MS;
ARPTimerTimeOut = TimerGet() + NET_UIP_ARP_TIMER_MS;
/* initialize the uIP TCP/IP stack. */
uip_init();
#if (BOOT_COM_NET_DHCP_ENABLE == 0)
/* set the IP address */
uip_ipaddr(ipaddr, BOOT_COM_NET_IPADDR0, BOOT_COM_NET_IPADDR1, BOOT_COM_NET_IPADDR2,
BOOT_COM_NET_IPADDR3);
uip_sethostaddr(ipaddr);
/* set the network mask */
uip_ipaddr(ipaddr, BOOT_COM_NET_NETMASK0, BOOT_COM_NET_NETMASK1, BOOT_COM_NET_NETMASK2,
BOOT_COM_NET_NETMASK3);
uip_setnetmask(ipaddr);
/* set the gateway address */
uip_ipaddr(ipaddr, BOOT_COM_NET_GATEWAY0, BOOT_COM_NET_GATEWAY1, BOOT_COM_NET_GATEWAY2,
BOOT_COM_NET_GATEWAY3);
uip_setdraddr(ipaddr);
#else
/* set the IP address */
uip_ipaddr(ipaddr, 0, 0, 0, 0);
uip_sethostaddr(ipaddr);
/* set the network mask */
uip_ipaddr(ipaddr, 0, 0, 0, 0);
uip_setnetmask(ipaddr);
/* set the gateway address */
uip_ipaddr(ipaddr, 0, 0, 0, 0);
uip_setdraddr(ipaddr);
#endif
/* start listening on the configured port for XCP transfers on TCP/IP */
uip_listen(HTONS(BOOT_COM_NET_PORT));
/* initialize the MAC and set the MAC address */
netdev_init_mac();
#if (BOOT_COM_NET_DHCP_ENABLE > 0)
/* initialize the DHCP client application and send the initial request. */
netdev_get_mac(&macAddress.addr[0]);
dhcpc_init(&macAddress.addr[0], 6);
dhcpc_request();
#endif
/* extend the time that the backdoor is open in case the default timed backdoor
* mechanism is used.
*/
#if (BOOT_BACKDOOR_HOOKS_ENABLE == 0)
if (BackDoorGetExtension() < BOOT_COM_NET_BACKDOOR_EXTENSION_MS)
{
BackDoorSetExtension(BOOT_COM_NET_BACKDOOR_EXTENSION_MS);
}
#endif /* BOOT_BACKDOOR_HOOKS_ENABLE == 0 */
/* set flag to indicate that we are now initialized. */
netInitializedFlag = BLT_TRUE;
}
} /*** end of NetInit ***/
#if (BOOT_COM_NET_DEFERRED_INIT_ENABLE == 1)
/************************************************************************************//**
** \brief Performs a deferred initialization of the TCP/IP network communication
** interface.
** \return none.
**
****************************************************************************************/
void NetDeferredInit(void)
{
/* reset the request to defer the initializaton */
netInitializationDeferred = BLT_FALSE;
/* perform the initialization if not yet initialized */
if (netInitializedFlag == BLT_FALSE)
{
NetInit();
}
} /*** end of NetDeferredInit ***/
#endif
/************************************************************************************//**
** \brief Transmits a packet formatted for the communication interface.
** \param data Pointer to byte array with data that it to be transmitted.
** \param len Number of bytes that are to be transmitted.
** \return none.
**
****************************************************************************************/
void NetTransmitPacket(blt_int8u *data, blt_int8u len)
{
uip_tcp_appstate_t *s;
blt_int16u cnt;
/* no need to send the packet if this module is not initialized */
if (netInitializedFlag == BLT_TRUE)
{
/* get pointer to application state */
s = &(uip_conn->appstate);
/* add the dto counter first */
*(blt_int32u *)&(s->dto_data[0]) = s->dto_counter;
/* copy the actual XCP response */
for (cnt=0; cnt<len; cnt++)
{
s->dto_data[cnt+4] = data[cnt];
}
/* set the length of the TCP/IP packet */
s->dto_len = len + 4;
/* set the flag to request the transmission of this packet. */
s->dto_tx_req = BLT_TRUE;
/* update dto counter for the next transmission */
s->dto_counter++;
}
} /*** end of NetTransmitPacket ***/
/************************************************************************************//**
** \brief Receives a communication interface packet if one is present.
** \param data Pointer to byte array where the data is to be stored.
** \param len Pointer where the length of the packet is to be stored.
** \return BLT_TRUE if a packet was received, BLT_FALSE otherwise.
**
****************************************************************************************/
blt_bool NetReceivePacket(blt_int8u *data, blt_int8u *len)
{
/* no need to check for newly received packets if this module is not initialized */
if (netInitializedFlag == BLT_TRUE)
{
/* run the TCP/IP server task function, which will handle the reception and
* transmission of XCP packets
*/
NetServerTask();
}
/* packet reception and transmission is completely handled by the NetServerTask so
* always return BLT_FALSE here.
*/
return BLT_FALSE;
} /*** end of NetReceivePacket ***/
/************************************************************************************//**
** \brief The uIP network application that implements XCP on TCP/IP. Note that this
** application make use of the fact that XCP is request/response based. So
** no new request will come in when a response is pending for transmission,
** if so, the transmission of the pending response is aborted.
** \return none.
**
****************************************************************************************/
void NetApp(void)
{
uip_tcp_appstate_t *s;
blt_int8u *newDataPtr;
/* get pointer to application state */
s = &(uip_conn->appstate);
if (uip_connected())
{
/* init the dto counter and reset the pending dto data length and transmit related
* flags.
*/
s->dto_counter = 1;
s->dto_len = 0;
s->dto_tx_req = BLT_FALSE;
s->dto_tx_pending = BLT_FALSE;
return;
}
if (uip_acked())
{
/* dto sent so reset the pending flag. */
s->dto_tx_pending = BLT_FALSE;
}
if (uip_rexmit())
{
/* is a dto transmission pending that should now be retransmitted? */
/* retransmit the currently pending dto response */
if (s->dto_tx_pending == BLT_TRUE)
{
/* resend the last pending dto response */
uip_send(s->dto_data, s->dto_len);
}
}
if (uip_poll())
{
/* check if there is a packet waiting to be transmitted. this is done via polling
* because then it is possible to asynchronously send data. otherwise data is
* only really send after a newly received packet was received.
*/
if (s->dto_tx_req == BLT_TRUE)
{
/* reset the transmit request flag. */
s->dto_tx_req = BLT_FALSE;
if (s->dto_len > 0)
{
/* set the transmit pending flag. */
s->dto_tx_pending = BLT_TRUE;
/* submit the data for transmission. */
uip_send(s->dto_data, s->dto_len);
}
}
}
if (uip_newdata())
{
/* only process the data if its length is not longer than expected. otherwise just
* ignore it. XCP is request/response. this means that a new requests should
* only be processed when the response the the previous request was sent. new
* requests before the last response was sent can therefore also be ignored.
*/
if ( ((uip_datalen() - 4) <= BOOT_COM_NET_RX_MAX_DATA) &&
(s->dto_tx_pending == BLT_FALSE) )
{
/* the first 4 bytes contain a counter value in which we are not really interested */
newDataPtr = uip_appdata;
XcpPacketReceived(&newDataPtr[4], (blt_int8u)(uip_datalen() - 4));
}
}
} /*** end of NetApp ***/
/************************************************************************************//**
** \brief Runs the TCP/IP server task.
** \return none.
**
****************************************************************************************/
static void NetServerTask(void)
{
blt_int32u connection;
blt_int32u packetLen;
/* check for an RX packet and read it. */
packetLen = netdev_read();
if (packetLen > 0)
{
/* set uip_len for uIP stack usage */
uip_len = (blt_int16u)packetLen;
/* process incoming IP packets here. */
if (NET_UIP_HEADER_BUF->type == htons(UIP_ETHTYPE_IP))
{
uip_arp_ipin();
uip_input();
/* if the above function invocation resulted in data that
* should be sent out on the network, the global variable
* uip_len is set to a value > 0.
*/
if (uip_len > 0)
{
uip_arp_out();
netdev_send();
uip_len = 0;
}
}
/* process incoming ARP packets here. */
else if (NET_UIP_HEADER_BUF->type == htons(UIP_ETHTYPE_ARP))
{
uip_arp_arpin();
/* if the above function invocation resulted in data that
* should be sent out on the network, the global variable
* uip_len is set to a value > 0.
*/
if (uip_len > 0)
{
netdev_send();
uip_len = 0;
}
}
}
/* process TCP/IP Periodic Timer here. */
if (TimerGet() >= periodicTimerTimeOut)
{
periodicTimerTimeOut += NET_UIP_PERIODIC_TIMER_MS;
for (connection = 0; connection < UIP_CONNS; connection++)
{
uip_periodic(connection);
/* If the above function invocation resulted in data that
* should be sent out on the network, the global variable
* uip_len is set to a value > 0.
*/
if (uip_len > 0)
{
uip_arp_out();
netdev_send();
uip_len = 0;
}
}
#if UIP_UDP
for (connection = 0; connection < UIP_UDP_CONNS; connection++)
{
uip_udp_periodic(connection);
/* If the above function invocation resulted in data that
* should be sent out on the network, the global variable
* uip_len is set to a value > 0.
*/
if(uip_len > 0)
{
uip_arp_out();
netdev_send();
uip_len = 0;
}
}
#endif
}
/* process ARP Timer here. */
if (TimerGet() >= ARPTimerTimeOut)
{
ARPTimerTimeOut += NET_UIP_ARP_TIMER_MS;
uip_arp_timer();
}
/* perform polling operations here. */
for (connection = 0; connection < UIP_CONNS; connection++)
{
uip_poll_conn(&uip_conns[connection]);
/* If the above function invocation resulted in data that
* should be sent out on the network, the global variable
* uip_len is set to a value > 0.
*/
if (uip_len > 0)
{
uip_arp_out();
netdev_send();
uip_len = 0;
}
}
} /*** end of NetServerTask ***/
#endif /* BOOT_COM_NET_ENABLE > 0 */
/*********************************** end of net.c **************************************/

80
openblt/net.h Normal file
View File

@@ -0,0 +1,80 @@
/************************************************************************************//**
* \file Source/net.h
* \brief Bootloader TCP/IP network communication interface header file.
* \ingroup Core
* \internal
*----------------------------------------------------------------------------------------
* C O P Y R I G H T
*----------------------------------------------------------------------------------------
* Copyright (c) 2014 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
****************************************************************************************/
#ifndef NET_H
#define NET_H
#if (BOOT_COM_NET_ENABLE > 0)
/****************************************************************************************
* Macro definitions
****************************************************************************************/
#ifndef UIP_APPCALL
#define UIP_APPCALL NetApp
#endif /* UIP_APPCALL */
/****************************************************************************************
* Type definitions
****************************************************************************************/
/** \brief Define the uip_tcp_appstate_t datatype. This is the state of our tcp/ip
* application, and the memory required for this state is allocated together
* with each TCP connection. One application state for each TCP connection.
*/
typedef struct net_state
{
blt_int32u dto_counter;
blt_int8u dto_data[BOOT_COM_NET_TX_MAX_DATA + 4]; /* +4 for counter overhead */
blt_int16u dto_len;
blt_bool dto_tx_req;
blt_bool dto_tx_pending;
} uip_tcp_appstate_t;
/****************************************************************************************
* Function prototypes
****************************************************************************************/
void NetInit(void);
#if (BOOT_COM_NET_DEFERRED_INIT_ENABLE == 1)
void NetDeferredInit(void);
#endif
void NetApp(void);
void NetTransmitPacket(blt_int8u *data, blt_int8u len);
blt_bool NetReceivePacket(blt_int8u *data, blt_int8u *len);
#else /* BOOT_COM_NET_ENABLE > 0 */
typedef struct net_state
{
blt_int8u unused;
} uip_tcp_appstate_t;
#define UIP_APPCALL();
#endif /* BOOT_COM_NET_ENABLE > 0 */
#endif /* NET_H */
/*********************************** end of net.h **************************************/

56
openblt/nvm.h Normal file
View File

@@ -0,0 +1,56 @@
/************************************************************************************//**
* \file Source/nvm.h
* \brief Bootloader non-volatile memory driver header file.
* \ingroup Core
* \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
****************************************************************************************/
#ifndef NVM_H
#define NVM_H
/****************************************************************************************
* Function prototypes
****************************************************************************************/
void NvmInit(void);
void NvmReinit(void);
blt_bool NvmWrite(blt_addr addr, blt_int32u len, blt_int8u *data);
blt_bool NvmErase(blt_addr addr, blt_int32u len);
blt_bool NvmVerifyChecksum(void);
blt_addr NvmGetUserProgBaseAddress(void);
blt_bool NvmDone(void);
/****************************************************************************************
* Macro definitions
****************************************************************************************/
/* return codes for hook function NvmWrite/Erase */
/** \brief Return code for success. */
#define BLT_NVM_ERROR (0x00)
/** \brief Return code for error. */
#define BLT_NVM_OKAY (0x01)
/** \brief Return code for not in range. */
#define BLT_NVM_NOT_IN_RANGE (0x02)
#endif /* NVM_H */
/*********************************** end of nvm.h **************************************/

519
openblt/plausibility.h Normal file
View File

@@ -0,0 +1,519 @@
/************************************************************************************//**
* \file Source/plausibility.h
* \brief Bootloader plausibility check header file, for checking the configuration
* at compile time.
* \ingroup Core
* \internal
*----------------------------------------------------------------------------------------
* C O P Y R I G H T
*----------------------------------------------------------------------------------------
* Copyright (c) 2011 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
****************************************************************************************/
#ifndef PLAUSIBILITY_H
#define PLAUSIBILITY_H
/****************************************************************************************
* C P U D R I V E R C O N F I G U R A T I O N C H E C K
****************************************************************************************/
#ifndef BOOT_CPU_XTAL_SPEED_KHZ
#error "BOOT_CPU_XTAL_SPEED_KHZ is missing in blt_conf.h"
#endif
#if (BOOT_CPU_XTAL_SPEED_KHZ <= 0)
#error "BOOT_CPU_XTAL_SPEED_KHZ must be > 0"
#endif
#ifndef BOOT_CPU_SYSTEM_SPEED_KHZ
#error "BOOT_CPU_SYSTEM_SPEED_KHZ is missing in blt_conf.h"
#endif
#if (BOOT_CPU_SYSTEM_SPEED_KHZ <= 0)
#error "BOOT_CPU_SYSTEM_SPEED_KHZ must be > 0"
#endif
#ifndef BOOT_CPU_BYTE_ORDER_MOTOROLA
#error "BOOT_CPU_BYTE_ORDER_MOTOROLA is missing in blt_conf.h"
#endif
#if (BOOT_CPU_BYTE_ORDER_MOTOROLA < 0) || (BOOT_CPU_BYTE_ORDER_MOTOROLA > 1)
#error "BOOT_CPU_BYTE_ORDER_MOTOROLA must be 0 or 1"
#endif
#ifndef BOOT_CPU_USER_PROGRAM_START_HOOK
#define BOOT_CPU_USER_PROGRAM_START_HOOK (0)
#endif
#if (BOOT_CPU_USER_PROGRAM_START_HOOK < 0) || (BOOT_CPU_USER_PROGRAM_START_HOOK > 1)
#error "BOOT_CPU_USER_PROGRAM_START_HOOK must be 0 or 1"
#endif
/****************************************************************************************
* C O M M U N I C A T I O N I N T E R F A C E C O N F I G U R A T I O N C H E C K
****************************************************************************************/
#ifndef BOOT_COM_CAN_TX_MAX_DATA
#define BOOT_COM_CAN_TX_MAX_DATA (0)
#endif
#ifndef BOOT_COM_CAN_RX_MAX_DATA
#define BOOT_COM_CAN_RX_MAX_DATA (0)
#endif
#ifndef BOOT_COM_RS232_TX_MAX_DATA
#define BOOT_COM_RS232_TX_MAX_DATA (0)
#endif
#ifndef BOOT_COM_RS232_RX_MAX_DATA
#define BOOT_COM_RS232_RX_MAX_DATA (0)
#endif
#ifndef BOOT_COM_USB_TX_MAX_DATA
#define BOOT_COM_USB_TX_MAX_DATA (0)
#endif
#ifndef BOOT_COM_USB_RX_MAX_DATA
#define BOOT_COM_USB_RX_MAX_DATA (0)
#endif
#ifndef BOOT_COM_NET_TX_MAX_DATA
#define BOOT_COM_NET_TX_MAX_DATA (0)
#endif
#ifndef BOOT_COM_NET_RX_MAX_DATA
#define BOOT_COM_NET_RX_MAX_DATA (0)
#endif
#ifndef BOOT_COM_CAN_ENABLE
#define BOOT_COM_CAN_ENABLE (0)
#endif
#if (BOOT_COM_CAN_ENABLE > 0)
/* Note that the value check was disabled for the following configuration macros, which
* makes it possible to link them to a function, allowing a more dynamic configuration:
* - BOOT_COM_CAN_BAUDRATE
* - BOOT_COM_CAN_TX_MSG_ID
* - BOOT_COM_CAN_RX_MSG_ID
*/
#ifndef BOOT_COM_CAN_BAUDRATE
#error "BOOT_COM_CAN_BAUDRATE is missing in blt_conf.h"
#endif
#ifndef BOOT_COM_CAN_TX_MSG_ID
#error "BOOT_COM_CAN_TX_MSG_ID is missing in blt_conf.h"
#endif
#ifndef BOOT_COM_CAN_TX_MAX_DATA
#error "BOOT_COM_CAN_TX_MAX_DATA is missing in blt_conf.h"
#endif
#if (BOOT_COM_CAN_TX_MAX_DATA <= 0)
#error "BOOT_COM_CAN_TX_MAX_DATA must be > 0"
#endif
#if (BOOT_COM_CAN_TX_MAX_DATA > 8)
#error "BOOT_COM_CAN_TX_MAX_DATA must be <= 8"
#endif
#ifndef BOOT_COM_CAN_RX_MSG_ID
#error "BOOT_COM_CAN_RX_MSG_ID is missing in blt_conf.h"
#endif
#ifndef BOOT_COM_CAN_RX_MAX_DATA
#error "BOOT_COM_CAN_RX_MAX_DATA is missing in blt_conf.h"
#endif
#if (BOOT_COM_CAN_RX_MAX_DATA <= 0)
#error "BOOT_COM_CAN_RX_MAX_DATA must be > 0"
#endif
#if (BOOT_COM_CAN_RX_MAX_DATA > 8)
#error "BOOT_COM_CAN_RX_MAX_DATA must be <= 8"
#endif
#ifndef BOOT_COM_CAN_CHANNEL_INDEX
#error "BOOT_COM_CAN_CHANNEL_INDEX is missing in blt_conf.h"
#endif
#if (BOOT_COM_CAN_CHANNEL_INDEX < 0)
#error "BOOT_COM_CAN_CHANNEL_INDEX must be >= 0"
#endif
#endif /* BOOT_COM_CAN_ENABLE > 0 */
#ifndef BOOT_COM_RS232_ENABLE
#define BOOT_COM_RS232_ENABLE (0)
#endif
#if (BOOT_COM_RS232_ENABLE > 0)
/* Note that the value check was disabled for the following configuration macros, which
* makes it possible to link them to a function, allowing a more dynamic configuration:
* - BOOT_COM_RS232_BAUDRATE
*/
#ifndef BOOT_COM_RS232_BAUDRATE
#error "BOOT_COM_RS232_BAUDRATE is missing in blt_conf.h"
#endif
#ifndef BOOT_COM_RS232_TX_MAX_DATA
#error "BOOT_COM_RS232_TX_MAX_DATA is missing in blt_conf.h"
#endif
#if (BOOT_COM_RS232_TX_MAX_DATA <= 0)
#error "BOOT_COM_RS232_TX_MAX_DATA must be > 0"
#endif
#if (BOOT_COM_RS232_TX_MAX_DATA > 255)
#error "BOOT_COM_RS232_TX_MAX_DATA must be <= 255"
#endif
#ifndef BOOT_COM_RS232_RX_MAX_DATA
#error "BOOT_COM_RS232_RX_MAX_DATA is missing in blt_conf.h"
#endif
#if (BOOT_COM_RS232_RX_MAX_DATA <= 0)
#error "BOOT_COM_RS232_RX_MAX_DATA must be > 0"
#endif
#if (BOOT_COM_RS232_RX_MAX_DATA > 255)
#error "BOOT_COM_RS232_RX_MAX_DATA must be <= 255"
#endif
#ifndef BOOT_COM_RS232_CHANNEL_INDEX
#error "BOOT_COM_RS232_CHANNEL_INDEX is missing in blt_conf.h"
#endif
#if (BOOT_COM_RS232_CHANNEL_INDEX < 0)
#error "BOOT_COM_RS232_CHANNEL_INDEX must be >= 0"
#endif
#endif /* BOOT_COM_RS232_ENABLE > 0 */
#ifndef BOOT_COM_USB_ENABLE
#define BOOT_COM_USB_ENABLE (0)
#endif
#if (BOOT_COM_USB_ENABLE > 0)
#ifndef BOOT_COM_USB_TX_MAX_DATA
#error "BOOT_COM_USB_TX_MAX_DATA is missing in blt_conf.h"
#endif
#if (BOOT_COM_USB_TX_MAX_DATA <= 0)
#error "BOOT_COM_USB_TX_MAX_DATA must be > 0"
#endif
#ifndef BOOT_COM_USB_RX_MAX_DATA
#error "BOOT_COM_USB_RX_MAX_DATA is missing in blt_conf.h"
#endif
#if (BOOT_COM_USB_RX_MAX_DATA <= 0)
#error "BOOT_COM_USB_RX_MAX_DATA must be > 0"
#endif
#ifdef BOOT_COM_USB_BACKDOOR_EXTENSION_MS
#if (BOOT_COM_USB_BACKDOOR_EXTENSION_MS < 0)
#error "BOOT_COM_USB_BACKDOOR_EXTENSION_MS must be >= 0"
#endif
#endif
#endif /* BOOT_COM_USB_ENABLE > 0 */
#ifndef BOOT_COM_NET_ENABLE
#define BOOT_COM_NET_ENABLE (0)
#endif
#if (BOOT_COM_NET_ENABLE > 0)
/* Note that the value check was disabled for the following configuration macros, which
* makes it possible to link them to a function, allowing a more dynamic configuration:
* - BOOT_COM_NET_IPADDR0
* - BOOT_COM_NET_IPADDR1
* - BOOT_COM_NET_IPADDR2
* - BOOT_COM_NET_IPADDR3
* - BOOT_COM_NET_NETMASK0
* - BOOT_COM_NET_NETMASK1
* - BOOT_COM_NET_NETMASK2
* - BOOT_COM_NET_NETMASK3
* - BOOT_COM_NET_GATEWAY0
* - BOOT_COM_NET_GATEWAY1
* - BOOT_COM_NET_GATEWAY2
* - BOOT_COM_NET_GATEWAY3
* - BOOT_COM_NET_PORT
*/
#ifndef BOOT_COM_NET_TX_MAX_DATA
#error "BOOT_COM_NET_TX_MAX_DATA is missing in blt_conf.h"
#endif
#if (BOOT_COM_NET_TX_MAX_DATA <= 0)
#error "BOOT_COM_NET_TX_MAX_DATA must be > 0"
#endif
#ifndef BOOT_COM_NET_RX_MAX_DATA
#error "BOOT_COM_NET_RX_MAX_DATA is missing in blt_conf.h"
#endif
#if (BOOT_COM_NET_RX_MAX_DATA <= 0)
#error "BOOT_COM_NET_RX_MAX_DATA must be > 0"
#endif
#ifndef BOOT_COM_NET_DHCP_ENABLE
#define BOOT_COM_NET_DHCP_ENABLE (0)
#endif
#if (BOOT_COM_NET_DHCP_ENABLE < 0) || (BOOT_COM_NET_DHCP_ENABLE > 1)
#error "BOOT_COM_NET_DHCP_ENABLE must be 0 or 1"
#endif
#if (BOOT_COM_NET_DHCP_ENABLE == 0)
#ifndef BOOT_COM_NET_IPADDR0
#error "BOOT_COM_NET_IPADDR0 is missing in blt_conf.h"
#endif
#ifndef BOOT_COM_NET_IPADDR1
#error "BOOT_COM_NET_IPADDR1 is missing in blt_conf.h"
#endif
#ifndef BOOT_COM_NET_IPADDR2
#error "BOOT_COM_NET_IPADDR2 is missing in blt_conf.h"
#endif
#ifndef BOOT_COM_NET_IPADDR3
#error "BOOT_COM_NET_IPADDR3 is missing in blt_conf.h"
#endif
#ifndef BOOT_COM_NET_NETMASK0
#error "BOOT_COM_NET_NETMASK0 is missing in blt_conf.h"
#endif
#ifndef BOOT_COM_NET_NETMASK1
#error "BOOT_COM_NET_NETMASK1 is missing in blt_conf.h"
#endif
#ifndef BOOT_COM_NET_NETMASK2
#error "BOOT_COM_NET_NETMASK2 is missing in blt_conf.h"
#endif
#ifndef BOOT_COM_NET_NETMASK3
#error "BOOT_COM_NET_NETMASK3 is missing in blt_conf.h"
#endif
#ifndef BOOT_COM_NET_GATEWAY0
#error "BOOT_COM_NET_GATEWAY0 is missing in blt_conf.h"
#endif
#ifndef BOOT_COM_NET_GATEWAY1
#error "BOOT_COM_NET_GATEWAY1 is missing in blt_conf.h"
#endif
#ifndef BOOT_COM_NET_GATEWAY2
#error "BOOT_COM_NET_GATEWAY2 is missing in blt_conf.h"
#endif
#ifndef BOOT_COM_NET_GATEWAY3
#error "BOOT_COM_NET_GATEWAY3 is missing in blt_conf.h"
#endif
#ifndef BOOT_COM_NET_PORT
#error "BOOT_COM_NET_PORT is missing in blt_conf.h"
#endif
#endif /* BOOT_COM_NET_DHCP_ENABLE == 0 */
#ifdef BOOT_COM_NET_BACKDOOR_EXTENSION_MS
#if (BOOT_COM_NET_BACKDOOR_EXTENSION_MS < 0)
#error "BOOT_COM_NET_BACKDOOR_EXTENSION_MS must be >= 0"
#endif
#endif
#ifndef BOOT_COM_NET_DEFERRED_INIT_ENABLE
#define BOOT_COM_NET_DEFERRED_INIT_ENABLE (0)
#endif
#if (BOOT_COM_NET_DEFERRED_INIT_ENABLE < 0) || (BOOT_COM_NET_DEFERRED_INIT_ENABLE > 1)
#error "BOOT_COM_NET_DEFERRED_INIT_ENABLE must be 0 or 1"
#endif
#endif /* BOOT_COM_NET_ENABLE > 0 */
#if (BOOT_COM_NET_DEFERRED_INIT_ENABLE == 1)
#define BOOT_COM_DEFERRED_INIT_ENABLE (1)
#else
#define BOOT_COM_DEFERRED_INIT_ENABLE (0)
#endif
#if (BOOT_COM_CAN_ENABLE == 1) || (BOOT_COM_RS232_ENABLE == 1) || (BOOT_COM_NET_ENABLE == 1) || (BOOT_COM_USB_ENABLE == 1)
#define BOOT_COM_ENABLE (1)
#else
#define BOOT_COM_ENABLE (0)
#endif
/****************************************************************************************
* F I L E S Y S T E M I N T E R F A C E C O N F I G U R A T I O N C H E C K
****************************************************************************************/
#ifndef BOOT_FILE_SYS_ENABLE
#define BOOT_FILE_SYS_ENABLE (0)
#endif
#if (BOOT_FILE_SYS_ENABLE < 0) || (BOOT_FILE_SYS_ENABLE > 1)
#error "BOOT_FILE_SYS_ENABLE must be 0 or 1"
#endif
#if (BOOT_FILE_SYS_ENABLE > 0)
#ifndef BOOT_FILE_LOGGING_ENABLE
#define BOOT_FILE_LOGGING_ENABLE (0)
#endif
#if (BOOT_FILE_LOGGING_ENABLE < 0) || (BOOT_FILE_LOGGING_ENABLE > 1)
#error "BOOT_FILE_LOGGING_ENABLE must be 0 or 1"
#endif
#ifndef BOOT_FILE_ERROR_HOOK_ENABLE
#define BOOT_FILE_ERROR_HOOK_ENABLE (0)
#endif
#if (BOOT_FILE_ERROR_HOOK_ENABLE < 0) || (BOOT_FILE_ERROR_HOOK_ENABLE > 1)
#error "BOOT_FILE_ERROR_HOOK_ENABLE must be 0 or 1"
#endif
#ifndef BOOT_FILE_STARTED_HOOK_ENABLE
#define BOOT_FILE_STARTED_HOOK_ENABLE (0)
#endif
#if (BOOT_FILE_STARTED_HOOK_ENABLE < 0) || (BOOT_FILE_STARTED_HOOK_ENABLE > 1)
#error "BOOT_FILE_STARTED_HOOK_ENABLE must be 0 or 1"
#endif
#ifndef BOOT_FILE_COMPLETED_HOOK_ENABLE
#define BOOT_FILE_COMPLETED_HOOK_ENABLE (0)
#endif
#if (BOOT_FILE_COMPLETED_HOOK_ENABLE < 0) || (BOOT_FILE_COMPLETED_HOOK_ENABLE > 1)
#error "BOOT_FILE_COMPLETED_HOOK_ENABLE must be 0 or 1"
#endif
#endif /* BOOT_FILE_SYS_ENABLE > 0 */
/****************************************************************************************
* B A C K D O O R E N T R Y C H E C K
****************************************************************************************/
#ifndef BOOT_BACKDOOR_HOOKS_ENABLE
#define BOOT_BACKDOOR_HOOKS_ENABLE (0)
#endif
#if (BOOT_BACKDOOR_HOOKS_ENABLE < 0) || (BOOT_BACKDOOR_HOOKS_ENABLE > 1)
#error "BOOT_BACKDOOR_HOOKS_ENABLE must be 0 or 1"
#endif
/****************************************************************************************
* F L A S H D R I V E R C O N F I G U R A T I O N C H E C K
****************************************************************************************/
#ifndef BOOT_FLASH_CRYPTO_HOOKS_ENABLE
#define BOOT_FLASH_CRYPTO_HOOKS_ENABLE (0)
#endif
#if (BOOT_FLASH_CRYPTO_HOOKS_ENABLE < 0) || (BOOT_FLASH_CRYPTO_HOOKS_ENABLE > 1)
#error "BOOT_FLASH_CRYPTO_HOOKS_ENABLE must be 0 or 1"
#endif
/****************************************************************************************
* N V M D R I V E R C O N F I G U R A T I O N C H E C K
****************************************************************************************/
#ifndef BOOT_NVM_HOOKS_ENABLE
#define BOOT_NVM_HOOKS_ENABLE (0)
#endif
#if (BOOT_NVM_HOOKS_ENABLE < 0) || (BOOT_NVM_HOOKS_ENABLE > 1)
#error "BOOT_NVM_HOOKS_ENABLE must be 0 or 1"
#endif
#ifndef BOOT_NVM_SIZE_KB
#error "BOOT_NVM_SIZE_KB is missing in blt_conf.h"
#endif
#if (BOOT_NVM_SIZE_KB <= 0)
#error "BOOT_NVM_SIZE_KB must be > 0"
#endif
#ifndef BOOT_NVM_CHECKSUM_HOOKS_ENABLE
#define BOOT_NVM_CHECKSUM_HOOKS_ENABLE (0)
#endif
#if (BOOT_NVM_CHECKSUM_HOOKS_ENABLE < 0) || (BOOT_NVM_CHECKSUM_HOOKS_ENABLE > 1)
#error "BOOT_NVM_CHECKSUM_HOOKS_ENABLE must be 0 or 1"
#endif
/****************************************************************************************
* W A T C H D O G D R I V E R C O N F I G U R A T I O N C H E C K
****************************************************************************************/
#ifndef BOOT_COP_HOOKS_ENABLE
#define BOOT_COP_HOOKS_ENABLE (0)
#endif
#if (BOOT_COP_HOOKS_ENABLE < 0) || (BOOT_COP_HOOKS_ENABLE > 1)
#error "BOOT_COP_HOOKS_ENABLE must be 0 or 1"
#endif
/****************************************************************************************
* X C P M O D U L E C O N F I G U R A T I O N C H E C K
****************************************************************************************/
#ifndef BOOT_XCP_SEED_KEY_ENABLE
#define BOOT_XCP_SEED_KEY_ENABLE (0)
#endif
#if (BOOT_XCP_SEED_KEY_ENABLE < 0) || (BOOT_XCP_SEED_KEY_ENABLE > 1)
#error "BOOT_XCP_SEED_KEY_ENABLE must be 0 or 1"
#endif
#ifndef BOOT_XCP_UPLOAD_ENABLE
#define BOOT_XCP_UPLOAD_ENABLE (1)
#endif
#if (BOOT_XCP_UPLOAD_ENABLE < 0) || (BOOT_XCP_UPLOAD_ENABLE > 1)
#error "BOOT_XCP_UPLOAD_ENABLE must be 0 or 1"
#endif
#ifndef BOOT_XCP_PACKET_RECEIVED_HOOK
#define BOOT_XCP_PACKET_RECEIVED_HOOK (0)
#endif
#if (BOOT_XCP_PACKET_RECEIVED_HOOK < 0) || (BOOT_XCP_PACKET_RECEIVED_HOOK > 1)
#error "BOOT_XCP_PACKET_RECEIVED_HOOK must be 0 or 1"
#endif
#ifndef BOOT_XCP_SEED_MAX_LEN
#define BOOT_XCP_SEED_MAX_LEN (64)
#endif
#if (BOOT_XCP_SEED_MAX_LEN <= 0)
#error "BOOT_XCP_SEED_MAX_LEN must be > 0"
#endif
#ifndef BOOT_XCP_KEY_MAX_LEN
#define BOOT_XCP_KEY_MAX_LEN (64)
#endif
#if (BOOT_XCP_KEY_MAX_LEN <= 0)
#error "BOOT_XCP_KEY_MAX_LEN must be > 0"
#endif
#endif /* PLAUSIBILITY_H */
/*********************************** end of plausibility.h *****************************/

42
openblt/rs232.h Normal file
View File

@@ -0,0 +1,42 @@
/************************************************************************************//**
* \file Source/rs232.h
* \brief Bootloader RS232 communication interface header file.
* \ingroup Core
* \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
****************************************************************************************/
#ifndef RS232_H
#define RS232_H
#if (BOOT_COM_RS232_ENABLE > 0)
/****************************************************************************************
* Function prototypes
****************************************************************************************/
void Rs232Init(void);
void Rs232TransmitPacket(blt_int8u *data, blt_int8u len);
blt_bool Rs232ReceivePacket(blt_int8u *data, blt_int8u *len);
#endif /* BOOT_COM_RS232_ENABLE > 0 */
#endif /* RS232_H */
/*********************************** end of rs232.h ************************************/

41
openblt/timer.h Normal file
View File

@@ -0,0 +1,41 @@
/************************************************************************************//**
* \file Source/timer.h
* \brief Bootloader timer driver header file.
* \ingroup Core
* \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
****************************************************************************************/
#ifndef TIMER_H
#define TIMER_H
/****************************************************************************************
* Function prototypes
****************************************************************************************/
void TimerInit(void);
void TimerUpdate(void);
blt_int32u TimerGet(void);
void TimerReset(void);
#endif /* TIMER_H */
/*********************************** end of timer.h ************************************/

52
openblt/usb.h Normal file
View File

@@ -0,0 +1,52 @@
/************************************************************************************//**
* \file Source/usb.h
* \brief Bootloader USB communication interface header file.
* \ingroup Core
* \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
****************************************************************************************/
#ifndef USB_H
#define USB_H
#if (BOOT_COM_USB_ENABLE > 0)
/****************************************************************************************
* Function prototypes
****************************************************************************************/
void UsbInit(void);
void UsbFree(void);
void UsbTransmitPacket(blt_int8u *data, blt_int8u len);
blt_bool UsbReceivePacket(blt_int8u *data, blt_int8u *len);
/****************************************************************************************
* Hook functions
****************************************************************************************/
extern void UsbEnterLowPowerModeHook(void);
extern void UsbLeaveLowPowerModeHook(void);
extern void UsbConnectHook(blt_bool connect);
#endif /* BOOT_COM_USB_ENABLE > 0 */
#endif /* USB_H */
/*********************************** end of usb.h **************************************/

1500
openblt/xcp.c Normal file

File diff suppressed because it is too large Load Diff

357
openblt/xcp.h Normal file
View File

@@ -0,0 +1,357 @@
/************************************************************************************//**
* \file Source/xcp.h
* \brief XCP 1.0 protocol core header file.
* \ingroup Core
* \internal
*----------------------------------------------------------------------------------------
* C O P Y R I G H T
*----------------------------------------------------------------------------------------
* Copyright (c) 2011 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
****************************************************************************************/
#ifndef XCP_H
#define XCP_H
#if (BOOT_COM_ENABLE > 0)
/****************************************************************************************
* Configuration
****************************************************************************************/
/** \brief Maximum length of the transport layer's command transmit object packet. */
#if defined(BOOT_XCP_CUSTOM_RX_MAX_DATA)
#define XCP_CTO_PACKET_LEN (BOOT_XCP_CUSTOM_RX_MAX_DATA)
#else
#define XCP_CTO_PACKET_LEN (ComGetActiveInterfaceMaxRxLen())
#endif
/** \brief Maximum length of the transport layer's data transmit object packet. */
#if defined(BOOT_XCP_CUSTOM_TX_MAX_DATA)
#define XCP_DTO_PACKET_LEN (BOOT_XCP_CUSTOM_TX_MAX_DATA)
#else
#define XCP_DTO_PACKET_LEN (ComGetActiveInterfaceMaxTxLen())
#endif
/** \brief Name in string format that is used to identify the ECU to the XCP master
* using the GET_ID command.
*/
#define XCP_STATION_ID_STRING "OpenBLT"
#if (BOOT_CPU_BYTE_ORDER_MOTOROLA > 0)
/** \brief XCP byte ordering according to the Motorola (big-endian). */
#define XCP_MOTOROLA_FORMAT (0x01)
#else
/** \brief XCP byte ordering according to the Intel (little-endian). */
#define XCP_MOTOROLA_FORMAT (0x00)
#endif
/** \brief Enable (=1) or disable (=0) support for the calibration resource. This is
* required when data is written to RAM during the XCP session.
*/
#define XCP_RES_CALIBRATION_EN (0)
/** \brief Enable (=1) or disable (=0) support for the paging resource. This is
* required when switching between application specific calibration pages
* should be supported. In this case the application specific external
* functions AppCalSetPage and AppCalGetPage must be provided.
*/
#define XCP_RES_PAGING_EN (0)
/** \brief Enable (=1) or disable (=0) support for the programming resource. This is
* required when non-volatile memory will be erased or programmed during an
* XCP session. In this case the following external hardware specific
* functions must be provided: NvmWrite, NvmErase and CpuStartUserProgram.
*/
#define XCP_RES_PROGRAMMING_EN (1)
/** \brief Enable (=1) or disable (=0) support for the data acquisition resource. This
* note that this feature is currently not supported by the XCP driver.
*/
#define XCP_RES_DATA_ACQUISITION_EN (0)
/** \brief Enable (=1) or disable (=0) support for the data stimulation resource. This
* note that this feature is currently not supported by the XCP driver.
*/
#define XCP_RES_DATA_STIMULATION_EN (0)
/** \brief Enable (=1) or disable (=0) support for the seed/key protection feature.
* If enabled, the XCP master has to perform a GET_SEED/UNLOCK sequence to
* obtain access to a resource. The protection algorithm is implemented in
* XcpGetSeed and XcpVerifyKey.
*/
#if (BOOT_XCP_SEED_KEY_ENABLE > 0)
#define XCP_SEED_KEY_PROTECTION_EN (1)
#else
#define XCP_SEED_KEY_PROTECTION_EN (0)
#endif
/** \brief Enable (=1) or disable (=0) uploading. By default, XCP always allows memory
* read operations using the commands UPLOAD and SHORT_UPLOAD. This is not
* always desired for security reasons. If disabled, memory reads via XCP always
* return zero values.
*/
#if (BOOT_XCP_UPLOAD_ENABLE > 0)
#define XCP_UPLOAD_EN (1)
#else
#define XCP_UPLOAD_EN (0)
#endif
/** \brief Enable (=1) or disable the hook function that gets called each time an XCP
* packet was received from the host.
* \details A master-slave bootloader can be realized by using this hook-function. The
* mode parameter in the XCP Connect command can be interpreted as a node ID.
* When trying to connect to a slave, a gateway could be activated that passes
* the packet on to the slave. When the response packet is received from the
* slave, ComTransmitPacket() can be called to pass the response on to the
* host. At the end of a firmware update procedure, the XCP Program Reset
* command is called, which can be used to deactivate the gateway. If this
* hook-function returns BLT_TRUE, the packet is no longer processed by the XCP
* module. If it returns BLT_FALSE, then the packet is processed as usual by
* the XCP module.
*/
#if (BOOT_XCP_PACKET_RECEIVED_HOOK > 0)
#define XCP_PACKET_RECEIVED_HOOK_EN (1)
#else
#define XCP_PACKET_RECEIVED_HOOK_EN (0)
#endif
/****************************************************************************************
* Defines
****************************************************************************************/
/** \brief XCP protocol layer version number (16-bit). */
#define XCP_VERSION_PROTOCOL_LAYER (0x0100)
/** \brief XCP transport layer version number (16-bit). */
#define XCP_VERSION_TRANSPORT_LAYER (0x0100)
/* XCP packet identifiers */
/** \brief Command response packet identifier. */
#define XCP_PID_RES (0xff)
/** \brief Error packet identifier. */
#define XCP_PID_ERR (0xfe)
/* XCP error codes */
/** \brief Cmd processor synchronization error code. */
#define XCP_ERR_CMD_SYNCH (0x00)
/** \brief Command was not executed error code. */
#define XCP_ERR_CMD_BUSY (0x10)
/** \brief Unknown or unsupported command error code. */
#define XCP_ERR_CMD_UNKNOWN (0x20)
/** \brief Parameter out of range error code. */
#define XCP_ERR_OUT_OF_RANGE (0x22)
/** \brief Protected error code. Seed/key required. */
#define XCP_ERR_ACCESS_LOCKED (0x25)
/** \brief Cal page not valid error code. */
#define XCP_ERR_PAGE_NOT_VALID (0x26)
/** \brief Sequence error code. */
#define XCP_ERR_SEQUENCE (0x29)
/** \brief Generic error code. */
#define XCP_ERR_GENERIC (0x31)
/* XCP command codes */
/** \brief CONNECT command code. */
#define XCP_CMD_CONNECT (0xff)
/** \brief DISCONNECT command code. */
#define XCP_CMD_DISCONNECT (0xfe)
/** \brief GET_STATUS command code. */
#define XCP_CMD_GET_STATUS (0xfd)
/** \brief SYNCH command code. */
#define XCP_CMD_SYNCH (0xfc)
/** \brief GET_ID command code. */
#define XCP_CMD_GET_ID (0xfa)
/** \brief GET_SEED command code. */
#define XCP_CMD_GET_SEED (0xf8)
/** \brief UNLOCK command code. */
#define XCP_CMD_UNLOCK (0xf7)
/** \brief SET_MTA command code. */
#define XCP_CMD_SET_MTA (0xf6)
/** \brief UPLOAD command code. */
#define XCP_CMD_UPLOAD (0xf5)
/** \brief SHORT_UPLOAD command code. */
#define XCP_CMD_SHORT_UPLOAD (0xf4)
/** \brief BUILD_CHECKSUM command code. */
#define XCP_CMD_BUILD_CHECKSUM (0xf3)
/** \brief DOWNLOAD command code. */
#define XCP_CMD_DOWNLOAD (0xf0)
/** \brief DOWNLOAD_MAX command code. */
#define XCP_CMD_DOWLOAD_MAX (0xee)
/** \brief SET_CALPAGE command code. */
#define XCP_CMD_SET_CAL_PAGE (0xeb)
/** \brief GET_CALPAGE command code. */
#define XCP_CMD_GET_CAL_PAGE (0xea)
/** \brief PROGRAM_START command code. */
#define XCP_CMD_PROGRAM_START (0xd2)
/** \brief PROGRAM_CLEAR command code. */
#define XCP_CMD_PROGRAM_CLEAR (0xd1)
/** \brief PROGRAM command code. */
#define XCP_CMD_PROGRAM (0xd0)
/** \brief PROGRAM_RESET command code. */
#define XCP_CMD_PROGRAM_RESET (0xcf)
/** \brief PROGRAM_PREPARE command code. */
#define XCP_CMD_PROGRAM_PREPARE (0xcc)
/** \brief PROGRAM_MAX command code. */
#define XCP_CMD_PROGRAM_MAX (0xc9)
/* xcp supported resources */
/** \brief ProGraMming resource. */
#define XCP_RES_PGM (0x10)
/** \brief data STIMulation resource. */
#define XCP_RES_STIM (0x08)
/** \brief Data AcQuisition resource. */
#define XCP_RES_DAQ (0x04)
/** \brief CALibration and PAGing resource. */
#define XCP_RES_CALPAG (0x01)
/* xcp checksum types */
/** \brief Add byte into byte checksum. */
#define XCP_CS_ADD11 (0x01)
/** \brief Add byte into word checksum. */
#define XCP_CS_ADD12 (0x02)
/** \brief Add byte into dword checksum. */
#define XCP_CS_ADD14 (0x03)
/** \brief Add word into word checksum. */
#define XCP_CS_ADD22 (0x04)
/** \brief Add word into dword checksum. */
#define XCP_CS_ADD24 (0x05)
/** \brief Add dword into dword checksum. */
#define XCP_CS_ADD44 (0x06)
/** \brief Use 16-bit CRC algorithm. */
#define XCP_CS_CRC16 (0x07)
/** \brief Use 16-bit CRC CITT algorithm. */
#define XCP_CS_CRC16CITT (0x08)
/** \brief Use 32-bit CRC algorithm. */
#define XCP_CS_CRC32 (0x09)
/** \brief Use user defined algorithm. */
#define XCP_CS_USER (0xff)
/** \brief Maximum number of bytes of a seed for the seed/key security feature. */
#define XCP_SEED_MAX_LEN (BOOT_XCP_SEED_MAX_LEN)
/** \brief Maximum number of bytes of a key for the seed/key security feature. */
#define XCP_KEY_MAX_LEN (BOOT_XCP_KEY_MAX_LEN)
/****************************************************************************************
* Function prototypes
****************************************************************************************/
void XcpInit(void);
blt_bool XcpIsConnected(void);
void XcpPacketTransmitted(void);
void XcpPacketReceived(blt_int8u *data, blt_int8u len);
/****************************************************************************************
* Configuration check
****************************************************************************************/
#if (XCP_RES_DATA_ACQUISITION_EN == 1)
#error "XCP.H, Current XCP driver does not support Data AcQuisition resource."
#endif
#if (XCP_RES_DATA_STIMULATION_EN == 1)
#error "XCP.H, Current XCP driver does not support Data StIMulation resource."
#endif
#ifndef XCP_CTO_PACKET_LEN
#error "XCP.H, Configuration macro XCP_CTO_PACKET_LEN is missing."
#endif
#ifndef XCP_DTO_PACKET_LEN
#error "XCP.H, Configuration macro XCP_DTO_PACKET_LEN is missing."
#endif
#ifndef XCP_STATION_ID_STRING
#error "XCP.H, Configuration macro XCP_STATION_ID_STRING is missing."
#endif
#ifndef XCP_RES_CALIBRATION_EN
#error "XCP.H, Configuration macro XCP_RES_CALIBRATION_EN is missing."
#endif
#if (XCP_RES_CALIBRATION_EN < 0) || (XCP_RES_CALIBRATION_EN > 1)
#error "XCP.H, XCP_RES_CALIBRATION_EN must be 0 or 1."
#endif
#ifndef XCP_RES_PAGING_EN
#error "XCP.H, Configuration macro XCP_RES_PAGING_EN is missing."
#endif
#if (XCP_RES_PAGING_EN < 0) || (XCP_RES_PAGING_EN > 1)
#error "XCP.H, XCP_RES_PAGING_EN must be 0 or 1."
#endif
#ifndef XCP_RES_PROGRAMMING_EN
#error "XCP.H, Configuration macro XCP_RES_PAGING_EN is missing."
#endif
#if (XCP_RES_PROGRAMMING_EN < 0) || (XCP_RES_PROGRAMMING_EN > 1)
#error "XCP.H, XCP_RES_PROGRAMMING_EN must be 0 or 1."
#endif
#ifndef XCP_RES_DATA_ACQUISITION_EN
#error "XCP.H, Configuration macro XCP_RES_DATA_ACQUISITION_EN is missing."
#endif
#if (XCP_RES_DATA_ACQUISITION_EN < 0) || (XCP_RES_DATA_ACQUISITION_EN > 1)
#error "XCP.H, XCP_RES_DATA_ACQUISITION_EN must be 0 or 1."
#endif
#ifndef XCP_RES_DATA_STIMULATION_EN
#error "XCP.H, Configuration macro XCP_RES_DATA_STIMULATION_EN is missing."
#endif
#if (XCP_RES_DATA_STIMULATION_EN < 0) || (XCP_RES_DATA_STIMULATION_EN > 1)
#error "XCP.H, XCP_RES_DATA_STIMULATION_EN must be 0 or 1."
#endif
#ifndef XCP_SEED_KEY_PROTECTION_EN
#error "XCP.H, Configuration macro XCP_SEED_KEY_PROTECTION_EN is missing."
#endif
#if (XCP_SEED_KEY_PROTECTION_EN < 0) || (XCP_SEED_KEY_PROTECTION_EN > 1)
#error "XCP.H, XCP_SEED_KEY_PROTECTION_EN must be 0 or 1."
#endif
#ifndef XCP_UPLOAD_EN
#error "XCP.H, Configuration macro XCP_UPLOAD_EN is missing."
#endif
#if (XCP_UPLOAD_EN < 0) || (XCP_UPLOAD_EN > 1)
#error "XCP.H, XCP_UPLOAD_EN must be 0 or 1."
#endif
#ifndef XCP_PACKET_RECEIVED_HOOK_EN
#error "XCP.H, Configuration macro XCP_PACKET_RECEIVED_HOOK_EN is missing."
#endif
#if (XCP_PACKET_RECEIVED_HOOK_EN < 0) || (XCP_PACKET_RECEIVED_HOOK_EN > 1)
#error "XCP.H, XCP_PACKET_RECEIVED_HOOK_EN must be 0 or 1."
#endif
#endif /* BOOT_COM_ENABLE > 0 */
#endif /* XCP_H */
/******************************** end of xcp.h *~~~~~***********************************/