d0ad047f81
wiki:https://wiki.segger.com/SEGGER_Flash_Loader Signed-off-by: anjiahao <anjiahao@xiaomi.com> Signed-off-by: chao an <anchao@xiaomi.com>
245 lines
7.2 KiB
C
245 lines
7.2 KiB
C
/****************************************************************************
|
|
* apps/system/ofloader/segger.c
|
|
*
|
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
* contributor license agreements. See the NOTICE file distributed with
|
|
* this work for additional information regarding copyright ownership. The
|
|
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
|
* "License"); you may not use this file except in compliance with the
|
|
* License. You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
* License for the specific language governing permissions and limitations
|
|
* under the License.
|
|
*
|
|
****************************************************************************/
|
|
|
|
/****************************************************************************
|
|
* Included Files
|
|
****************************************************************************/
|
|
|
|
#include <errno.h>
|
|
#include <fcntl.h>
|
|
#include <stdio.h>
|
|
#include <mqueue.h>
|
|
|
|
#include <nuttx/init.h>
|
|
|
|
#include "ofloader.h"
|
|
|
|
/****************************************************************************
|
|
* Pre-processor Definitions
|
|
****************************************************************************/
|
|
|
|
#define ONCHIP 1 /* On-chip Flash Memory */
|
|
#define ALGO_VERSION 0x101 /* Algo version, must not be modified. */
|
|
|
|
/****************************************************************************
|
|
* Private Type Definitions
|
|
****************************************************************************/
|
|
|
|
struct SECTOR_INFO
|
|
{
|
|
uint32_t SectorSize; /* Sector Size in bytes */
|
|
uint32_t SectorStartAddr; /* Start address of the sector area
|
|
* (relative to the "BaseAddr" of the flash)
|
|
*/
|
|
};
|
|
|
|
struct FlashDevice
|
|
{
|
|
uint16_t AlgoVer;
|
|
uint8_t Name[128];
|
|
uint16_t Type;
|
|
uint32_t BaseAddr;
|
|
uint32_t TotalSize;
|
|
uint32_t PageSize;
|
|
uint32_t Reserved;
|
|
uint8_t ErasedVal;
|
|
uint32_t TimeoutProg;
|
|
uint32_t TimeoutErase;
|
|
struct SECTOR_INFO SectorInfo[2];
|
|
};
|
|
|
|
const struct FlashDevice FlashDevice
|
|
locate_data("DevDscr") used_data =
|
|
{
|
|
ALGO_VERSION, /* Algo version */
|
|
"NuttX", /* Flash device name */
|
|
ONCHIP, /* Flash device type */
|
|
0x00000000, /* Flash base address */
|
|
0xffffffff, /* Total flash device size in Bytes */
|
|
CONFIG_SYSTEM_OFLOADER_BUFFERSIZE, /* Page Size (number of bytes that will
|
|
* be passed to ProgramPage(). May be
|
|
* multiple of min alignment in order
|
|
* to reduce overhead for calling
|
|
* ProgramPage multiple times
|
|
*/
|
|
1, /* Reserved, should be 1 */
|
|
0xff, /* Flash erased value */
|
|
5000, /* Program page timeout in ms */
|
|
5000, /* Erase sector timeout in ms */
|
|
|
|
/* Flash sector layout definition
|
|
* Sector size equl with page size to skip erase
|
|
*/
|
|
|
|
{
|
|
{CONFIG_SYSTEM_OFLOADER_BUFFERSIZE, 0x00000000},
|
|
{0xffffffff, 0xffffffff}
|
|
}
|
|
};
|
|
|
|
/* This array is used to mark the stack and transfer buffer
|
|
*locations used by the ofloader
|
|
*/
|
|
|
|
static uint8_t g_stack_buff[CONFIG_SYSTEM_OFLOADER_STACKSIZE +
|
|
CONFIG_SYSTEM_OFLOADER_BUFFERSIZE]
|
|
locate_data("DevStack") used_data;
|
|
|
|
/****************************************************************************
|
|
* Public Function Prototypes
|
|
****************************************************************************/
|
|
|
|
int SEGGER_FL_Prepare(uint32_t PreparePara0, uint32_t PreparePara1,
|
|
uint32_t PreparePara2)
|
|
locate_code("PrgData") used_code;
|
|
|
|
int SEGGER_FL_Restore(uint32_t PreparePara0, uint32_t PreparePara1,
|
|
uint32_t PreparePara2)
|
|
locate_code("PrgData") used_code;
|
|
|
|
int SEGGER_FL_Program(uint32_t DestAddr, uint32_t NumBytes,
|
|
FAR uint8_t *pSrcBuff)
|
|
locate_code("PrgData") used_code;
|
|
|
|
int SEGGER_FL_Erase(uint32_t SectorAddr, uint32_t SectorIndex,
|
|
uint32_t NumSectors)
|
|
locate_code("PrgData") used_code;
|
|
|
|
int SEGGER_FL_Read(uint32_t Addr, uint32_t NumBytes, FAR uint8_t *pDestBuff)
|
|
locate_code("PrgData") used_code;
|
|
|
|
uint32_t SEGGER_FL_Verify(uint32_t Addr, uint32_t NumBytes,
|
|
FAR uint8_t *pData)
|
|
locate_code("PrgData") used_code;
|
|
|
|
/****************************************************************************
|
|
* Public data
|
|
****************************************************************************/
|
|
|
|
/* Reference SEGGER_FL_Prepare to prevent it from being
|
|
* optimized by the compiler
|
|
*/
|
|
|
|
FAR void *g_create_idle = SEGGER_FL_Prepare;
|
|
|
|
static int SEGGER_FL_SendAndWait(FAR struct ofloader_msg *msg)
|
|
{
|
|
int atcion = msg->atcion;
|
|
mqd_t mq;
|
|
int ret;
|
|
|
|
mq = mq_open(OFLOADER_QNAME, O_RDWR, 0666, NULL);
|
|
if (mq < 0)
|
|
{
|
|
return -errno;
|
|
}
|
|
|
|
ret = mq_send(mq, (FAR void *)&msg, sizeof(msg), 0);
|
|
if (ret < 0)
|
|
{
|
|
ret = -errno;
|
|
goto out;
|
|
}
|
|
|
|
/* TODO:SEGGER disables interrupts by default during operation
|
|
* so wait ofloader main thread do somthing.
|
|
*/
|
|
|
|
while (msg->atcion == atcion);
|
|
if (msg->atcion == OFLOADER_ERROR)
|
|
{
|
|
ret = -EIO;
|
|
goto out;
|
|
}
|
|
|
|
out:
|
|
mq_close(mq);
|
|
return ret;
|
|
}
|
|
|
|
extern void __start(void);
|
|
|
|
/****************************************************************************
|
|
* Public Functions
|
|
****************************************************************************/
|
|
|
|
int SEGGER_FL_Prepare(uint32_t PreparePara0, uint32_t PreparePara1,
|
|
uint32_t PreparePara2)
|
|
{
|
|
g_create_idle = NULL;
|
|
__start();
|
|
return 0;
|
|
}
|
|
|
|
int SEGGER_FL_Restore(uint32_t PreparePara0, uint32_t PreparePara1,
|
|
uint32_t PreparePara2)
|
|
{
|
|
struct ofloader_msg msg;
|
|
|
|
msg.atcion = OFLOADER_SYNC;
|
|
return SEGGER_FL_SendAndWait(&msg);
|
|
}
|
|
|
|
int SEGGER_FL_Program(uint32_t DestAddr, uint32_t NumBytes,
|
|
FAR uint8_t *pSrcBuff)
|
|
{
|
|
struct ofloader_msg msg;
|
|
|
|
msg.addr = DestAddr;
|
|
msg.size = NumBytes;
|
|
msg.buff = pSrcBuff;
|
|
msg.atcion = OFLOADER_WRITE;
|
|
return SEGGER_FL_SendAndWait(&msg);
|
|
}
|
|
|
|
int SEGGER_FL_Erase(uint32_t SectorAddr, uint32_t SectorIndex,
|
|
uint32_t NumSectors)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
int SEGGER_FL_Read(uint32_t Addr, uint32_t NumBytes, FAR uint8_t *pDestBuff)
|
|
{
|
|
struct ofloader_msg msg;
|
|
|
|
msg.addr = Addr;
|
|
msg.size = NumBytes;
|
|
msg.buff = pDestBuff;
|
|
msg.atcion = OFLOADER_READ;
|
|
return SEGGER_FL_SendAndWait(&msg);
|
|
}
|
|
|
|
uint32_t SEGGER_FL_Verify(uint32_t Addr, uint32_t NumBytes,
|
|
FAR uint8_t *pData)
|
|
{
|
|
struct ofloader_msg msg;
|
|
|
|
msg.addr = Addr;
|
|
msg.size = NumBytes;
|
|
msg.buff = pData;
|
|
msg.atcion = OFLOADER_VERIFY;
|
|
if (SEGGER_FL_SendAndWait(&msg) < 0)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
return Addr + NumBytes;
|
|
}
|