1
0
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:
gussy 2010-03-13 17:53:42 +00:00 committed by gussy
parent 3b332c786f
commit 444a652383
9 changed files with 709 additions and 21 deletions

View File

@ -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.)
@ -83,7 +83,9 @@ DOXYGENDIR = .../Doc/Doxygen
# use file-extension c for "c-only"-files
## OPENPILOT Bootloader:
SRC = $(OPBLSYSTEM)/openpilot_bl.c
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

View 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");
}
}

View 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 */

View File

@ -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 */

View File

@ -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

View File

@ -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

View 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 */

View File

@ -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();
/* Delay system */
PIOS_DELAY_Init();
/* Only go into bootloader when the USB cable is connected */
if(PIOS_USB_CableConnected()) {
/* Delay system */
PIOS_DELAY_Init();
/* Initialise LED's */
PIOS_LED_Init();
/* Initialise the USB system */
PIOS_USB_Init(0);
/* Loop for ever */
/* Initialise COM Ports */
PIOS_COM_Init();
/* Initialise LED's */
PIOS_LED_Init();
PIOS_LED_Off(LED1);
PIOS_LED_Off(LED2);
/* 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;

View 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;
}