/************************************************************************************//** * \file Demo/ARMCM3_EFM32_Olimex_EM32G880F128STK_GCC/Prog/boot.c * \brief Demo program bootloader interface source file. * \ingroup Prog_ARMCM3_EFM32_Olimex_EM32G880F128STK_GCC * \internal *---------------------------------------------------------------------------------------- * C O P Y R I G H T *---------------------------------------------------------------------------------------- * Copyright (c) 2012 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 "header.h" /* generic header */ /**************************************************************************************** * Function prototypes ****************************************************************************************/ #if (BOOT_COM_RS232_ENABLE > 0) static void BootComRs232Init(void); static void BootComRs232CheckActivationRequest(void); #endif /************************************************************************************//** ** \brief Initializes the communication interface. ** \return none. ** ****************************************************************************************/ void BootComInit(void) { #if (BOOT_COM_RS232_ENABLE > 0) BootComRs232Init(); #endif } /*** end of BootComInit ***/ /************************************************************************************//** ** \brief Receives the CONNECT request from the host, which indicates that the ** bootloader should be activated and, if so, activates it. ** \return none. ** ****************************************************************************************/ void BootComCheckActivationRequest(void) { #if (BOOT_COM_RS232_ENABLE > 0) BootComRs232CheckActivationRequest(); #endif } /*** end of BootComCheckActivationRequest ***/ /************************************************************************************//** ** \brief Bootloader activation function. ** \return none. ** ****************************************************************************************/ void BootActivate(void) { /* perform software reset to activate the bootoader again */ NVIC_SystemReset(); } /*** end of BootActivate ***/ #if (BOOT_COM_RS232_ENABLE > 0) /**************************************************************************************** * U N I V E R S A L A S Y N C H R O N O U S R X T X I N T E R F A C E ****************************************************************************************/ /**************************************************************************************** * 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) /**************************************************************************************** * Function prototypes ****************************************************************************************/ static unsigned char Rs232ReceiveByte(unsigned char *data); /************************************************************************************//** ** \brief Initializes the UART communication interface. ** \return none. ** ****************************************************************************************/ static void BootComRs232Init(void) { LEUART_Init_TypeDef init = LEUART_INIT_DEFAULT; /* configure GPIO pins */ CMU_ClockEnable(cmuClock_GPIO, true); /* to avoid false start, configure output as high */ GPIO_PinModeSet(gpioPortC, 6, gpioModePushPull, 1); GPIO_PinModeSet(gpioPortC, 7, gpioModeInput, 0); /* enable CORE LE clock in order to access LE modules */ CMU_ClockEnable(cmuClock_CORELE, true); /* select LFXO for LEUARTs (and wait for it to stabilize) */ CMU_ClockSelectSet(cmuClock_LFB, cmuSelect_LFXO); /* do not prescale clock */ CMU_ClockDivSet(cmuClock_LEUART1, cmuClkDiv_1); /* enable LEUART1 clock */ CMU_ClockEnable(cmuClock_LEUART1, true); /* configure LEUART */ init.enable = leuartDisable; LEUART_Init(LEUART1, &init); LEUART_BaudrateSet(LEUART1, 0, BOOT_COM_RS232_BAUDRATE); /* enable pins at default location */ LEUART1->ROUTE = LEUART_ROUTE_RXPEN | LEUART_ROUTE_TXPEN; /* clear previous RX interrupts */ LEUART_IntClear(LEUART1, LEUART_IF_RXDATAV); /* finally enable it */ LEUART_Enable(LEUART1, leuartEnable); } /*** end of BootComRs232Init ***/ /************************************************************************************//** ** \brief Receives the CONNECT request from the host, which indicates that the ** bootloader should be activated and, if so, activates it. ** \return none. ** ****************************************************************************************/ static void BootComRs232CheckActivationRequest(void) { static unsigned char xcpCtoReqPacket[BOOT_COM_RS232_RX_MAX_DATA+1]; static unsigned char xcpCtoRxLength; static unsigned char xcpCtoRxInProgress = 0; static unsigned long xcpCtoRxStartTime = 0; /* start of cto packet received? */ if (xcpCtoRxInProgress == 0) { /* store the message length when received */ if (Rs232ReceiveByte(&xcpCtoReqPacket[0]) == 1) { /* check that the length has a valid value. it should not be 0 */ if ( (xcpCtoReqPacket[0] > 0) && (xcpCtoReqPacket[0] <= BOOT_COM_RS232_RX_MAX_DATA) ) { /* store the start time */ xcpCtoRxStartTime = TimerGet(); /* indicate that a cto packet is being received */ xcpCtoRxInProgress = 1; /* reset packet data count */ xcpCtoRxLength = 0; } } } else { /* store the next packet byte */ if (Rs232ReceiveByte(&xcpCtoReqPacket[xcpCtoRxLength+1]) == 1) { /* increment the packet data count */ xcpCtoRxLength++; /* check to see if the entire packet was received */ if (xcpCtoRxLength == xcpCtoReqPacket[0]) { /* done with cto packet reception */ xcpCtoRxInProgress = 0; /* check if this was an XCP CONNECT command */ if ((xcpCtoReqPacket[1] == 0xff) && (xcpCtoRxLength == 2)) { /* connection request received so start the bootloader */ BootActivate(); } } } else { /* check packet reception timeout */ if (TimerGet() > (xcpCtoRxStartTime + RS232_CTO_RX_PACKET_TIMEOUT_MS)) { /* cancel cto packet reception due to timeout. note that this automatically * discards the already received packet bytes, allowing the host to retry. */ xcpCtoRxInProgress = 0; } } } } /*** end of BootComRs232CheckActivationRequest ***/ /************************************************************************************//** ** \brief Receives a communication interface byte if one is present. ** \param data Pointer to byte where the data is to be stored. ** \return 1 if a byte was received, 0 otherwise. ** ****************************************************************************************/ static unsigned char Rs232ReceiveByte(unsigned char *data) { /* check to see if a new bytes was received */ if ((LEUART1->IF & LEUART_IF_RXDATAV) != 0) { /* store the received data byte and set return value to positive */ *data = LEUART_Rx(LEUART1); return 1; } /* still here to no new byte received */ return 0; } /*** end of Rs232ReceiveByte ***/ #endif /* BOOT_COM_RS232_ENABLE > 0 */ /*********************************** end of boot.c *************************************/