Init
This commit is contained in:
56
openblt/ARMCM4_STM32L4/GCC/cpu_comp.c
Normal file
56
openblt/ARMCM4_STM32L4/GCC/cpu_comp.c
Normal 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 *********************************/
|
||||
350
openblt/ARMCM4_STM32L4/can.c
Normal file
350
openblt/ARMCM4_STM32L4/can.c
Normal 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 **************************************/
|
||||
195
openblt/ARMCM4_STM32L4/cpu.c
Normal file
195
openblt/ARMCM4_STM32L4/cpu.c
Normal 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 **************************************/
|
||||
821
openblt/ARMCM4_STM32L4/flash.c
Normal file
821
openblt/ARMCM4_STM32L4/flash.c
Normal 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 ************************************/
|
||||
45
openblt/ARMCM4_STM32L4/flash.h
Normal file
45
openblt/ARMCM4_STM32L4/flash.h
Normal 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 ************************************/
|
||||
245
openblt/ARMCM4_STM32L4/nvm.c
Normal file
245
openblt/ARMCM4_STM32L4/nvm.c
Normal 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 **************************************/
|
||||
316
openblt/ARMCM4_STM32L4/rs232.c
Normal file
316
openblt/ARMCM4_STM32L4/rs232.c
Normal 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 ************************************/
|
||||
129
openblt/ARMCM4_STM32L4/timer.c
Normal file
129
openblt/ARMCM4_STM32L4/timer.c
Normal 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 ************************************/
|
||||
58
openblt/ARMCM4_STM32L4/types.h
Normal file
58
openblt/ARMCM4_STM32L4/types.h
Normal 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 ************************************/
|
||||
521
openblt/ARMCM4_STM32L4/usb.c
Normal file
521
openblt/ARMCM4_STM32L4/usb.c
Normal 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
56
openblt/asserts.c
Normal 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
62
openblt/asserts.h
Normal 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
221
openblt/backdoor.c
Normal 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
43
openblt/backdoor.h
Normal 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
95
openblt/boot.c
Normal 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
79
openblt/boot.h
Normal 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
42
openblt/can.h
Normal 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
356
openblt/com.c
Normal 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
145
openblt/com.h
Normal 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
70
openblt/cop.c
Normal 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
39
openblt/cop.h
Normal 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
44
openblt/cpu.h
Normal 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
853
openblt/file.c
Normal 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
103
openblt/file.h
Normal 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
446
openblt/net.c
Normal 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
80
openblt/net.h
Normal 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
56
openblt/nvm.h
Normal 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
519
openblt/plausibility.h
Normal 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
42
openblt/rs232.h
Normal 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
41
openblt/timer.h
Normal 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
52
openblt/usb.h
Normal 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
1500
openblt/xcp.c
Normal file
File diff suppressed because it is too large
Load Diff
357
openblt/xcp.h
Normal file
357
openblt/xcp.h
Normal 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 *~~~~~***********************************/
|
||||
Reference in New Issue
Block a user