/** ****************************************************************************** * @addtogroup AHRS BOOTLOADER * @brief The AHRS Modules perform * * @{ * @addtogroup AHRS_BOOTLOADER_Main * @brief Main function which does the hardware dependent stuff * @{ * * * @file main.c * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. * @brief * @see The GNU Public License (GPL) Version 3 * *****************************************************************************/ /* * This program 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. * * This program 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 should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* OpenPilot Includes */ #include "ahrs_bl.h" #include "pios_opahrs_proto.h" #include "bl_fsm.h" /* lfsm_state */ #include "stm32f10x_flash.h" #define NSS_HOLD_STATE ((GPIOB->IDR & GPIO_Pin_12) ? 0 : 1) enum bootloader_status boot_status; /* Private typedef -----------------------------------------------------------*/ typedef void (*pFunction)(void); pFunction Jump_To_Application; uint32_t JumpAddress; /* Function Prototypes */ void process_spi_request(void); void jump_to_app(); uint8_t jumpFW = FALSE; uint32_t Fw_crc; /** * @brief Bootloader Main function */ int main() { uint8_t GO_dfu = false; /* Brings up System using CMSIS functions, enables the LEDs. */ PIOS_SYS_Init(); /* Delay system */ PIOS_DELAY_Init(); for (uint32_t t = 0; t < 20000000; ++t) { if (NSS_HOLD_STATE == 0) GO_dfu = TRUE; else { GO_dfu = FALSE; break; } } GO_dfu = GO_dfu;// OR with app boot request if (GO_dfu == FALSE) { jump_to_app(); } /* SPI link to master */ PIOS_SPI_Init(); lfsm_init(); boot_status = idle; Fw_crc = crc_memory_calc(); while (1) { process_spi_request(); } return 0; } static struct opahrs_msg_v0 link_tx_v0; static struct opahrs_msg_v0 link_rx_v0; static struct opahrs_msg_v0 user_tx_v0; static struct opahrs_msg_v0 user_rx_v0; void process_spi_request(void) { bool msg_to_process = FALSE; PIOS_IRQ_Disable(); /* Figure out if we're in an interesting stable state */ switch (lfsm_get_state()) { case LFSM_STATE_USER_BUSY: msg_to_process = TRUE; break; case LFSM_STATE_INACTIVE: /* Queue up a receive buffer */ lfsm_user_set_rx_v0(&user_rx_v0); lfsm_user_done(); break; case LFSM_STATE_STOPPED: /* Get things going */ lfsm_set_link_proto_v0(&link_tx_v0, &link_rx_v0); break; default: /* Not a stable state */ break; } PIOS_IRQ_Enable(); if (!msg_to_process) { /* Nothing to do */ //PIOS_COM_SendFormattedString(PIOS_COM_AUX, "."); return; } if (user_rx_v0.tail.magic != OPAHRS_MSG_MAGIC_TAIL) { return; } switch (user_rx_v0.payload.user.t) { case OPAHRS_MSG_V0_REQ_FWUP_VERIFY: opahrs_msg_v0_init_user_tx(&user_tx_v0, OPAHRS_MSG_V0_RSP_FWUP_STATUS); Fw_crc = crc_memory_calc(); lfsm_user_set_tx_v0(&user_tx_v0); user_tx_v0.payload.user.v.rsp.fwup_status.status = boot_status; break; case OPAHRS_MSG_V0_REQ_RESET: PIOS_DELAY_WaitmS(user_rx_v0.payload.user.v.req.reset.reset_delay_in_ms); PIOS_SYS_Reset(); break; case OPAHRS_MSG_V0_REQ_VERSIONS: PIOS_LED_Toggle(LED1); opahrs_msg_v0_init_user_tx(&user_tx_v0, OPAHRS_MSG_V0_RSP_VERSIONS); user_tx_v0.payload.user.v.rsp.versions.bl_version = BOOTLOADER_VERSION; user_tx_v0.payload.user.v.rsp.versions.hw_version = HW_VERSION; user_tx_v0.payload.user.v.rsp.versions.fw_version = Fw_crc; read_description( (uint8_t *) &(user_tx_v0.payload.user.v.rsp.versions.description)); lfsm_user_set_tx_v0(&user_tx_v0); break; case OPAHRS_MSG_V0_REQ_MEM_MAP: opahrs_msg_v0_init_user_tx(&user_tx_v0, OPAHRS_MSG_V0_RSP_MEM_MAP); user_tx_v0.payload.user.v.rsp.mem_map.density = HW_TYPE; user_tx_v0.payload.user.v.rsp.mem_map.rw_flags = 0;//TODO user_tx_v0.payload.user.v.rsp.mem_map.size_of_code_memory = SIZE_OF_CODE; user_tx_v0.payload.user.v.rsp.mem_map.size_of_description = SIZE_OF_DESCRIPTION; user_tx_v0.payload.user.v.rsp.mem_map.start_of_user_code = START_OF_USER_CODE; //read_description( // (uint8_t *) &(user_tx_v0.payload.user.v.rsp.versions.description)); lfsm_user_set_tx_v0(&user_tx_v0); break; case OPAHRS_MSG_V0_REQ_SERIAL: opahrs_msg_v0_init_user_tx(&user_tx_v0, OPAHRS_MSG_V0_RSP_SERIAL); PIOS_SYS_SerialNumberGet( (char *) &(user_tx_v0.payload.user.v.rsp.serial.serial_bcd)); lfsm_user_set_tx_v0(&user_tx_v0); //PIOS_LED_Toggle(LED1); break; case OPAHRS_MSG_V0_REQ_FWUP_DATA: opahrs_msg_v0_init_user_tx(&user_tx_v0, OPAHRS_MSG_V0_REQ_FWUP_DATA); if (!(user_rx_v0.payload.user.v.req.fwup_data.adress < START_OF_USER_CODE)) { if (FLASH_ProgramWord( user_rx_v0.payload.user.v.req.fwup_data.adress, user_rx_v0.payload.user.v.req.fwup_data.data) != FLASH_COMPLETE) { boot_status = write_error; } } else { boot_status = outside_dev_capabilities; } user_tx_v0.payload.user.v.rsp.fwup_status.status = boot_status; lfsm_user_set_tx_v0(&user_tx_v0); break; case OPAHRS_MSG_V0_REQ_FWUP_START: opahrs_msg_v0_init_user_tx(&user_tx_v0, OPAHRS_MSG_V0_RSP_FWUP_STATUS); if (FLASH_Start() == TRUE) { boot_status = started; } else { boot_status = start_failed; break; } user_tx_v0.payload.user.v.rsp.fwup_status.status = boot_status; lfsm_user_set_tx_v0(&user_tx_v0); break; case OPAHRS_MSG_V0_REQ_BOOT: PIOS_DELAY_WaitmS(user_rx_v0.payload.user.v.req.boot.boot_delay_in_ms); FLASH_Lock(); jump_to_app(); break; default: break; } /* Finished processing the received message, requeue it */ lfsm_user_set_rx_v0(&user_rx_v0); lfsm_user_done(); } void jump_to_app() { if (((*(__IO uint32_t*) START_OF_USER_CODE) & 0x2FFE0000) == 0x20000000) { /* Jump to user application */ FLASH_Lock(); RCC_APB2PeriphResetCmd(0xffffffff, ENABLE); RCC_APB1PeriphResetCmd(0xffffffff, ENABLE); RCC_APB2PeriphResetCmd(0xffffffff, DISABLE); RCC_APB1PeriphResetCmd(0xffffffff, DISABLE); //_SetCNTR(0); // clear interrupt mask //_SetISTR(0); // clear all requests JumpAddress = *(__IO uint32_t*) (START_OF_USER_CODE + 4); Jump_To_Application = (pFunction) JumpAddress; /* Initialize user application's Stack Pointer */ __set_MSP(*(__IO uint32_t*) START_OF_USER_CODE); Jump_To_Application(); } else { boot_status = jump_failed; return; } }