mirror of
https://bitbucket.org/librepilot/librepilot.git
synced 2025-01-18 03:52:11 +01:00
OP-21: Bootloader mostly complete. Working and tested.
git-svn-id: svn://svn.openpilot.org/OpenPilot/trunk@299 ebee16cc-31ac-478f-84a7-5cbb03baadba
This commit is contained in:
parent
3b332c786f
commit
444a652383
@ -51,7 +51,7 @@ USE_THUMB_MODE = YES
|
||||
# - BOARD just passed as define (optional)
|
||||
MCU = cortex-m3
|
||||
CHIP = STM32F103RET
|
||||
MODEL = HD_BL
|
||||
MODEL = HD
|
||||
BOARD = STM3210E_OP
|
||||
|
||||
# Directory for output files (lst, obj, dep, elf, sym, map, hex, bin etc.)
|
||||
@ -84,6 +84,8 @@ DOXYGENDIR = .../Doc/Doxygen
|
||||
|
||||
## OPENPILOT Bootloader:
|
||||
SRC = $(OPBLSYSTEM)/openpilot_bl.c
|
||||
SRC += $(OPBLSYSTEM)/bootloader.c
|
||||
SRC += $(OPBLSYSTEM)/ymodem.c
|
||||
|
||||
## PIOS Hardware (STM32F10x)
|
||||
SRC += $(PIOSSTM32F10X)/pios_sys.c
|
||||
@ -91,8 +93,8 @@ SRC += $(PIOSSTM32F10X)/pios_led.c
|
||||
SRC += $(PIOSSTM32F10X)/pios_usart.c
|
||||
SRC += $(PIOSSTM32F10X)/pios_delay.c
|
||||
SRC += $(PIOSSTM32F10X)/pios_irq.c
|
||||
#SRC += $(PIOSSTM32F10X)/pios_usb.c
|
||||
#SRC += $(PIOSSTM32F10X)/pios_usb_hid.c
|
||||
SRC += $(PIOSSTM32F10X)/pios_usb.c
|
||||
SRC += $(PIOSSTM32F10X)/pios_usb_hid.c
|
||||
|
||||
## PIOS Hardware (Common)
|
||||
SRC += $(PIOSCOMMON)/pios_com.c
|
||||
@ -105,16 +107,18 @@ SRC += $(CMSISDIR)/system_stm32f10x.c
|
||||
## Used parts of the STM-Library
|
||||
SRC += $(STMSPDSRCDIR)/stm32f10x_gpio.c
|
||||
SRC += $(STMSPDSRCDIR)/stm32f10x_rcc.c
|
||||
SRC += $(STMSPDSRCDIR)/stm32f10x_wwdg.c
|
||||
SRC += $(STMSPDSRCDIR)/stm32f10x_tim.c
|
||||
SRC += $(STMSPDSRCDIR)/stm32f10x_flash.c
|
||||
SRC += $(STMSPDSRCDIR)/stm32f10x_usart.c
|
||||
SRC += $(STMSPDSRCDIR)/misc.c
|
||||
|
||||
## STM32 USB Library
|
||||
#SRC += $(STMUSBSRCDIR)/usb_core.c
|
||||
#SRC += $(STMUSBSRCDIR)/usb_init.c
|
||||
#SRC += $(STMUSBSRCDIR)/usb_int.c
|
||||
#SRC += $(STMUSBSRCDIR)/usb_mem.c
|
||||
3SRC += $(STMUSBSRCDIR)/usb_regs.c
|
||||
SRC += $(STMUSBSRCDIR)/usb_core.c
|
||||
SRC += $(STMUSBSRCDIR)/usb_init.c
|
||||
SRC += $(STMUSBSRCDIR)/usb_int.c
|
||||
SRC += $(STMUSBSRCDIR)/usb_mem.c
|
||||
SRC += $(STMUSBSRCDIR)/usb_regs.c
|
||||
|
||||
# List C source files here which must be compiled in ARM-Mode (no -mthumb).
|
||||
# use file-extension c for "c-only"-files
|
||||
|
205
flight/Bootloaders/OpenPilot/bootloader.c
Normal file
205
flight/Bootloaders/OpenPilot/bootloader.c
Normal file
@ -0,0 +1,205 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file bootloader.h
|
||||
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||
* @brief Bootloader functions header
|
||||
* @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
|
||||
*/
|
||||
|
||||
/* Includes */
|
||||
#include "openpilot_bl.h"
|
||||
|
||||
/* Local Functions */
|
||||
static void Serial_PutString(uint8_t *s);
|
||||
static void FLASH_DisableWriteProtectionPages(void);
|
||||
static void SerialDownload(void);
|
||||
|
||||
/* Global Variables */
|
||||
extern uint32_t FlashDestination;
|
||||
extern uint8_t file_name[FILE_NAME_LENGTH];
|
||||
|
||||
/* Local variables */
|
||||
uint32_t BlockNbr = 0, UserMemoryMask = 0;
|
||||
bool FlashProtection = FALSE;
|
||||
uint8_t tab_1024[1024] = { 0 };
|
||||
|
||||
/**
|
||||
* Main bootloader function
|
||||
*/
|
||||
void StartBootloader(void)
|
||||
{
|
||||
uint8_t key = 0;
|
||||
|
||||
/* Get the number of block (4 or 2 pages) from where the user program will be loaded */
|
||||
BlockNbr = (FlashDestination - 0x08000000) >> 12;
|
||||
|
||||
/* Compute the mask to test if the Flash memory, where the user program will be loaded, is write protected */
|
||||
if(BlockNbr < 62) {
|
||||
UserMemoryMask = ((uint32_t) ~((1 << BlockNbr) - 1));
|
||||
} else {
|
||||
UserMemoryMask = ((uint32_t) 0x80000000);
|
||||
}
|
||||
|
||||
/* Test if any page of Flash memory where program user will be loaded is write protected */
|
||||
if((FLASH_GetWriteProtectionOptionByte() & UserMemoryMask) != UserMemoryMask) {
|
||||
FlashProtection = TRUE;
|
||||
SerialPutString(" Download Image To the STM32F10x Internal Flash ------- 1\r\n");
|
||||
SerialPutString(" Execute The New Program ------------------------------ 2\r\n");
|
||||
SerialPutString(" Disable the write protection ------------------------- 3\r\n");
|
||||
} else {
|
||||
FlashProtection = FALSE;
|
||||
SerialPutString(" Download Image To the STM32F10x Internal Flash ------- 1\r\n");
|
||||
SerialPutString(" Execute The New Program ------------------------------ 2\r\n");
|
||||
}
|
||||
|
||||
/* Loop through 1mS check for specified time */
|
||||
for(int32_t i = 0; i < OPBL_MAGIC_TIMEOUT; i++) {
|
||||
uint16_t start = PIOS_DELAY_TIMER->CNT;
|
||||
|
||||
/* Check for magic character for 1mS */
|
||||
while((volatile uint16_t)(PIOS_DELAY_TIMER->CNT - start) <= 1000) {
|
||||
/* Check to see if there is anything on the receiving buffer */
|
||||
if(PIOS_COM_ReceiveBufferUsed(OPBL_COM_PORT) > 0) {
|
||||
key = PIOS_COM_ReceiveBuffer(OPBL_COM_PORT);
|
||||
if(key == 0x31) {
|
||||
/* Download user application in the Flash */
|
||||
SerialDownload();
|
||||
return;
|
||||
} else if ((key == 0x33) && (FlashProtection == TRUE)) {
|
||||
/* Disable the write protection of desired pages */
|
||||
FLASH_DisableWriteProtectionPages();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the number of pages
|
||||
* \param[in] Size The image size
|
||||
* \return The number of pages
|
||||
*/
|
||||
uint32_t FLASH_PagesMask(__IO uint32_t Size)
|
||||
{
|
||||
uint32_t pagenumber = 0x0;
|
||||
uint32_t size = Size;
|
||||
|
||||
if((size % PAGE_SIZE) != 0) {
|
||||
pagenumber = (size / PAGE_SIZE) + 1;
|
||||
} else {
|
||||
pagenumber = size / PAGE_SIZE;
|
||||
}
|
||||
return pagenumber;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Print a string on the HyperTerminal
|
||||
* \param[in] s The string to be printed
|
||||
*/
|
||||
static void Serial_PutString(uint8_t *s)
|
||||
{
|
||||
while(*s != '\0') {
|
||||
PIOS_COM_SendChar(OPBL_COM_PORT, *s);
|
||||
s++;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable the write protection of desired pages
|
||||
*/
|
||||
static void FLASH_DisableWriteProtectionPages(void)
|
||||
{
|
||||
uint32_t useroptionbyte = 0, WRPR = 0;
|
||||
uint16_t var1 = OB_IWDG_SW, var2 = OB_STOP_NoRST, var3 = OB_STDBY_NoRST;
|
||||
FLASH_Status status = FLASH_BUSY;
|
||||
|
||||
WRPR = FLASH_GetWriteProtectionOptionByte();
|
||||
|
||||
/* Test if user memory is write protected */
|
||||
if((WRPR & UserMemoryMask) != UserMemoryMask) {
|
||||
useroptionbyte = FLASH_GetUserOptionByte();
|
||||
|
||||
UserMemoryMask |= WRPR;
|
||||
|
||||
status = FLASH_EraseOptionBytes();
|
||||
|
||||
if(UserMemoryMask != 0xFFFFFFFF) {
|
||||
status = FLASH_EnableWriteProtection(
|
||||
(uint32_t) ~UserMemoryMask);
|
||||
}
|
||||
|
||||
/* Test if user Option Bytes are programmed */
|
||||
if((useroptionbyte & 0x07) != 0x07) { /* Restore user Option Bytes */
|
||||
if((useroptionbyte & 0x01) == 0x0) {
|
||||
var1 = OB_IWDG_HW;
|
||||
}
|
||||
if((useroptionbyte & 0x02) == 0x0) {
|
||||
var2 = OB_STOP_RST;
|
||||
}
|
||||
if((useroptionbyte & 0x04) == 0x0) {
|
||||
var3 = OB_STDBY_RST;
|
||||
}
|
||||
|
||||
FLASH_UserOptionByteConfig(var1, var2, var3);
|
||||
}
|
||||
|
||||
if(status == FLASH_COMPLETE) {
|
||||
SerialPutString("Write Protection disabled...\r\n");
|
||||
|
||||
SerialPutString("...and a System Reset will be generated to re-load the new option bytes\r\n");
|
||||
|
||||
/* Enable WWDG clock */
|
||||
RCC_APB1PeriphClockCmd(RCC_APB1Periph_WWDG, ENABLE);
|
||||
|
||||
/* Generate a system Reset to re-load the new option bytes: enable WWDG and set
|
||||
counter value to 0x4F, as T6 bit is cleared this will generate a WWDG reset */
|
||||
WWDG_Enable(0x4F);
|
||||
} else {
|
||||
SerialPutString("Error: Flash write unprotection failed...\r\n");
|
||||
}
|
||||
} else {
|
||||
SerialPutString("Flash memory not write protected\r\n");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Download and program the binary file
|
||||
*/
|
||||
static void SerialDownload(void)
|
||||
{
|
||||
int32_t Size = 0;
|
||||
|
||||
SerialPutString("Waiting for the file to be sent ... (press 'a' to abort)\n\r");
|
||||
Size = Ymodem_Receive(&tab_1024[0]);
|
||||
if(Size > 0) {
|
||||
SerialPutString("\n\n\r Programming Completed Successfully!\n\r--------------------------------\r\n Name: ");
|
||||
} else if(Size == -1) {
|
||||
SerialPutString("\n\n\rThe image size is higher than the allowed space memory!\n\r");
|
||||
} else if(Size == -2) {
|
||||
SerialPutString("\n\n\rVerification failed!\n\r");
|
||||
} else if(Size == -3) {
|
||||
SerialPutString("\r\n\nAborted by user.\n\r");
|
||||
} else {
|
||||
SerialPutString("\n\rFailed to receive the file!\n\r");
|
||||
}
|
||||
}
|
45
flight/Bootloaders/OpenPilot/inc/bootloader.h
Normal file
45
flight/Bootloaders/OpenPilot/inc/bootloader.h
Normal file
@ -0,0 +1,45 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file bootloader.h
|
||||
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||
* @brief Bootloader functions header
|
||||
* @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
|
||||
*/
|
||||
|
||||
#ifndef BOOTLOADER_H
|
||||
#define BOOTLOADER_H
|
||||
|
||||
/* Global Types */
|
||||
typedef void (*pFunction)(void);
|
||||
|
||||
/* Global Defines */
|
||||
#define CMD_STRING_SIZE 128
|
||||
#define ApplicationAddress 0x8008000
|
||||
#define PAGE_SIZE (0x800)
|
||||
#define FLASH_SIZE (0x80000) /* 512K */
|
||||
|
||||
/* Global macros */
|
||||
#define SerialPutString(x) Serial_PutString((uint8_t*)(x))
|
||||
|
||||
/* Public Functions */
|
||||
extern void StartBootloader(void);
|
||||
extern uint32_t FLASH_PagesMask(volatile uint32_t Size);
|
||||
|
||||
#endif /* BOOTLOADER_H */
|
@ -27,8 +27,12 @@
|
||||
#ifndef OPENPILOT_BL_H
|
||||
#define OPENPILOT_BL_H
|
||||
|
||||
#define OPBL_MAGIC_TIMEOUT 2000
|
||||
#define OPBL_COM_PORT COM_DEBUG_USART
|
||||
|
||||
/* PIOS Includes */
|
||||
#include <pios.h>
|
||||
#include "bootloader.h"
|
||||
#include "ymodem.h"
|
||||
|
||||
#endif /* OPENPILOT_BL_H */
|
||||
|
@ -27,6 +27,7 @@
|
||||
#ifndef PIOS_BOARD_H
|
||||
#define PIOS_BOARD_H
|
||||
|
||||
|
||||
//------------------------
|
||||
// PIOS_LED
|
||||
//------------------------
|
||||
@ -54,7 +55,7 @@
|
||||
#define PIOS_USART1_IRQHANDLER_FUNC void USART2_IRQHandler(void)
|
||||
#define PIOS_USART1_CLK_FUNC RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE)
|
||||
#define PIOS_USART1_NVIC_PRIO PIOS_IRQ_PRIO_HIGHEST
|
||||
#define PIOS_USART1_BAUDRATE 57600
|
||||
#define PIOS_USART1_BAUDRATE 115200
|
||||
|
||||
//-------------------------
|
||||
// PIOS_USART2 (GPS)
|
||||
@ -90,8 +91,8 @@
|
||||
// PIOS_USART
|
||||
//-------------------------
|
||||
#define PIOS_USART_NUM 1
|
||||
#define PIOS_USART_RX_BUFFER_SIZE 1024
|
||||
#define PIOS_USART_TX_BUFFER_SIZE 256
|
||||
#define PIOS_USART_RX_BUFFER_SIZE 128
|
||||
#define PIOS_USART_TX_BUFFER_SIZE 128
|
||||
#define PIOS_COM_DEBUG_PORT USART_1
|
||||
|
||||
//-------------------------
|
||||
@ -101,10 +102,11 @@
|
||||
#define PIOS_DELAY_TIMER_RCC_FUNC RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE)
|
||||
|
||||
//-------------------------
|
||||
// Master Clock
|
||||
// System Settings
|
||||
//-------------------------
|
||||
#define PIOS_MASTER_CLOCK 72000000
|
||||
#define PIOS_PERIPHERAL_CLOCK (PIOS_MASTER_CLOCK / 2)
|
||||
#define PIOS_NVIC_VECTTAB_FLASH ((uint32_t)0x08000000)
|
||||
|
||||
//-------------------------
|
||||
// Interrupt Priorities
|
||||
|
@ -41,8 +41,8 @@
|
||||
#define PIOS_INCLUDE_SYS
|
||||
#define PIOS_INCLUDE_USART
|
||||
//#define PIOS_INCLUDE_USB_COM
|
||||
//#define PIOS_INCLUDE_USB_HID
|
||||
//#define PIOS_INCLUDE_USB
|
||||
#define PIOS_INCLUDE_USB_HID
|
||||
#define PIOS_INCLUDE_USB
|
||||
//#define PIOS_INCLUDE_BMP085
|
||||
#define PIOS_INCLUDE_COM
|
||||
//#define PIOS_INCLUDE_SDCARD
|
||||
|
73
flight/Bootloaders/OpenPilot/inc/ymodem.h
Normal file
73
flight/Bootloaders/OpenPilot/inc/ymodem.h
Normal file
@ -0,0 +1,73 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file ymodem.c
|
||||
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||
* @brief YModem functions header
|
||||
* @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
|
||||
*/
|
||||
|
||||
#ifndef YMODEM_H
|
||||
#define YMODEM_H
|
||||
|
||||
/* Global Defines */
|
||||
#define PACKET_SEQNO_INDEX (1)
|
||||
#define PACKET_SEQNO_COMP_INDEX (2)
|
||||
|
||||
#define PACKET_HEADER (3)
|
||||
#define PACKET_TRAILER (2)
|
||||
#define PACKET_OVERHEAD (PACKET_HEADER + PACKET_TRAILER)
|
||||
#define PACKET_SIZE (128)
|
||||
#define PACKET_1K_SIZE (1024)
|
||||
|
||||
#define FILE_NAME_LENGTH (256)
|
||||
#define FILE_SIZE_LENGTH (16)
|
||||
|
||||
#define SOH (0x01) /* start of 128-byte data packet */
|
||||
#define STX (0x02) /* start of 1024-byte data packet */
|
||||
#define EOT (0x04) /* end of transmission */
|
||||
#define ACK (0x06) /* acknowledge */
|
||||
#define NAK (0x15) /* negative acknowledge */
|
||||
#define CA (0x18) /* two of these in succession aborts transfer */
|
||||
#define CRC16 (0x43) /* 'C' == 0x43, request 16-bit CRC */
|
||||
|
||||
#define ABORT1 (0x41) /* 'A' == 0x41, abort by user */
|
||||
#define ABORT2 (0x61) /* 'a' == 0x61, abort by user */
|
||||
|
||||
#define NAK_TIMEOUT (0x100000)
|
||||
#define MAX_ERRORS (5)
|
||||
|
||||
/* Global Macros */
|
||||
#define IS_AF(c) ((c >= 'A') && (c <= 'F'))
|
||||
#define IS_af(c) ((c >= 'a') && (c <= 'f'))
|
||||
#define IS_09(c) ((c >= '0') && (c <= '9'))
|
||||
#define ISVALIDHEX(c) IS_AF(c) || IS_af(c) || IS_09(c)
|
||||
#define ISVALIDDEC(c) IS_09(c)
|
||||
#define CONVERTDEC(c) (c - '0')
|
||||
|
||||
#define CONVERTHEX_alpha(c) (IS_AF(c) ? (c - 'A'+10) : (c - 'a'+10))
|
||||
#define CONVERTHEX(c) (IS_09(c) ? (c - '0') : CONVERTHEX_alpha(c))
|
||||
|
||||
/* Global Variables */
|
||||
extern uint8_t tab_1024[1024];
|
||||
|
||||
/* Public Functions */
|
||||
extern int32_t Ymodem_Receive(uint8_t *buf);
|
||||
|
||||
#endif /* YMODEM_H */
|
@ -28,6 +28,8 @@
|
||||
#include "openpilot_bl.h"
|
||||
|
||||
/* Global Variables */
|
||||
static pFunction Jump_To_Application;
|
||||
static uint32_t JumpAddress;
|
||||
|
||||
/* Local Variables */
|
||||
|
||||
@ -41,19 +43,47 @@ int main()
|
||||
/* Brings up System using CMSIS functions, enables the LEDs. */
|
||||
PIOS_SYS_Init();
|
||||
|
||||
/* Only go into bootloader when the USB cable is connected */
|
||||
if(PIOS_USB_CableConnected()) {
|
||||
/* Delay system */
|
||||
PIOS_DELAY_Init();
|
||||
|
||||
/* Initialise the USB system */
|
||||
PIOS_USB_Init(0);
|
||||
|
||||
/* Initialise COM Ports */
|
||||
PIOS_COM_Init();
|
||||
|
||||
/* Initialise LED's */
|
||||
PIOS_LED_Init();
|
||||
PIOS_LED_Off(LED1);
|
||||
PIOS_LED_Off(LED2);
|
||||
|
||||
/* Loop for ever */
|
||||
/* Flash unlock */
|
||||
FLASH_Unlock();
|
||||
|
||||
/* Execute the IAP driver in order to re-program the Flash */
|
||||
StartBootloader();
|
||||
}
|
||||
|
||||
/* Test if user code is programmed starting from address "ApplicationAddress" */
|
||||
if(((*(volatile uint32_t*) ApplicationAddress) & 0x2FFE0000) == 0x20000000) {
|
||||
/* Jump to user application */
|
||||
JumpAddress = *(volatile uint32_t*) (ApplicationAddress + 4);
|
||||
Jump_To_Application = (pFunction) JumpAddress;
|
||||
|
||||
/* Initialise user application's Stack Pointer */
|
||||
__set_MSP(*(volatile uint32_t*) ApplicationAddress);
|
||||
Jump_To_Application();
|
||||
}
|
||||
|
||||
/* Loop for ever if no application code is not programmed */
|
||||
PIOS_LED_Off(LED1);
|
||||
PIOS_LED_Off(LED2);
|
||||
for(;;) {
|
||||
PIOS_LED_Toggle(LED1);
|
||||
PIOS_LED_Toggle(LED2);
|
||||
PIOS_DELAY_WaitmS(200);
|
||||
PIOS_DELAY_WaitmS(50);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
325
flight/Bootloaders/OpenPilot/ymodem.c
Normal file
325
flight/Bootloaders/OpenPilot/ymodem.c
Normal file
@ -0,0 +1,325 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file ymodem.c
|
||||
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||
* @brief YModem functions
|
||||
* @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
|
||||
*/
|
||||
|
||||
/* Includes */
|
||||
#include "openpilot_bl.h"
|
||||
|
||||
/* Local functions */
|
||||
static int32_t Receive_Byte(uint8_t *c, uint32_t timeout);
|
||||
static uint32_t Send_Byte(uint8_t c);
|
||||
static int32_t Receive_Packet(uint8_t *data, int32_t *length, uint32_t timeout);
|
||||
static uint32_t Str2Int(uint8_t *inputstr, int32_t *intnum);
|
||||
|
||||
/* Global variables */
|
||||
uint32_t FlashDestination = ApplicationAddress; /* Flash user program offset */
|
||||
uint8_t tab_1024[1024];
|
||||
|
||||
/* Local variables */
|
||||
static uint8_t file_name[FILE_NAME_LENGTH];
|
||||
static uint16_t PageSize = PAGE_SIZE;
|
||||
static uint32_t EraseCounter = 0x0;
|
||||
static uint32_t NbrOfPage = 0;
|
||||
static FLASH_Status FLASHStatus = FLASH_COMPLETE;
|
||||
static uint32_t RamSource;
|
||||
|
||||
|
||||
/**
|
||||
* Receive a file using the ymodem protocol
|
||||
* \param[in] buf Address of the first byte
|
||||
* \return The size of the file
|
||||
*/
|
||||
int32_t Ymodem_Receive(uint8_t *buf)
|
||||
{
|
||||
uint8_t packet_data[PACKET_1K_SIZE + PACKET_OVERHEAD], file_size[FILE_SIZE_LENGTH], *file_ptr, *buf_ptr;
|
||||
int32_t i, j, packet_length, session_done, file_done, packets_received, errors, session_begin, size = 0;
|
||||
|
||||
/* Initialise FlashDestination variable */
|
||||
FlashDestination = ApplicationAddress;
|
||||
|
||||
for(session_done = 0, errors = 0, session_begin = 0;;) {
|
||||
for(packets_received = 0, file_done = 0, buf_ptr = buf;;) {
|
||||
switch(Receive_Packet(packet_data, &packet_length,
|
||||
NAK_TIMEOUT)) {
|
||||
case 0:
|
||||
errors = 0;
|
||||
switch(packet_length) {
|
||||
/* Abort by sender */
|
||||
case -1:
|
||||
Send_Byte(ACK);
|
||||
return 0;
|
||||
/* End of transmission */
|
||||
case 0:
|
||||
Send_Byte(ACK);
|
||||
file_done = 1;
|
||||
break;
|
||||
/* Normal packet */
|
||||
default:
|
||||
if((packet_data[PACKET_SEQNO_INDEX] & 0xff) != (packets_received & 0xff)) {
|
||||
Send_Byte(NAK);
|
||||
} else {
|
||||
if(packets_received == 0) {/* Filename packet */
|
||||
if(packet_data[PACKET_HEADER] != 0) {/* Filename packet has valid data */
|
||||
for(i = 0, file_ptr = packet_data + PACKET_HEADER; (*file_ptr != 0) && (i < FILE_NAME_LENGTH);) {
|
||||
file_name[i++] = *file_ptr++;
|
||||
}
|
||||
file_name[i++] = '\0';
|
||||
for(i = 0, file_ptr++; (*file_ptr != ' ') & (i < FILE_SIZE_LENGTH);) {
|
||||
file_size[i++] = *file_ptr++;
|
||||
}
|
||||
file_size[i++] = '\0';
|
||||
Str2Int(file_size, &size);
|
||||
/* Test the size of the image to be sent */
|
||||
/* Image size is greater than Flash size */
|
||||
if(size > (FLASH_SIZE - 1)) {
|
||||
/* End session */
|
||||
Send_Byte(CA);
|
||||
Send_Byte(CA);
|
||||
return -1;
|
||||
}
|
||||
/* Erase the needed pages where the user application will be loaded */
|
||||
/* Define the number of page to be erased */
|
||||
NbrOfPage = FLASH_PagesMask(size);
|
||||
/* Erase the FLASH pages */
|
||||
for(EraseCounter = 0; (EraseCounter < NbrOfPage) && (FLASHStatus == FLASH_COMPLETE); EraseCounter++) {
|
||||
FLASHStatus = FLASH_ErasePage(FlashDestination + (PageSize * EraseCounter));
|
||||
}
|
||||
Send_Byte(ACK);
|
||||
Send_Byte(CRC16);
|
||||
}
|
||||
/* Filename packet is empty, end session */
|
||||
else {
|
||||
Send_Byte(ACK);
|
||||
file_done = 1;
|
||||
session_done = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* Data packet */
|
||||
else {
|
||||
memcpy(buf_ptr, packet_data + PACKET_HEADER, packet_length);
|
||||
RamSource = (uint32_t) buf;
|
||||
for(j = 0; (j < packet_length) && (FlashDestination < ApplicationAddress + size); j += 4) {
|
||||
/* Program the data received into STM32F10x Flash */
|
||||
FLASH_ProgramWord(FlashDestination, *(uint32_t*) RamSource);
|
||||
if(*(uint32_t*) FlashDestination != *(uint32_t*) RamSource) {
|
||||
/* End session */
|
||||
Send_Byte(CA);
|
||||
Send_Byte(CA);
|
||||
return -2;
|
||||
}
|
||||
FlashDestination += 4;
|
||||
RamSource += 4;
|
||||
}
|
||||
Send_Byte(ACK);
|
||||
}
|
||||
packets_received++;
|
||||
session_begin = 1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
Send_Byte(CA);
|
||||
Send_Byte(CA);
|
||||
return -3;
|
||||
default:
|
||||
if(session_begin > 0) {
|
||||
errors++;
|
||||
}
|
||||
if(errors > MAX_ERRORS) {
|
||||
Send_Byte(CA);
|
||||
Send_Byte(CA);
|
||||
return 0;
|
||||
}
|
||||
Send_Byte(CRC16);
|
||||
break;
|
||||
}
|
||||
if(file_done != 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(session_done != 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return (int32_t) size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Receive byte from sender
|
||||
* \param[in] c Character
|
||||
* \param[in] timeout Timeout
|
||||
* \return 0 Byte received
|
||||
* \return -1 Timeout
|
||||
*/
|
||||
static int32_t Receive_Byte(uint8_t *c, uint32_t timeout)
|
||||
{
|
||||
while(timeout-- > 0) {
|
||||
if(PIOS_COM_ReceiveBufferUsed(OPBL_COM_PORT) > 0) {
|
||||
*c = PIOS_COM_ReceiveBuffer(OPBL_COM_PORT);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a byte
|
||||
* \param[in] c Character
|
||||
* \return 0 Byte sent
|
||||
*/
|
||||
static uint32_t Send_Byte(uint8_t c)
|
||||
{
|
||||
PIOS_COM_SendChar(OPBL_COM_PORT, c);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Receive a packet from sender
|
||||
* \param[in] data
|
||||
* \param[in] length
|
||||
* \param[in] timeout
|
||||
* 0 end of transmission
|
||||
* -1 abort by sender
|
||||
* >0 packet length
|
||||
* \return 0 normally return
|
||||
* \return -1 timeout or packet error
|
||||
* \return 1 abort by user
|
||||
*/
|
||||
static int32_t Receive_Packet(uint8_t *data, int32_t *length, uint32_t timeout)
|
||||
{
|
||||
uint16_t i, packet_size;
|
||||
uint8_t c;
|
||||
*length = 0;
|
||||
if(Receive_Byte(&c, timeout) != 0) {
|
||||
return -1;
|
||||
}
|
||||
switch(c) {
|
||||
case SOH:
|
||||
packet_size = PACKET_SIZE;
|
||||
break;
|
||||
case STX:
|
||||
packet_size = PACKET_1K_SIZE;
|
||||
break;
|
||||
case EOT:
|
||||
return 0;
|
||||
case CA:
|
||||
if((Receive_Byte(&c, timeout) == 0) && (c == CA)) {
|
||||
*length = -1;
|
||||
return 0;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
case ABORT1:
|
||||
case ABORT2:
|
||||
return 1;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
*data = c;
|
||||
for(i = 1; i < (packet_size + PACKET_OVERHEAD); i++) {
|
||||
if(Receive_Byte(data + i, timeout) != 0) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
if(data[PACKET_SEQNO_INDEX] != ((data[PACKET_SEQNO_COMP_INDEX] ^ 0xff)
|
||||
& 0xff)) {
|
||||
return -1;
|
||||
}
|
||||
*length = packet_size;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a string to an integer
|
||||
* \param[in] inputstr The string to be converted
|
||||
* \param[in] intnum The intger value
|
||||
* \return 1 Correct
|
||||
* \return 0 Error
|
||||
*/
|
||||
static uint32_t Str2Int(uint8_t *inputstr, int32_t *intnum)
|
||||
{
|
||||
uint32_t i = 0, res = 0;
|
||||
uint32_t val = 0;
|
||||
|
||||
if(inputstr[0] == '0' && (inputstr[1] == 'x' || inputstr[1] == 'X')) {
|
||||
if(inputstr[2] == '\0') {
|
||||
return 0;
|
||||
}
|
||||
for(i = 2; i < 11; i++) {
|
||||
if(inputstr[i] == '\0') {
|
||||
*intnum = val;
|
||||
/* return 1; */
|
||||
res = 1;
|
||||
break;
|
||||
}
|
||||
if(ISVALIDHEX(inputstr[i])) {
|
||||
val = (val << 4) + CONVERTHEX(inputstr[i]);
|
||||
} else {
|
||||
/* return 0, Invalid input */
|
||||
res = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* over 8 digit hex --invalid */
|
||||
if(i >= 11) {
|
||||
res = 0;
|
||||
}
|
||||
} else /* max 10-digit decimal input */
|
||||
{
|
||||
for(i = 0; i < 11; i++) {
|
||||
if(inputstr[i] == '\0') {
|
||||
*intnum = val;
|
||||
/* return 1 */
|
||||
res = 1;
|
||||
break;
|
||||
} else if((inputstr[i] == 'k' || inputstr[i] == 'K')
|
||||
&& (i > 0)) {
|
||||
val = val << 10;
|
||||
*intnum = val;
|
||||
res = 1;
|
||||
break;
|
||||
} else if((inputstr[i] == 'm' || inputstr[i] == 'M')
|
||||
&& (i > 0)) {
|
||||
val = val << 20;
|
||||
*intnum = val;
|
||||
res = 1;
|
||||
break;
|
||||
} else if(ISVALIDDEC(inputstr[i])) {
|
||||
val = val * 10 + CONVERTDEC(inputstr[i]);
|
||||
} else {
|
||||
/* return 0, Invalid input */
|
||||
res = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* Over 10 digit decimal --invalid */
|
||||
if(i >= 11) {
|
||||
res = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user