forked from xuos/xiuos
Upgrading binary packages by iap on xidatong-arm32
This commit is contained in:
parent
d615793063
commit
85105cb65d
|
@ -6,6 +6,9 @@ endif
|
|||
|
||||
ifeq ($(CONFIG_BSP_USING_OTA),y)
|
||||
SRC_FILES += fsl_romapi.c flash.c mcuboot.c
|
||||
ifeq ($(CONFIG_MCUBOOT_BOOTLOADER),y)
|
||||
SRC_FILES += common.c ymodem.c
|
||||
endif
|
||||
endif
|
||||
|
||||
include $(KERNEL_ROOT)/compiler.mk
|
||||
|
|
|
@ -0,0 +1,275 @@
|
|||
|
||||
/*
|
||||
* Copyright (c) 2020 AIIT XUOS Lab
|
||||
* XiUOS is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
* See the Mulan PSL v2 for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file: common.c
|
||||
* @brief: file common.c
|
||||
* @version: 1.0
|
||||
* @author: AIIT XUOS Lab
|
||||
* @date: 2023/3/24
|
||||
*/
|
||||
|
||||
|
||||
#include "common.h"
|
||||
|
||||
/**
|
||||
* @brief Convert an Integer to a string
|
||||
* @param str: The string
|
||||
* @param intnum: The intger to be converted
|
||||
* @retval None
|
||||
*/
|
||||
void Int2Str(uint8_t* str, int32_t intnum)
|
||||
{
|
||||
uint32_t i, Div = 1000000000, j = 0, Status = 0;
|
||||
|
||||
for (i = 0; i < 10; i++)
|
||||
{
|
||||
str[j++] = (intnum / Div) + 48;
|
||||
|
||||
intnum = intnum % Div;
|
||||
Div /= 10;
|
||||
if ((str[j-1] == '0') & (Status == 0))
|
||||
{
|
||||
j = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
Status++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Convert a string to an integer
|
||||
* @param inputstr: The string to be converted
|
||||
* @param intnum: The intger value
|
||||
* @retval 1: Correct
|
||||
* 0: Error
|
||||
*/
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get an integer from the HyperTerminal
|
||||
* @param num: The inetger
|
||||
* @retval 1: Correct
|
||||
* 0: Error
|
||||
*/
|
||||
uint32_t GetIntegerInput(int32_t * num)
|
||||
{
|
||||
uint8_t inputstr[16];
|
||||
|
||||
while (1)
|
||||
{
|
||||
GetInputString(inputstr);
|
||||
if (inputstr[0] == '\0') continue;
|
||||
if ((inputstr[0] == 'a' || inputstr[0] == 'A') && inputstr[1] == '\0')
|
||||
{
|
||||
Serial_PutString("User Cancelled \r\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (Str2Int(inputstr, num) == 0)
|
||||
{
|
||||
Serial_PutString("Error, Input again: \r\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Test to see if a key has been pressed on the HyperTerminal
|
||||
* @param key: The key pressed
|
||||
* @retval 1: Correct
|
||||
* 0: Error
|
||||
*/
|
||||
uint32_t SerialKeyPressed(uint8_t *key)
|
||||
{
|
||||
if ((kLPUART_RxDataRegFullFlag)&LPUART_GetStatusFlags(LPUART1))
|
||||
{
|
||||
*key = LPUART_ReadByte(LPUART1);
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get a key from the HyperTerminal
|
||||
* @param None
|
||||
* @retval The Key Pressed
|
||||
*/
|
||||
uint8_t GetKey(void)
|
||||
{
|
||||
uint8_t key = 0;
|
||||
|
||||
/* Waiting for user input */
|
||||
while (1)
|
||||
{
|
||||
if (SerialKeyPressed((uint8_t*)&key)) break;
|
||||
}
|
||||
return key;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Print a character on the HyperTerminal
|
||||
* @param c: The character to be printed
|
||||
* @retval None
|
||||
*/
|
||||
void SerialPutChar(uint8_t c)
|
||||
{
|
||||
LPUART_WriteByte(LPUART1,c);
|
||||
while(!(kLPUART_TxDataRegEmptyFlag & LPUART_GetStatusFlags(LPUART1)))
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Print a string on the HyperTerminal
|
||||
* @param s: The string to be printed
|
||||
* @retval None
|
||||
*/
|
||||
void Serial_PutString(uint8_t *s)
|
||||
{
|
||||
while (*s != '\0')
|
||||
{
|
||||
SerialPutChar(*s);
|
||||
s++;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get Input string from the HyperTerminal
|
||||
* @param buffP: The input string
|
||||
* @retval None
|
||||
*/
|
||||
void GetInputString (uint8_t * buffP)
|
||||
{
|
||||
uint32_t bytes_read = 0;
|
||||
uint8_t c = 0;
|
||||
do
|
||||
{
|
||||
c = GetKey();
|
||||
if (c == '\r')
|
||||
break;
|
||||
if (c == '\b') /* Backspace */
|
||||
{
|
||||
if (bytes_read > 0)
|
||||
{
|
||||
Serial_PutString("\b \b");
|
||||
bytes_read --;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (bytes_read >= CMD_STRING_SIZE )
|
||||
{
|
||||
Serial_PutString("Command string size overflow\r\n");
|
||||
bytes_read = 0;
|
||||
continue;
|
||||
}
|
||||
if (c >= 0x20 && c <= 0x7E)
|
||||
{
|
||||
buffP[bytes_read++] = c;
|
||||
SerialPutChar(c);
|
||||
}
|
||||
}
|
||||
while (1);
|
||||
Serial_PutString(("\n\r"));
|
||||
buffP[bytes_read] = '\0';
|
||||
}
|
|
@ -25,7 +25,7 @@
|
|||
/*******************************************************************************
|
||||
* Prototypes
|
||||
******************************************************************************/
|
||||
|
||||
uint8_t NorFlash_BUFFER[4096]; //4K buffer cache
|
||||
uint8_t buffer[FLASH_PAGE_SIZE]; //256 bytes buffer cache
|
||||
/*******************************************************************************
|
||||
* Variables
|
||||
|
@ -264,13 +264,13 @@ status_t FLASH_EraseSector(uint32_t addr)
|
|||
* @param len : 字节数
|
||||
* @retval kStatus_Success:完成
|
||||
*/
|
||||
status_t FLASH_WritePage(uint32_t addr, const uint8_t *buf, uint32_t len)
|
||||
status_t FLASH_WritePage(uint32_t addr, const uint32_t *buf, uint32_t len)
|
||||
{
|
||||
status_t status;
|
||||
addr &= 0x0FFFFFFF;
|
||||
__disable_irq();
|
||||
norConfig.pageSize = len;
|
||||
status = ROM_FLEXSPI_NorFlash_ProgramPage(0, &norConfig, addr, (const uint32_t *)buf);
|
||||
status = ROM_FLEXSPI_NorFlash_ProgramPage(0, &norConfig, addr, buf);
|
||||
__enable_irq();
|
||||
|
||||
return status;
|
||||
|
@ -282,7 +282,7 @@ status_t FLASH_WritePage(uint32_t addr, const uint8_t *buf, uint32_t len)
|
|||
* @param len : 字节数
|
||||
* @retval kStatus_Success:完成
|
||||
*/
|
||||
status_t FLASH_Read(uint32_t addr, const uint8_t *buf, uint32_t len)
|
||||
status_t FLASH_Read(uint32_t addr, uint32_t *buf, uint32_t len)
|
||||
{
|
||||
status_t status;
|
||||
flexspi_xfer_t flashXfer;
|
||||
|
@ -294,7 +294,7 @@ status_t FLASH_Read(uint32_t addr, const uint8_t *buf, uint32_t len)
|
|||
flashXfer.seqId = NOR_CMD_LUT_SEQ_IDX_READ;
|
||||
flashXfer.baseAddress = addr;
|
||||
flashXfer.isParallelModeEnable = false;
|
||||
flashXfer.rxBuffer = (uint32_t *)buf;
|
||||
flashXfer.rxBuffer = buf;
|
||||
flashXfer.rxSize = len;
|
||||
|
||||
__disable_irq();
|
||||
|
@ -338,7 +338,7 @@ status_t flash_erase(uint32_t start_addr, uint32_t byte_cnt)
|
|||
*/
|
||||
status_t flash_write(uint32_t start_addr, uint8_t *buf, uint32_t byte_cnt)
|
||||
{
|
||||
return FLASH_WritePage(start_addr, buf, byte_cnt);
|
||||
return FLASH_WritePage(start_addr, (void *)buf, byte_cnt);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -353,7 +353,7 @@ status_t flash_read(uint32_t addr, uint8_t *buf, uint32_t len)
|
|||
/* For FlexSPI Memory ReadBack, use IP Command instead of AXI command for security */
|
||||
if((addr >= 0x60000000) && (addr < 0x70000000))
|
||||
{
|
||||
return FLASH_Read(addr, buf, len);
|
||||
return FLASH_Read(addr, (void *)buf, len);
|
||||
}
|
||||
|
||||
else
|
||||
|
@ -433,4 +433,184 @@ status_t flash_copy(uint32_t srcAddr,uint32_t dstAddr, uint32_t imageSize)
|
|||
}
|
||||
|
||||
return (status_t)kStatus_Success;
|
||||
}
|
||||
}
|
||||
|
||||
status_t NOR_FLASH_Erase(uint32_t app_base_addr,uint32_t imageSize)
|
||||
{
|
||||
uint16_t i;
|
||||
uint32_t sectorNum = (imageSize%4096 != 0)? (imageSize/4096 + 1):(imageSize/4096);
|
||||
|
||||
for(i=0;i<sectorNum;i++)
|
||||
{
|
||||
status_t status = FLASH_EraseSector(app_base_addr+i*SECTOR_SIZE);
|
||||
|
||||
if (status != kStatus_Success)
|
||||
{
|
||||
KPrintf("Erase_Sector 0x%x faild!\r\n",i*SECTOR_SIZE);
|
||||
return status;
|
||||
}
|
||||
}
|
||||
return kStatus_Success;
|
||||
}
|
||||
|
||||
void NorFlash_Write_PageProgram(uint8_t* pBuffer,uint32_t WriteAddr,uint16_t NumByteToWrite)
|
||||
{
|
||||
uint8_t temp_data[256] = {0xff};
|
||||
|
||||
memcpy(temp_data,pBuffer,NumByteToWrite);
|
||||
|
||||
status_t status = FLASH_WritePage(WriteAddr,(void *)temp_data,FLASH_PAGE_SIZE);
|
||||
if (status != kStatus_Success)
|
||||
{
|
||||
KPrintf("Write_PageProgram 0x%x faild!\r\n",WriteAddr);
|
||||
}
|
||||
}
|
||||
|
||||
void NorFlash_Write_NoCheck(uint8_t* pBuffer,uint32_t WriteAddr,uint16_t NumByteToWrite)
|
||||
{
|
||||
uint16_t pageRemain;
|
||||
|
||||
pageRemain = 256 - WriteAddr%256;//单页剩余的字节数
|
||||
|
||||
if(NumByteToWrite <= pageRemain)
|
||||
{
|
||||
pageRemain = NumByteToWrite;//不大于256个字节
|
||||
}
|
||||
|
||||
while(1)
|
||||
{
|
||||
NorFlash_Write_PageProgram(pBuffer,WriteAddr,pageRemain);
|
||||
if(NumByteToWrite == pageRemain)
|
||||
{
|
||||
break;//写入结束了
|
||||
}
|
||||
else //NumByteToWrite>pageRemain
|
||||
{
|
||||
pBuffer += pageRemain;
|
||||
WriteAddr += pageRemain;
|
||||
|
||||
NumByteToWrite -= pageRemain;//减去已经写入了的字节数
|
||||
if(NumByteToWrite > 256)
|
||||
{
|
||||
pageRemain = 256;//一次可以写入256个字节
|
||||
}
|
||||
else
|
||||
{
|
||||
pageRemain = NumByteToWrite;//不够256个字节了
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NorFlash_Write(uint8_t* pBuffer,uint32_t WriteAddr,uint16_t NumByteToWrite)
|
||||
{
|
||||
uint32_t secPos;
|
||||
uint16_t secOff;
|
||||
uint16_t secRemain;
|
||||
uint16_t i;
|
||||
uint8_t *NorFlash_BUF = 0;
|
||||
|
||||
NorFlash_BUF = NorFlash_BUFFER;//RAM缓冲区4K
|
||||
|
||||
WriteAddr &= 0x0FFFFFFF;
|
||||
|
||||
secPos = WriteAddr/SECTOR_SIZE;//扇区地址
|
||||
secOff = WriteAddr%SECTOR_SIZE;//在扇区内的偏移
|
||||
secRemain = SECTOR_SIZE - secOff;//扇区剩余空间大小
|
||||
|
||||
if(NumByteToWrite <= secRemain)
|
||||
{
|
||||
secRemain = NumByteToWrite;//不大于4096个字节
|
||||
}
|
||||
while(1)
|
||||
{
|
||||
FLASH_Read(FLASH_BASE + secPos*SECTOR_SIZE, (void *)NorFlash_BUF, SECTOR_SIZE);//读出整个扇区的内容
|
||||
for(i=0;i<secRemain;i++)//校验数据
|
||||
{
|
||||
if(NorFlash_BUF[secOff+i] != 0xFF)
|
||||
{
|
||||
break;//需要擦除
|
||||
}
|
||||
}
|
||||
if(i < secRemain)//需要擦除
|
||||
{
|
||||
FLASH_EraseSector(FLASH_BASE + secPos*SECTOR_SIZE);
|
||||
for(i=0;i<secRemain;i++)//复制
|
||||
{
|
||||
NorFlash_BUF[i+secOff] = pBuffer[i];
|
||||
|
||||
}
|
||||
NorFlash_Write_NoCheck(NorFlash_BUF,FLASH_BASE + secPos*4096,4096);//写入整个扇区
|
||||
}
|
||||
else
|
||||
{
|
||||
NorFlash_Write_NoCheck(pBuffer,FLASH_BASE + WriteAddr,secRemain);//写已经擦除了的,直接写入扇区剩余区间.
|
||||
}
|
||||
|
||||
if(NumByteToWrite == secRemain)
|
||||
{
|
||||
break;//写入结束了
|
||||
}
|
||||
else//写入未结束
|
||||
{
|
||||
secPos++;//扇区地址增1
|
||||
secOff=0;//偏移位置为0
|
||||
|
||||
pBuffer += secRemain;//指针偏移
|
||||
WriteAddr += secRemain;//写地址偏移
|
||||
NumByteToWrite -= secRemain;//字节数递减
|
||||
if(NumByteToWrite > 4096)
|
||||
{
|
||||
secRemain = 4096;//下一个扇区还是写不完
|
||||
}
|
||||
else
|
||||
{
|
||||
secRemain = NumByteToWrite;//下一个扇区可以写完了
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef USE_HIGHT_SPEED_TRANS
|
||||
uint32_t NOR_FLASH_Write(uint32_t* FlashAddress, uint8_t* Data ,uint16_t DataLength)
|
||||
{
|
||||
uint32_t WriteAddr;
|
||||
WriteAddr = *FlashAddress;
|
||||
NorFlash_Write(Data,WriteAddr,DataLength);
|
||||
*FlashAddress += DataLength;
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
uint8_t packetNum = 0;
|
||||
uint32_t dataLen = 0;
|
||||
uint32_t WriteAddr;
|
||||
uint8_t dataBuff[5*1024];
|
||||
uint32_t NOR_FLASH_Write(uint32_t* FlashAddress, uint8_t* Data ,uint16_t DataLength,uint8_t doneFlag)
|
||||
{
|
||||
if(!doneFlag)
|
||||
{
|
||||
memcpy(&dataBuff[dataLen],Data,DataLength);
|
||||
dataLen += DataLength;
|
||||
packetNum ++;
|
||||
if(1 == packetNum)
|
||||
{
|
||||
WriteAddr = *FlashAddress;
|
||||
}
|
||||
|
||||
if(dataLen>=4096)
|
||||
{
|
||||
NorFlash_Write(dataBuff,WriteAddr,dataLen);
|
||||
packetNum = 0;
|
||||
dataLen = 0;
|
||||
}
|
||||
*FlashAddress += DataLength;
|
||||
}
|
||||
else
|
||||
{
|
||||
NorFlash_Write(dataBuff,WriteAddr,dataLen);
|
||||
packetNum = 0;
|
||||
dataLen = 0;
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
#endif
|
|
@ -12,22 +12,16 @@
|
|||
* @author AIIT XUOS Lab
|
||||
* @date 2023-04-03
|
||||
*/
|
||||
|
||||
|
||||
#include <stdint.h>
|
||||
#include <xs_base.h>
|
||||
#include "flash.h"
|
||||
#include "stdint.h"
|
||||
#include "mcuboot.h"
|
||||
#include "ymodem.h"
|
||||
#include "common.h"
|
||||
|
||||
#ifdef MCUBOOT_BOOTLOADER
|
||||
static void JumpToApp(void)
|
||||
{
|
||||
asm volatile("LDR R0, = 0x60100000");
|
||||
asm volatile("LDR R0, [R0]");
|
||||
asm volatile("MOV SP, R0");
|
||||
|
||||
asm volatile("LDR R0, = 0x60100000+4");
|
||||
asm volatile("LDR R0, [R0]");
|
||||
asm volatile("BX R0");
|
||||
}
|
||||
extern void ImxrtMsDelay(uint32 ms);
|
||||
|
||||
static uint32_t UartSrcFreq(void)
|
||||
{
|
||||
|
@ -55,32 +49,72 @@ static void UartConfig(void)
|
|||
LPUART_Init(LPUART1, &config, UartSrcFreq());
|
||||
}
|
||||
|
||||
static void SerialPutC(uint8_t c)
|
||||
static void jump_to_application(void)
|
||||
{
|
||||
LPUART_WriteByte(LPUART1, c);
|
||||
while(!(kLPUART_TxDataRegEmptyFlag & LPUART_GetStatusFlags(LPUART1)))
|
||||
{
|
||||
}
|
||||
}
|
||||
SCB->VTOR = (uint32_t)0x60100000;
|
||||
|
||||
static void SerialPutString(uint8_t *s)
|
||||
{
|
||||
while (*s != '\0') {
|
||||
SerialPutC(*s);
|
||||
s++;
|
||||
}
|
||||
asm volatile("LDR R0, = 0x60100000");
|
||||
asm volatile("LDR R0, [R0]");
|
||||
asm volatile("MOV SP, R0");
|
||||
|
||||
asm volatile("LDR R0, = 0x60100000+4");
|
||||
asm volatile("LDR R0, [R0]");
|
||||
asm volatile("BX R0");
|
||||
}
|
||||
|
||||
void BootLoaderJumpApp(void)
|
||||
{
|
||||
uint8_t ch1, ch2;
|
||||
uint32_t ret;
|
||||
uint32_t timeout = 500;
|
||||
|
||||
BOARD_ConfigMPU();
|
||||
BOARD_InitPins();
|
||||
BOARD_BootClockRUN();
|
||||
|
||||
UartConfig();
|
||||
SysTick_Config(SystemCoreClock / TICK_PER_SECOND);
|
||||
|
||||
Serial_PutString("Please press 'space' key into menu in 5s !!!\r\n");
|
||||
|
||||
SerialPutString("BOOTLOADER START AND JUMP TO APP[0x60100000]\n");
|
||||
SCB->VTOR = (uint32_t)0x60100000;
|
||||
JumpToApp();
|
||||
while(timeout)
|
||||
{
|
||||
ret = (SerialKeyPressed((uint8_t*)&ch1));
|
||||
if(ret) break;
|
||||
timeout--;
|
||||
ImxrtMsDelay(10);
|
||||
}
|
||||
|
||||
while(1)
|
||||
{
|
||||
if((ret)&&(ch1 == 0x20))
|
||||
{
|
||||
Serial_PutString("\r\nPlease slecet:");
|
||||
Serial_PutString("\r\n 1:run app");
|
||||
Serial_PutString("\r\n 2:update app");
|
||||
Serial_PutString("\r\n 3:reboot \r\n");
|
||||
|
||||
ch2 = GetKey();
|
||||
switch(ch2)
|
||||
{
|
||||
case 0x31:
|
||||
jump_to_application();
|
||||
break;
|
||||
case 0x32:
|
||||
FLASH_Init();
|
||||
SerialDownload();
|
||||
FLASH_DeInit();
|
||||
break;
|
||||
case 0x33:
|
||||
__set_FAULTMASK(1);
|
||||
NVIC_SystemReset();
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
jump_to_application();
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,391 @@
|
|||
|
||||
/*
|
||||
* Copyright (c) 2020 AIIT XUOS Lab
|
||||
* XiUOS is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
* See the Mulan PSL v2 for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file: ymodem.c
|
||||
* @brief: file ymodem.c
|
||||
* @version: 1.0
|
||||
* @author: AIIT XUOS Lab
|
||||
* @date: 2023/3/24
|
||||
*/
|
||||
|
||||
|
||||
#include "common.h"
|
||||
#include "ymodem.h"
|
||||
#include "string.h"
|
||||
#include "flash.h"
|
||||
|
||||
#define BL_APP_VECTOR_TABLE_ADDRESS 0x60100000
|
||||
|
||||
uint8_t tab_1024[1024] ={0};
|
||||
uint8_t FileName[FILE_NAME_LENGTH];
|
||||
|
||||
|
||||
/**
|
||||
* @brief Receive byte from sender
|
||||
* @param c: Character
|
||||
* @param timeout: Timeout
|
||||
* @retval 0: Byte received
|
||||
* -1: Timeout
|
||||
*/
|
||||
static int32_t Receive_Byte (uint8_t *c, uint32_t timeout)
|
||||
{
|
||||
while (timeout-- > 0)
|
||||
{
|
||||
if (SerialKeyPressed(c) == 1)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Send a byte
|
||||
* @param c: Character
|
||||
* @retval 0: Byte sent
|
||||
*/
|
||||
static uint32_t Send_Byte (uint8_t c)
|
||||
{
|
||||
SerialPutChar(c);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Update CRC16 for input byte
|
||||
* @param CRC input value
|
||||
* @param input byte
|
||||
* @retval Updated CRC value
|
||||
*/
|
||||
uint16_t UpdateCRC16(uint16_t crcIn, uint8_t byte)
|
||||
{
|
||||
uint32_t crc = crcIn;
|
||||
uint32_t in = byte|0x100;
|
||||
|
||||
do
|
||||
{
|
||||
crc <<= 1;
|
||||
in <<= 1;
|
||||
|
||||
if(in&0x100)
|
||||
{
|
||||
++crc;
|
||||
}
|
||||
|
||||
if(crc&0x10000)
|
||||
{
|
||||
crc ^= 0x1021;
|
||||
}
|
||||
} while(!(in&0x10000));
|
||||
|
||||
return (crc&0xffffu);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Cal CRC16 for YModem Packet
|
||||
* @param data
|
||||
* @param length
|
||||
* @retval CRC value
|
||||
*/
|
||||
uint16_t Cal_CRC16(const uint8_t* data, uint32_t size)
|
||||
{
|
||||
uint32_t crc = 0;
|
||||
const uint8_t* dataEnd = data+size;
|
||||
|
||||
while(data<dataEnd)
|
||||
{
|
||||
crc = UpdateCRC16(crc,*data++);
|
||||
}
|
||||
crc = UpdateCRC16(crc,0);
|
||||
crc = UpdateCRC16(crc,0);
|
||||
|
||||
return (crc&0xffffu);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Cal Check sum for YModem Packet
|
||||
* @param data
|
||||
* @param length
|
||||
* @retval None
|
||||
*/
|
||||
uint8_t CalChecksum(const uint8_t* data, uint32_t size)
|
||||
{
|
||||
uint32_t sum = 0;
|
||||
const uint8_t* dataEnd = data+size;
|
||||
|
||||
while(data < dataEnd)
|
||||
{
|
||||
sum += *data++;
|
||||
}
|
||||
|
||||
return (sum&0xffu);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Receive a packet from sender
|
||||
* @param data
|
||||
* @param length
|
||||
* @param timeout
|
||||
* 0: end of transmission
|
||||
* -1: abort by sender
|
||||
* >0: packet length
|
||||
* @retval 0: normally return
|
||||
* -1: timeout or packet error
|
||||
* 1: abort by user
|
||||
*/
|
||||
static int32_t Receive_Packet (uint8_t *data, int32_t *length, uint32_t timeout)
|
||||
{
|
||||
uint16_t i, packet_size, computedcrc;
|
||||
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;
|
||||
}
|
||||
|
||||
/* Compute the CRC */
|
||||
computedcrc = Cal_CRC16(&data[PACKET_HEADER], (uint32_t)packet_size);
|
||||
/* Check that received CRC match the already computed CRC value
|
||||
data[packet_size+3]<<8) | data[packet_size+4] contains the received CRC
|
||||
computedcrc contains the computed CRC value */
|
||||
if (computedcrc != (uint16_t)((data[packet_size+3]<<8) | data[packet_size+4]))
|
||||
{
|
||||
/* CRC error */
|
||||
return -1;
|
||||
}
|
||||
|
||||
*length = packet_size;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Receive a file using the ymodem protocol
|
||||
* @param buf: Address of the first byte
|
||||
* @retval 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, packet_length, session_done, file_done, packets_received, errors, session_begin, size = 0;
|
||||
uint32_t flashdestination;
|
||||
|
||||
/* Initialize flashdestination variable */
|
||||
flashdestination = BL_APP_VECTOR_TABLE_ADDRESS;
|
||||
|
||||
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);)
|
||||
{
|
||||
FileName[i++] = *file_ptr++;
|
||||
}
|
||||
FileName[i++] = '\0';
|
||||
for (i = 0, file_ptr ++; (*file_ptr != ' ') && (i < (FILE_SIZE_LENGTH - 1));)
|
||||
{
|
||||
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 > (USER_FLASH_SIZE + 1))
|
||||
{
|
||||
/* End session */
|
||||
Send_Byte(CA);
|
||||
Send_Byte(CA);
|
||||
return -1;
|
||||
}
|
||||
/* erase user application area */
|
||||
|
||||
NOR_FLASH_Erase(BL_APP_VECTOR_TABLE_ADDRESS,size);
|
||||
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);
|
||||
|
||||
/* Write received data in Flash */
|
||||
#ifndef USE_HIGHT_SPEED_TRANS
|
||||
if (NOR_FLASH_Write(&flashdestination, buf, (uint16_t) packet_length) == 0)
|
||||
#else
|
||||
if (NOR_FLASH_Write(&flashdestination, buf, (uint16_t) packet_length,0) == 0)
|
||||
#endif
|
||||
{
|
||||
Send_Byte(ACK);
|
||||
}
|
||||
else /* An error occurred while writing to Flash memory */
|
||||
{
|
||||
/* End session */
|
||||
Send_Byte(CA);
|
||||
Send_Byte(CA);
|
||||
return -2;
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
#ifdef USE_HIGHT_SPEED_TRANS
|
||||
NOR_FLASH_Write(&flashdestination, buf, (uint16_t) packet_length,1);
|
||||
#endif
|
||||
return (int32_t)size;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Download a file via serial port
|
||||
* @param None
|
||||
* @retval None
|
||||
*/
|
||||
void SerialDownload(void)
|
||||
{
|
||||
uint8_t Number[10] = {0};
|
||||
int32_t Size = 0;
|
||||
|
||||
Serial_PutString("Waiting for the file to be sent ... (press 'a' to abort)\n\r");
|
||||
Size = Ymodem_Receive(&tab_1024[0]);
|
||||
if (Size > 0)
|
||||
{
|
||||
Serial_PutString("\n\n\r Programming Completed Successfully!\n\r--------------------------------\r\n Name: ");
|
||||
Serial_PutString(FileName);
|
||||
Int2Str(Number, Size);
|
||||
Serial_PutString("\n\r Size: ");
|
||||
Serial_PutString(Number);
|
||||
Serial_PutString(" Bytes\r\n");
|
||||
Serial_PutString("-------------------\n");
|
||||
}
|
||||
else if (Size == -1)
|
||||
{
|
||||
Serial_PutString("\n\n\rThe image size is higher than the allowed space memory!\n\r");
|
||||
}
|
||||
else if (Size == -2)
|
||||
{
|
||||
Serial_PutString("\n\n\rVerification failed!\n\r");
|
||||
}
|
||||
else if (Size == -3)
|
||||
{
|
||||
Serial_PutString("\r\n\nAborted by user.\n\r");
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial_PutString("\n\rFailed to receive the file!\n\r");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* Copyright (c) 2020 AIIT XUOS Lab
|
||||
* XiUOS is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
* See the Mulan PSL v2 for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file: common.h
|
||||
* @brief: file common.h
|
||||
* @version: 1.0
|
||||
* @author: AIIT XUOS Lab
|
||||
* @date: 2023/3/24
|
||||
*/
|
||||
|
||||
#ifndef _COMMON_H
|
||||
#define _COMMON_H
|
||||
|
||||
#include "fsl_common.h"
|
||||
#include "fsl_lpuart.h"
|
||||
|
||||
#define CMD_STRING_SIZE 128
|
||||
#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))
|
||||
|
||||
void Int2Str(uint8_t* str,int32_t intnum);
|
||||
uint32_t Str2Int(uint8_t *inputstr,int32_t *intnum);
|
||||
uint32_t GetIntegerInput(int32_t * num);
|
||||
uint32_t SerialKeyPressed(uint8_t *key);
|
||||
uint8_t GetKey(void);
|
||||
void SerialPutChar(uint8_t c);
|
||||
void Serial_PutString(uint8_t *s);
|
||||
void GetInputString(uint8_t * buffP);
|
||||
|
||||
#endif
|
|
@ -19,18 +19,32 @@
|
|||
#include <stdint.h>
|
||||
#include "fsl_romapi.h"
|
||||
|
||||
#define USE_HIGHT_SPEED_TRANS 1
|
||||
#define FLASH_BASE 0x60000000
|
||||
#define SECTOR_SIZE 0x1000
|
||||
#define FLASH_PAGE_SIZE 256
|
||||
|
||||
void FLASH_Init(void);
|
||||
void FLASH_DeInit(void);
|
||||
uint32_t FLASH_GetSectorSize(void);
|
||||
status_t FLASH_WritePage(uint32_t addr, const uint8_t *buf, uint32_t len);
|
||||
status_t FLASH_WritePage(uint32_t addr, const uint32_t *buf, uint32_t len);
|
||||
status_t FLASH_EraseSector(uint32_t addr);
|
||||
status_t FLASH_Read(uint32_t addr, const uint8_t *buf, uint32_t len);
|
||||
uint32_t FLASH_Test(uint32_t startAddr, uint32_t len);
|
||||
uint32_t FLASH_GetProgramCmd(void);
|
||||
status_t FLASH_Read(uint32_t addr, uint32_t *buf, uint32_t len);
|
||||
status_t flash_erase(uint32_t start_addr, uint32_t byte_cnt);
|
||||
status_t flash_write(uint32_t start_addr, uint8_t *buf, uint32_t byte_cnt);
|
||||
status_t flash_read(uint32_t addr, uint8_t *buf, uint32_t len);
|
||||
status_t flash_copy(uint32_t srcAddr,uint32_t dstAddr, uint32_t imageSize);
|
||||
|
||||
status_t NOR_FLASH_Erase(uint32_t app_base_addr,uint32_t imageSize);
|
||||
status_t NOR_FLASH_Erase(uint32_t app_base_addr,uint32_t imageSize);
|
||||
void NorFlash_Write_PageProgram(uint8_t* pBuffer,uint32_t WriteAddr,uint16_t NumByteToWrite);
|
||||
void NorFlash_Write_NoCheck(uint8_t* pBuffer,uint32_t WriteAddr,uint16_t NumByteToWrite);
|
||||
void NorFlash_Write(uint8_t* pBuffer,uint32_t WriteAddr,uint16_t NumByteToWrite);
|
||||
#ifndef USE_HIGHT_SPEED_TRANS
|
||||
uint32_t NOR_FLASH_Write(uint32_t* FlashAddress, uint8_t* Data ,uint16_t DataLength);
|
||||
#else
|
||||
uint32_t NOR_FLASH_Write(uint32_t* FlashAddress, uint8_t* Data ,uint16_t DataLength,uint8_t doneFlag);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
* Copyright (c) 2020 AIIT XUOS Lab
|
||||
* XiUOS is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
* See the Mulan PSL v2 for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file: ymodem.h
|
||||
* @brief: file ymodem.h
|
||||
* @version: 1.0
|
||||
* @author: AIIT XUOS Lab
|
||||
* @date: 2023/3/24
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _YMODEM_H_
|
||||
#define _YMODEM_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define BL_APP_VECTOR_TABLE_ADDRESS 0x60100000 //Application start address
|
||||
#define USER_FLASH_SIZE 0x100000 //Application package size is limited to 1M
|
||||
#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)
|
||||
|
||||
void SerialDownload(void);
|
||||
int32_t Ymodem_Receive (uint8_t *);
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue