155 lines
5.3 KiB
C
155 lines
5.3 KiB
C
// The code is this file allows the user to enter DFU mode when the board
|
|
// starts up, by connecting POS10 on the external connector to GND.
|
|
// The code itself is taken from the LimiFrog software repository found at
|
|
// https://github.com/LimiFrog/LimiFrog-SW, and the original license header
|
|
// is copied below.
|
|
|
|
#include STM32_HAL_H
|
|
|
|
static void LBF_DFU_If_Needed(void);
|
|
|
|
void LIMIFROG_board_early_init(void) {
|
|
LBF_DFU_If_Needed();
|
|
}
|
|
|
|
/*******************************************************************************
|
|
* LBF_DFU_If_Needed.c
|
|
*
|
|
* (c)2015 LimiFrog / CYMEYA
|
|
* This program is licensed under the terms of the MIT License.
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND.
|
|
* Please refer to the License File LICENSE.txt located at the root of this
|
|
* project for full licensing conditions,
|
|
* or visit https://opensource.org/licenses/MIT.
|
|
******************************************************************************/
|
|
|
|
#define __LIMIFROG_02
|
|
|
|
/* ==== BTLE (excl UART) ======================================== */
|
|
// PC9 = BT_RST (active high)
|
|
|
|
#define BT_RST_PIN GPIO_PIN_9
|
|
#define BT_RST_PORT GPIOC
|
|
|
|
// Position 10
|
|
#ifdef __LIMIFROG_01
|
|
#define CONN_POS10_PIN GPIO_PIN_9
|
|
#define CONN_POS10_PORT GPIOB
|
|
#else
|
|
#define CONN_POS10_PIN GPIO_PIN_8
|
|
#define CONN_POS10_PORT GPIOB
|
|
#endif
|
|
|
|
static inline void GPIO_HIGH(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
|
|
{
|
|
GPIOx->BSRR = (uint32_t)GPIO_Pin;
|
|
}
|
|
|
|
static inline int IS_GPIO_RESET(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
|
|
{
|
|
GPIO_PinState bitstatus;
|
|
if((GPIOx->IDR & GPIO_Pin) != (uint32_t)GPIO_PIN_RESET)
|
|
{
|
|
bitstatus = GPIO_PIN_SET;
|
|
}
|
|
else
|
|
{
|
|
bitstatus = GPIO_PIN_RESET;
|
|
}
|
|
return (bitstatus==GPIO_PIN_RESET);
|
|
}
|
|
|
|
/**************************************************************
|
|
RATIONALE FOR THIS FUNCTION :
|
|
|
|
- The STM32 embeds in ROM a bootloader that allows to
|
|
obtain code and boot from a number of different interfaces,
|
|
including USB in a mode called "DFU" (Device Frimware Update)
|
|
[see AN3606 from ST for full details]
|
|
This bootloader code is executed instead of the regular
|
|
application code when pin BOOT0 is pulled-up (which on
|
|
LimiFrog0.2 is achieved by pressing the general-purpose
|
|
pushbutton switch on the side.
|
|
- The bootloader monitors a number of IOs of the STM32 to decide
|
|
from which interface it should boot.
|
|
- Problem in LimiFrog (up to versions 0.2a at least): upon
|
|
power-up the BLE modules generates some activity on UART3,
|
|
which is part of the pins monitored by the STM32.
|
|
This misleads the bootloader in trying to boot from UART3
|
|
and, as a result, not continuing with booting from USB.
|
|
|
|
- This code implements an alternative solution to launch the
|
|
bootloader while making sure UART3 remains stable.
|
|
- The idea it to start application code with a check, prior to any
|
|
other applicative code, of whether USB bootload is required (as
|
|
flagged by a GPIO pulled low at reset, in the same way as BOOT0).
|
|
The hadware reset pin of BLE is asserted (so that now it won't
|
|
generate any acitivity on UART3), and if USB bootload is required :
|
|
bootload ROM is remapped at address 0x0, stack pointer is
|
|
updated and the code is branched to the start of the bootloader.
|
|
- This code is run prior to any applicative configuration of clocks,
|
|
IRQs etc. -- the STM32 is therefore still running from MSI
|
|
|
|
THIS FUNCTION MAY BE SUPPRESSED IF YOU NEVER NEED TO BOOT DFU MODE
|
|
|
|
********************************************************************/
|
|
|
|
static void LBF_DFU_If_Needed(void)
|
|
{
|
|
|
|
|
|
GPIO_InitTypeDef GPIO_InitStruct;
|
|
|
|
|
|
// Initialize and assert pin BTLE_RST
|
|
// (hw reset to BLE module, so it won't drive UART3)
|
|
|
|
__GPIOC_CLK_ENABLE();
|
|
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
|
|
GPIO_InitStruct.Pull = GPIO_NOPULL;
|
|
GPIO_InitStruct.Speed = GPIO_SPEED_LOW;
|
|
GPIO_InitStruct.Pin = BT_RST_PIN;
|
|
HAL_GPIO_Init(BT_RST_PORT, &GPIO_InitStruct);
|
|
|
|
GPIO_HIGH(BT_RST_PORT, BT_RST_PIN); // assert BTLE reset
|
|
|
|
|
|
/* -- Bootloader will be called if position 10 on the extension port
|
|
is actively pulled low -- */
|
|
// Note - this is an arbitrary choice, code could be modified to
|
|
// monitor another GPIO of the STM32 and/or decide that active level
|
|
// is high rather than low
|
|
|
|
|
|
// Initialize Extension Port Position 10 = PB8 (bears I2C1_SCL)
|
|
// Use weak pull-up to detect if pin is externally pulled low
|
|
|
|
__GPIOB_CLK_ENABLE();
|
|
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
|
|
GPIO_InitStruct.Pull = GPIO_PULLUP;
|
|
GPIO_InitStruct.Pin = CONN_POS10_PIN;
|
|
HAL_GPIO_Init(CONN_POS10_PORT, &GPIO_InitStruct);
|
|
|
|
// If selection pin pulled low...
|
|
if ( IS_GPIO_RESET(CONN_POS10_PORT, CONN_POS10_PIN ))
|
|
|
|
{
|
|
// Remap bootloader ROM (ie System Flash) to address 0x0
|
|
SYSCFG->MEMRMP = 0x00000001;
|
|
|
|
// Init stack pointer with value residing at ROM base
|
|
asm (
|
|
"LDR R0, =0x00000000\n\t" // load ROM base address"
|
|
"LDR SP,[R0, #0]\n\t" // assign main stack pointer"
|
|
);
|
|
|
|
// Jump to address pointed by 0x00000004 -- */
|
|
|
|
asm (
|
|
"LDR R0,[R0, #4]\n\t" // load bootloader address
|
|
"BX R0\n\t"
|
|
);
|
|
|
|
}
|
|
}
|