1 Star 4 Fork 0

px4/Bootloader

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
main_f4.c 23.57 KB
一键复制 编辑 原始数据 按行查看 历史
Zoey Zhuang 提交于 2021-01-19 18:28 +08:00 . Ensure RTC is enabled and LSE is not affected
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937
/*
* STM32F4 board support for the bootloader.
*
*/
#include "hw_config.h"
#include <stdlib.h>
#include <libopencm3/stm32/rcc.h>
#include <libopencm3/stm32/gpio.h>
#include <libopencm3/stm32/flash.h>
#include <libopencm3/stm32/usart.h>
#include <libopencm3/cm3/systick.h>
#include <libopencm3/stm32/pwr.h>
#include <libopencm3/stm32/timer.h>
#include <libopencm3/cm3/scb.h>
#include <libopencm3/cm3/systick.h>
#include "bl.h"
#include "uart.h"
/* flash parameters that we should not really know */
static struct {
uint32_t sector_number;
uint32_t size;
} flash_sectors[] = {
/* Physical FLASH sector 0 is reserved for bootloader and is not
* the table below.
* N sectors may aslo be reserved for the app fw in which case
* the zero based define BOARD_FIRST_FLASH_SECTOR_TO_ERASE must
* be defined to begin the erase above of the reserved sectors.
* The default value of BOARD_FIRST_FLASH_SECTOR_TO_ERASE is 0
* and begins flash erase operations at phsical sector 1 the 0th entry
* in the table below.
* A value of 1 for BOARD_FIRST_FLASH_SECTOR_TO_ERASE would reserve
* the 0th entry and begin erasing a index 1 the third physical sector
* on the device.
*
* When BOARD_FIRST_FLASH_SECTOR_TO_ERASE is defined APP_RESERVATION_SIZE
* must also be defined to remove that additonal reserved FLASH space
* from the BOARD_FLASH_SIZE. See APP_SIZE_MAX below.
*/
{0x01, 16 * 1024},
{0x02, 16 * 1024},
{0x03, 16 * 1024},
{0x04, 64 * 1024},
{0x05, 128 * 1024},
{0x06, 128 * 1024},
{0x07, 128 * 1024},
{0x08, 128 * 1024},
{0x09, 128 * 1024},
{0x0a, 128 * 1024},
{0x0b, 128 * 1024},
/* flash sectors only in 2MiB devices */
{0x10, 16 * 1024},
{0x11, 16 * 1024},
{0x12, 16 * 1024},
{0x13, 16 * 1024},
{0x14, 64 * 1024},
{0x15, 128 * 1024},
{0x16, 128 * 1024},
{0x17, 128 * 1024},
{0x18, 128 * 1024},
{0x19, 128 * 1024},
{0x1a, 128 * 1024},
{0x1b, 128 * 1024},
};
#define BOOTLOADER_RESERVATION_SIZE (16 * 1024)
#define OTP_BASE 0x1fff7800
#define OTP_SIZE 512
#define UDID_START 0x1FFF7A10
// address of MCU IDCODE
#define DBGMCU_IDCODE 0xE0042000
#define STM32_UNKNOWN 0
#define STM32F40x_41x 0x413
#define STM32F42x_43x 0x419
#define STM32F42x_446xx 0x421
#define REVID_MASK 0xFFFF0000
#define DEVID_MASK 0xFFF
// A board may disable VBUS sensing, but still provide a (non-standard) VBUS
// sensing pin (and use it for fast booting when USB is disconnected). If VBUS
// sensing is enabled, only PA9 can be used.
#ifndef BOARD_USB_VBUS_SENSE_DISABLED
# define BOARD_PORT_VBUS GPIOA
# define BOARD_PIN_VBUS GPIO9
#endif
/* magic numbers from reference manual */
typedef enum mcu_rev_e {
MCU_REV_STM32F4_REV_A = 0x1000,
MCU_REV_STM32F4_REV_Z = 0x1001,
MCU_REV_STM32F4_REV_Y = 0x1003,
MCU_REV_STM32F4_REV_1 = 0x1007,
MCU_REV_STM32F4_REV_3 = 0x2001
} mcu_rev_e;
typedef struct mcu_des_t {
uint16_t mcuid;
const char *desc;
char rev;
} mcu_des_t;
// The default CPU ID of STM32_UNKNOWN is 0 and is in offset 0
// Before a rev is known it is set to ?
// There for new silicon will result in STM32F4..,?
mcu_des_t mcu_descriptions[] = {
{ STM32_UNKNOWN, "STM32F???", '?'},
{ STM32F40x_41x, "STM32F40x", '?'},
{ STM32F42x_43x, "STM32F42x", '?'},
{ STM32F42x_446xx, "STM32F446XX", '?'},
};
typedef struct mcu_rev_t {
mcu_rev_e revid;
char rev;
} mcu_rev_t;
/*
* This table is used in 2 ways. One to look look up the revision
* of a given chip. Two to see it a revsion is in the group of "Bad"
* silicon.
*
* Therefore when adding entries for good silicon rev, they must be inserted
* at the beginning of the table. The value of FIRST_BAD_SILICON_OFFSET will
* also need to be increased to that of the value of the first bad silicon offset.
*
*/
const mcu_rev_t silicon_revs[] = {
{MCU_REV_STM32F4_REV_3, '3'}, /* Revision 3 */
{MCU_REV_STM32F4_REV_A, 'A'}, /* Revision A */ // FIRST_BAD_SILICON_OFFSET (place good ones above this line and update the FIRST_BAD_SILICON_OFFSET accordingly)
{MCU_REV_STM32F4_REV_Z, 'Z'}, /* Revision Z */
{MCU_REV_STM32F4_REV_Y, 'Y'}, /* Revision Y */
{MCU_REV_STM32F4_REV_1, '1'}, /* Revision 1 */
};
#define FIRST_BAD_SILICON_OFFSET 1
#define APP_SIZE_MAX (BOARD_FLASH_SIZE - (BOOTLOADER_RESERVATION_SIZE + APP_RESERVATION_SIZE))
/* context passed to cinit */
#if INTERFACE_USART
# define BOARD_INTERFACE_CONFIG_USART (void *)BOARD_USART
#endif
#if INTERFACE_USB
# define BOARD_INTERFACE_CONFIG_USB NULL
#endif
/* board definition */
struct boardinfo board_info = {
.board_type = BOARD_TYPE,
.board_rev = 0,
.fw_size = 0,
.systick_mhz = 168,
};
static void board_init(void);
#define BOOT_RTC_SIGNATURE 0xb007b007
#define POWER_DOWN_RTC_SIGNATURE 0xdeaddead // Written by app fw to not re-power on.
#define BOOT_RTC_REG MMIO32(RTC_BASE + 0x50)
/* standard clocking for all F4 boards */
static const struct rcc_clock_scale clock_setup = {
.pllm = OSC_FREQ,
.plln = 336,
.pllp = 2,
.pllq = 7,
#if defined(STM32F446) || defined(STM32F469)
.pllr = 2,
#endif
.hpre = RCC_CFGR_HPRE_DIV_NONE,
.ppre1 = RCC_CFGR_PPRE_DIV_4,
.ppre2 = RCC_CFGR_PPRE_DIV_2,
.power_save = 0,
.flash_config = FLASH_ACR_ICEN | FLASH_ACR_DCEN | FLASH_ACR_LATENCY_5WS,
.apb1_frequency = 42000000,
.apb2_frequency = 84000000,
};
/* State of an inserted USB cable */
static bool usb_connected = false;
static uint32_t
board_get_rtc_signature()
{
/* enable the backup registers */
PWR_CR |= PWR_CR_DBP;
RCC_BDCR |= RCC_BDCR_RTCEN;
uint32_t result = BOOT_RTC_REG;
/* disable the backup registers */
PWR_CR &= ~PWR_CR_DBP;
return result;
}
static void
board_set_rtc_signature(uint32_t sig)
{
/* enable the backup registers */
PWR_CR |= PWR_CR_DBP;
RCC_BDCR |= RCC_BDCR_RTCEN;
BOOT_RTC_REG = sig;
/* disable the backup registers */
PWR_CR &= ~PWR_CR_DBP;
}
static bool
board_test_force_pin()
{
#if defined(BOARD_FORCE_BL_PIN_IN) && defined(BOARD_FORCE_BL_PIN_OUT)
/* two pins strapped together */
volatile unsigned samples = 0;
volatile unsigned vote = 0;
for (volatile unsigned cycles = 0; cycles < 10; cycles++) {
gpio_set(BOARD_FORCE_BL_PORT, BOARD_FORCE_BL_PIN_OUT);
for (unsigned count = 0; count < 20; count++) {
if (gpio_get(BOARD_FORCE_BL_PORT, BOARD_FORCE_BL_PIN_IN) != 0) {
vote++;
}
samples++;
}
gpio_clear(BOARD_FORCE_BL_PORT, BOARD_FORCE_BL_PIN_OUT);
for (unsigned count = 0; count < 20; count++) {
if (gpio_get(BOARD_FORCE_BL_PORT, BOARD_FORCE_BL_PIN_IN) == 0) {
vote++;
}
samples++;
}
}
/* the idea here is to reject wire-to-wire coupling, so require > 90% agreement */
if ((vote * 100) > (samples * 90)) {
return true;
}
#endif
#if defined(BOARD_FORCE_BL_PIN)
/* single pin pulled up or down */
volatile unsigned samples = 0;
volatile unsigned vote = 0;
for (samples = 0; samples < 200; samples++) {
if ((gpio_get(BOARD_FORCE_BL_PORT, BOARD_FORCE_BL_PIN) ? 1 : 0) == BOARD_FORCE_BL_STATE) {
vote++;
}
}
/* reject a little noise */
if ((vote * 100) > (samples * 90)) {
return true;
}
#endif
return false;
}
#if INTERFACE_USART
static bool
board_test_usart_receiving_break()
{
#if !defined(SERIAL_BREAK_DETECT_DISABLED)
/* (re)start the SysTick timer system */
systick_interrupt_disable(); // Kill the interrupt if it is still active
systick_counter_disable(); // Stop the timer
systick_set_clocksource(STK_CSR_CLKSOURCE_AHB);
/* Set the timer period to be half the bit rate
*
* Baud rate = 115200, therefore bit period = 8.68us
* Half the bit rate = 4.34us
* Set period to 4.34 microseconds (timer_period = timer_tick / timer_reset_frequency = 168MHz / (1/4.34us) = 729.12 ~= 729)
*/
systick_set_reload(((board_info.systick_mhz * 1000000) / USART_BAUDRATE) >> 1);
systick_counter_enable(); // Start the timer
uint8_t cnt_consecutive_low = 0;
uint8_t cnt = 0;
/* Loop for 3 transmission byte cycles and count the low and high bits. Sampled at a rate to be able to count each bit twice.
*
* One transmission byte is 10 bits (8 bytes of data + 1 start bit + 1 stop bit)
* We sample at every half bit time, therefore 20 samples per transmission byte,
* therefore 60 samples for 3 transmission bytes
*/
while (cnt < 60) {
// Only read pin when SysTick timer is true
if (systick_get_countflag() == 1) {
if (gpio_get(BOARD_PORT_USART_RX, BOARD_PIN_RX) == 0) {
cnt_consecutive_low++; // Increment the consecutive low counter
} else {
cnt_consecutive_low = 0; // Reset the consecutive low counter
}
cnt++;
}
// If 9 consecutive low bits were received break out of the loop
if (cnt_consecutive_low >= 18) {
break;
}
}
systick_counter_disable(); // Stop the timer
/*
* If a break is detected, return true, else false
*
* Break is detected if line was low for 9 consecutive bits.
*/
if (cnt_consecutive_low >= 18) {
return true;
}
#endif // !defined(SERIAL_BREAK_DETECT_DISABLED)
return false;
}
#endif
uint32_t
board_get_devices(void)
{
uint32_t devices = BOOT_DEVICES_SELECTION;
if (usb_connected) {
devices &= BOOT_DEVICES_FILTER_ONUSB;
}
return devices;
}
static void
board_init(void)
{
/* fix up the max firmware size, we have to read memory to get this */
board_info.fw_size = APP_SIZE_MAX;
#if defined(TARGET_HW_PX4_FMU_V2) || defined(TARGET_HW_PX4_FMU_V3) || defined(TARGET_HW_PX4_FMU_V4) || defined(TARGET_HW_UVIFY_CORE)
if (check_silicon() && board_info.fw_size == (2 * 1024 * 1024) - BOOTLOADER_RESERVATION_SIZE) {
board_info.fw_size = (1024 * 1024) - BOOTLOADER_RESERVATION_SIZE;
}
#endif
#if defined(BOARD_POWER_PIN_OUT)
/* Configure the Power pins */
rcc_peripheral_enable_clock(&BOARD_POWER_CLOCK_REGISTER, BOARD_POWER_CLOCK_BIT);
gpio_mode_setup(BOARD_POWER_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, BOARD_POWER_PIN_OUT);
gpio_set_output_options(BOARD_POWER_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_2MHZ, BOARD_POWER_PIN_OUT);
BOARD_POWER_ON(BOARD_POWER_PORT, BOARD_POWER_PIN_OUT);
#endif
#if INTERFACE_USB
#if !defined(BOARD_USB_VBUS_SENSE_DISABLED)
/* enable configured GPIO to sample VBUS */
rcc_peripheral_enable_clock(&RCC_AHB1ENR, RCC_AHB1ENR_IOPAEN);
#endif
#endif
#if INTERFACE_USART
/* configure USART pins */
rcc_peripheral_enable_clock(&BOARD_USART_PIN_CLOCK_REGISTER, BOARD_USART_PIN_CLOCK_BIT_TX);
rcc_peripheral_enable_clock(&BOARD_USART_PIN_CLOCK_REGISTER, BOARD_USART_PIN_CLOCK_BIT_RX);
/* Setup GPIO pins for USART transmit. */
gpio_mode_setup(BOARD_PORT_USART_TX, GPIO_MODE_AF, GPIO_PUPD_PULLUP, BOARD_PIN_TX);
gpio_mode_setup(BOARD_PORT_USART_RX, GPIO_MODE_AF, GPIO_PUPD_PULLUP, BOARD_PIN_RX);
/* Setup USART TX & RX pins as alternate function. */
gpio_set_af(BOARD_PORT_USART_TX, BOARD_PORT_USART_AF_TX, BOARD_PIN_TX);
gpio_set_af(BOARD_PORT_USART_RX, BOARD_PORT_USART_AF_RX, BOARD_PIN_RX);
/* configure USART clock */
rcc_peripheral_enable_clock(&BOARD_USART_CLOCK_REGISTER, BOARD_USART_CLOCK_BIT);
#endif
#if defined(BOARD_FORCE_BL_PIN_IN) && defined(BOARD_FORCE_BL_PIN_OUT)
/* configure the force BL pins */
rcc_peripheral_enable_clock(&BOARD_FORCE_BL_CLOCK_REGISTER, BOARD_FORCE_BL_CLOCK_BIT);
gpio_mode_setup(BOARD_FORCE_BL_PORT, GPIO_MODE_INPUT, BOARD_FORCE_BL_PULL, BOARD_FORCE_BL_PIN_IN);
gpio_mode_setup(BOARD_FORCE_BL_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, BOARD_FORCE_BL_PIN_OUT);
gpio_set_output_options(BOARD_FORCE_BL_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_100MHZ, BOARD_FORCE_BL_PIN_OUT);
#endif
#if defined(BOARD_FORCE_BL_PIN)
/* configure the force BL pins */
rcc_peripheral_enable_clock(&BOARD_FORCE_BL_CLOCK_REGISTER, BOARD_FORCE_BL_CLOCK_BIT);
gpio_mode_setup(BOARD_FORCE_BL_PORT, GPIO_MODE_INPUT, BOARD_FORCE_BL_PULL, BOARD_FORCE_BL_PIN);
#endif
/* initialise LEDs */
rcc_peripheral_enable_clock(&RCC_AHB1ENR, BOARD_CLOCK_LEDS);
gpio_mode_setup(
BOARD_PORT_LEDS,
GPIO_MODE_OUTPUT,
GPIO_PUPD_NONE,
BOARD_PIN_LED_BOOTLOADER | BOARD_PIN_LED_ACTIVITY);
gpio_set_output_options(
BOARD_PORT_LEDS,
GPIO_OTYPE_PP,
GPIO_OSPEED_2MHZ,
BOARD_PIN_LED_BOOTLOADER | BOARD_PIN_LED_ACTIVITY);
BOARD_LED_ON(
BOARD_PORT_LEDS,
BOARD_PIN_LED_BOOTLOADER | BOARD_PIN_LED_ACTIVITY);
/* enable the power controller clock */
rcc_peripheral_enable_clock(&RCC_APB1ENR, RCC_APB1ENR_PWREN);
}
void
board_deinit(void)
{
#if INTERFACE_USART
/* deinitialise GPIO pins for USART transmit. */
gpio_mode_setup(BOARD_PORT_USART_TX, GPIO_MODE_INPUT, GPIO_PUPD_NONE, BOARD_PIN_TX);
gpio_mode_setup(BOARD_PORT_USART_RX, GPIO_MODE_INPUT, GPIO_PUPD_NONE, BOARD_PIN_RX);
/* disable USART peripheral clock */
rcc_peripheral_disable_clock(&BOARD_USART_CLOCK_REGISTER, BOARD_USART_CLOCK_BIT);
#endif
#if defined(BOARD_FORCE_BL_PIN_IN) && defined(BOARD_FORCE_BL_PIN_OUT)
/* deinitialise the force BL pins */
gpio_mode_setup(BOARD_FORCE_BL_PORT, GPIO_MODE_INPUT, GPIO_PUPD_NONE, BOARD_FORCE_BL_PIN_OUT);
gpio_mode_setup(BOARD_FORCE_BL_PORT, GPIO_MODE_INPUT, GPIO_PUPD_NONE, BOARD_FORCE_BL_PIN_IN);
#endif
#if defined(BOARD_FORCE_BL_PIN)
/* deinitialise the force BL pin */
gpio_mode_setup(BOARD_FORCE_BL_PORT, GPIO_MODE_INPUT, GPIO_PUPD_NONE, BOARD_FORCE_BL_PIN);
#endif
#if defined(BOARD_POWER_PIN_OUT) && defined(BOARD_POWER_PIN_RELEASE)
/* deinitialize the POWER pin - with the assumption the hold up time of
* the voltage being bleed off by an inupt pin impedance will allow
* enough time to boot the app
*/
gpio_mode_setup(BOARD_POWER_PORT, GPIO_MODE_INPUT, GPIO_PUPD_NONE, BOARD_POWER_PIN);
#endif
/* deinitialise LEDs */
gpio_mode_setup(
BOARD_PORT_LEDS,
GPIO_MODE_INPUT,
GPIO_PUPD_NONE,
BOARD_PIN_LED_BOOTLOADER | BOARD_PIN_LED_ACTIVITY);
/* disable the power controller clock */
rcc_peripheral_disable_clock(&RCC_APB1ENR, RCC_APB1ENR_PWREN);
/* disable the AHB peripheral clocks */
RCC_AHB1ENR = 0x00100000; // XXX Magic reset number from STM32F4x reference manual
}
/**
* @brief Initializes the RCC clock configuration.
*
* @param clock_setup : The clock configuration to set
*/
static inline void
clock_init(void)
{
rcc_clock_setup_hse_3v3(&clock_setup);
}
inline void arch_systic_init(void)
{
/* (re)start the timer system */
systick_set_clocksource(STK_CSR_CLKSOURCE_AHB);
systick_set_reload(board_info.systick_mhz * 1000); /* 1ms tick, magic number */
systick_interrupt_enable();
systick_counter_enable();
}
inline void arch_systic_deinit(void)
{
/* kill the systick interrupt */
systick_interrupt_disable();
systick_counter_disable();
}
/**
* @brief Resets the RCC clock configuration to the default reset state.
* @note The default reset state of the clock configuration is given below:
* - HSI ON and used as system clock source
* - HSE, PLL and PLLI2S OFF
* - AHB, APB1 and APB2 prescaler set to 1.
* - CSS, MCO1 and MCO2 OFF
* - All interrupts disabled
* @note This function doesn't modify the configuration of the
* - Peripheral clocks
* - LSI, LSE and RTC clocks
*/
void
clock_deinit(void)
{
/* Enable internal high-speed oscillator. */
rcc_osc_on(RCC_HSI);
rcc_wait_for_osc_ready(RCC_HSI);
/* Reset the RCC_CFGR register */
RCC_CFGR = 0x000000;
/* Stop the HSE, CSS, PLL, PLLI2S, PLLSAI */
rcc_osc_off(RCC_HSE);
rcc_osc_off(RCC_PLL);
rcc_css_disable();
/* Reset the RCC_PLLCFGR register */
RCC_PLLCFGR = 0x24003010; // XXX Magic reset number from STM32F4xx reference manual
/* Reset the HSEBYP bit */
rcc_osc_bypass_disable(RCC_HSE);
/* Reset the CIR register */
RCC_CIR = 0x000000;
}
inline void arch_flash_lock(void)
{
flash_lock();
}
inline void arch_flash_unlock(void)
{
flash_unlock();
}
inline void arch_setvtor(uint32_t address)
{
SCB_VTOR = address;
}
uint32_t
flash_func_sector_size(unsigned sector)
{
if (sector < BOARD_FLASH_SECTORS) {
return flash_sectors[sector].size;
}
return 0;
}
void
flash_func_erase_sector(unsigned sector)
{
if (sector >= BOARD_FLASH_SECTORS || sector < BOARD_FIRST_FLASH_SECTOR_TO_ERASE) {
return;
}
/* Caculate the logical base address of the sector
* flash_func_read_word will add APP_LOAD_ADDRESS
*/
uint32_t address = 0;
for (unsigned i = BOARD_FIRST_FLASH_SECTOR_TO_ERASE; i < sector; i++) {
address += flash_func_sector_size(i);
}
/* blank-check the sector */
unsigned size = flash_func_sector_size(sector);
bool blank = true;
for (unsigned i = 0; i < size; i += sizeof(uint32_t)) {
if (flash_func_read_word(address + i) != 0xffffffff) {
blank = false;
break;
}
}
/* erase the sector if it failed the blank check */
if (!blank) {
flash_erase_sector(flash_sectors[sector].sector_number, FLASH_CR_PROGRAM_X32);
}
}
void
flash_func_write_word(uint32_t address, uint32_t word)
{
flash_program_word(address + APP_LOAD_ADDRESS, word);
}
uint32_t
flash_func_read_word(uint32_t address)
{
if (address & 3) {
return 0;
}
return *(uint32_t *)(address + APP_LOAD_ADDRESS);
}
uint32_t
flash_func_read_otp(uint32_t address)
{
if (address & 3) {
return 0;
}
if (address > OTP_SIZE) {
return 0;
}
return *(uint32_t *)(address + OTP_BASE);
}
uint32_t get_mcu_id(void)
{
return *(uint32_t *)DBGMCU_IDCODE;
}
int get_mcu_desc(int max, uint8_t *revstr)
{
uint32_t idcode = (*(uint32_t *)DBGMCU_IDCODE);
int32_t mcuid = idcode & DEVID_MASK;
mcu_rev_e revid = (idcode & REVID_MASK) >> 16;
mcu_des_t des = mcu_descriptions[STM32_UNKNOWN];
for (int i = 0; i < arraySize(mcu_descriptions); i++) {
if (mcuid == mcu_descriptions[i].mcuid) {
des = mcu_descriptions[i];
break;
}
}
for (int i = 0; i < arraySize(silicon_revs); i++) {
if (silicon_revs[i].revid == revid) {
des.rev = silicon_revs[i].rev;
}
}
uint8_t *endp = &revstr[max - 1];
uint8_t *strp = revstr;
while (strp < endp && *des.desc) {
*strp++ = *des.desc++;
}
if (strp < endp) {
*strp++ = ',';
}
if (strp < endp) {
*strp++ = des.rev;
}
return strp - revstr;
}
int check_silicon(void)
{
#if defined(TARGET_HW_PX4_FMU_V2) || defined(TARGET_HW_PX4_FMU_V3) || defined(TARGET_HW_PX4_FMU_V4) || defined(TARGET_HW_UVIFY_CORE)
uint32_t idcode = (*(uint32_t *)DBGMCU_IDCODE);
mcu_rev_e revid = (idcode & REVID_MASK) >> 16;
for (int i = FIRST_BAD_SILICON_OFFSET; i < arraySize(silicon_revs); i++) {
if (silicon_revs[i].revid == revid) {
return -1;
}
}
#endif
return 0;
}
uint32_t
flash_func_read_sn(uint32_t address)
{
// read a byte out from unique chip ID area
// it's 12 bytes, or 3 words.
return *(uint32_t *)(address + UDID_START);
}
void
led_on(unsigned led)
{
switch (led) {
case LED_ACTIVITY:
BOARD_LED_ON(BOARD_PORT_LEDS, BOARD_PIN_LED_ACTIVITY);
break;
case LED_BOOTLOADER:
BOARD_LED_ON(BOARD_PORT_LEDS, BOARD_PIN_LED_BOOTLOADER);
break;
}
}
void
led_off(unsigned led)
{
switch (led) {
case LED_ACTIVITY:
BOARD_LED_OFF(BOARD_PORT_LEDS, BOARD_PIN_LED_ACTIVITY);
break;
case LED_BOOTLOADER:
BOARD_LED_OFF(BOARD_PORT_LEDS, BOARD_PIN_LED_BOOTLOADER);
break;
}
}
void
led_toggle(unsigned led)
{
switch (led) {
case LED_ACTIVITY:
gpio_toggle(BOARD_PORT_LEDS, BOARD_PIN_LED_ACTIVITY);
break;
case LED_BOOTLOADER:
gpio_toggle(BOARD_PORT_LEDS, BOARD_PIN_LED_BOOTLOADER);
break;
}
}
/* we should know this, but we don't */
#ifndef SCB_CPACR
# define SCB_CPACR (*((volatile uint32_t *) (((0xE000E000UL) + 0x0D00UL) + 0x088)))
#endif
int
main(void)
{
bool try_boot = true; /* try booting before we drop to the bootloader */
unsigned timeout = BOOTLOADER_DELAY; /* if nonzero, drop out of the bootloader after this time */
/* Enable the FPU before we hit any FP instructions */
SCB_CPACR |= ((3UL << 10 * 2) | (3UL << 11 * 2)); /* set CP10 Full Access and set CP11 Full Access */
#if defined(BOARD_POWER_PIN_OUT)
/* Here we check for the app setting the POWER_DOWN_RTC_SIGNATURE
* in this case, we reset the signature and wait to die
*/
if (board_get_rtc_signature() == POWER_DOWN_RTC_SIGNATURE) {
board_set_rtc_signature(0);
while (1);
}
#endif
/* do board-specific initialisation */
board_init();
/* configure the clock for bootloader activity */
clock_init();
/*
* Check the force-bootloader register; if we find the signature there, don't
* try booting.
*/
if (board_get_rtc_signature() == BOOT_RTC_SIGNATURE) {
/*
* Don't even try to boot before dropping to the bootloader.
*/
try_boot = false;
/*
* Don't drop out of the bootloader until something has been uploaded.
*/
timeout = 0;
/*
* Clear the signature so that if someone resets us while we're
* in the bootloader we'll try to boot next time.
*/
board_set_rtc_signature(0);
}
#ifdef BOOT_DELAY_ADDRESS
{
/*
if a boot delay signature is present then delay the boot
by at least that amount of time in seconds. This allows
for an opportunity for a companion computer to load a
new firmware, while still booting fast by sending a BOOT
command
*/
uint32_t sig1 = flash_func_read_word(BOOT_DELAY_ADDRESS);
uint32_t sig2 = flash_func_read_word(BOOT_DELAY_ADDRESS + 4);
if (sig2 == BOOT_DELAY_SIGNATURE2 &&
(sig1 & 0xFFFFFF00) == (BOOT_DELAY_SIGNATURE1 & 0xFFFFFF00)) {
unsigned boot_delay = sig1 & 0xFF;
if (boot_delay <= BOOT_DELAY_MAX) {
try_boot = false;
if (timeout < boot_delay * 1000) {
timeout = boot_delay * 1000;
}
}
}
}
#endif
/*
* Check if the force-bootloader pins are strapped; if strapped,
* don't try booting.
*/
if (board_test_force_pin()) {
try_boot = false;
}
#if INTERFACE_USB
/*
* Check for USB connection - if present, don't try to boot, but set a timeout after
* which we will fall out of the bootloader.
*
* If the force-bootloader pins are tied, we will stay here until they are removed and
* we then time out.
*/
#if defined(BOARD_PORT_VBUS)
if (gpio_get(BOARD_PORT_VBUS, BOARD_PIN_VBUS) != 0) {
usb_connected = true;
/* don't try booting before we set up the bootloader */
try_boot = false;
}
#else
try_boot = false;
#endif
#endif
#if INTERFACE_USART
/*
* Check for if the USART port RX line is receiving a break command, or is being held low. If yes,
* don't try to boot, but set a timeout after
* which we will fall out of the bootloader.
*
* If the force-bootloader pins are tied, we will stay here until they are removed and
* we then time out.
*/
if (board_test_usart_receiving_break()) {
try_boot = false;
}
#endif
/* Try to boot the app if we think we should just go straight there */
if (try_boot) {
/* set the boot-to-bootloader flag so that if boot fails on reset we will stop here */
#ifdef BOARD_BOOT_FAIL_DETECT
board_set_rtc_signature(BOOT_RTC_SIGNATURE);
#endif
/* try to boot immediately */
jump_to_app();
// If it failed to boot, reset the boot signature and stay in bootloader
board_set_rtc_signature(BOOT_RTC_SIGNATURE);
/* booting failed, stay in the bootloader forever */
timeout = 0;
}
/* start the interface */
#if INTERFACE_USART
cinit(BOARD_INTERFACE_CONFIG_USART, USART);
#endif
#if INTERFACE_USB
cinit(BOARD_INTERFACE_CONFIG_USB, USB);
#endif
#if 0
// MCO1/02
gpio_mode_setup(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO8);
gpio_set_output_options(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_100MHZ, GPIO8);
gpio_set_af(GPIOA, GPIO_AF0, GPIO8);
gpio_mode_setup(GPIOC, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO9);
gpio_set_af(GPIOC, GPIO_AF0, GPIO9);
#endif
while (1) {
/* run the bootloader, come back after an app is uploaded or we time out */
bootloader(timeout);
/* if the force-bootloader pins are strapped, just loop back */
if (board_test_force_pin()) {
continue;
}
#if INTERFACE_USART
/* if the USART port RX line is still receiving a break, just loop back */
if (board_test_usart_receiving_break()) {
continue;
}
#endif
/* set the boot-to-bootloader flag so that if boot fails on reset we will stop here */
#ifdef BOARD_BOOT_FAIL_DETECT
board_set_rtc_signature(BOOT_RTC_SIGNATURE);
#endif
/* look to see if we can boot the app */
jump_to_app();
/* launching the app failed - stay in the bootloader forever */
timeout = 0;
}
}
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/px4/Bootloader.git
git@gitee.com:px4/Bootloader.git
px4
Bootloader
Bootloader
master

搜索帮助