1161 lines
29 KiB
C
1161 lines
29 KiB
C
#include <string.h>
|
||
#include "typedef.h"
|
||
#include "amt630h.h"
|
||
#include "uart.h"
|
||
#include "timer.h"
|
||
#include "gpio.h"
|
||
#include "spi.h"
|
||
#include "cp15.h"
|
||
#include "sysinfo.h"
|
||
#include "crc32.h"
|
||
#include "update.h"
|
||
#include "board.h"
|
||
#include "os_adapt.h"
|
||
|
||
#if DEVICE_TYPE_SELECT == SPI_NOR_FLASH || DEVICE_TYPE_SELECT == EMMC_FLASH
|
||
#define SPI_CS_GPIO 32
|
||
|
||
#define SPI_RXFIFO_FULL (1<<4)
|
||
#define SPI_RXFIFO_NOTEMPTY (1<<3)
|
||
#define SPI_TXFIFO_EMPTY (1<<2)
|
||
#define SPI_TXFIFO_NOTFULL (1<<1)
|
||
#define SPIFLASH_BUSY (1<<0)
|
||
|
||
/* SFUD support manufacturer JEDEC ID */
|
||
#define SFUD_MF_ID_CYPRESS 0x01
|
||
#define SFUD_MF_ID_FUJITSU 0x04
|
||
#define SFUD_MF_ID_EON 0x1C
|
||
#define SFUD_MF_ID_ATMEL 0x1F
|
||
#define SFUD_MF_ID_MICRON 0x20
|
||
#define SFUD_MF_ID_AMIC 0x37
|
||
#define SFUD_MF_ID_SANYO 0x62
|
||
#define SFUD_MF_ID_INTEL 0x89
|
||
#define SFUD_MF_ID_ESMT 0x8C
|
||
#define SFUD_MF_ID_FUDAN 0xA1
|
||
#define SFUD_MF_ID_HYUNDAI 0xAD
|
||
#define SFUD_MF_ID_SST 0xBF
|
||
#define SFUD_MF_ID_MICRONIX 0xC2
|
||
#define SFUD_MF_ID_GIGADEVICE 0xC8
|
||
#define SFUD_MF_ID_ISSI 0xD5
|
||
#define SFUD_MF_ID_WINBOND 0xEF
|
||
|
||
int SpiNorBurn(void *buf, unsigned int offset, unsigned int size, int show_progress);
|
||
extern void wdt_cpu_reboot(void);
|
||
static void SpiWriteEnable(void);
|
||
|
||
/* flash chip information */
|
||
typedef struct {
|
||
char *name; /**< flash chip name */
|
||
uint8_t mf_id; /**< manufacturer ID */
|
||
uint8_t type_id; /**< memory type ID */
|
||
uint8_t capacity_id; /**< capacity ID */
|
||
uint32_t capacity; /**< flash capacity (bytes) */
|
||
} flash_chip;
|
||
|
||
static const flash_chip flash_chip_table[] =
|
||
{
|
||
{"W25Q40BV", SFUD_MF_ID_WINBOND, 0x40, 0x13, 512L*1024L},
|
||
{"W25Q16BV", SFUD_MF_ID_WINBOND, 0x40, 0x15, 2L*1024L*1024L},
|
||
{"W25Q32BV", SFUD_MF_ID_WINBOND, 0x40, 0x16, 4L*1024L*1024L},
|
||
{"W25Q64CV", SFUD_MF_ID_WINBOND, 0x40, 0x17, 8L*1024L*1024L},
|
||
{"W25Q64DW", SFUD_MF_ID_WINBOND, 0x60, 0x17, 8L*1024L*1024L},
|
||
{"W25Q128BV", SFUD_MF_ID_WINBOND, 0x40, 0x18, 16L*1024L*1024L},
|
||
{"W25Q256FV", SFUD_MF_ID_WINBOND, 0x40, 0x19, 32L*1024L*1024L},
|
||
{"W25H256JV", SFUD_MF_ID_WINBOND, 0x90, 0x19, 32L*1024L*1024L},
|
||
{"W25Q512JVFM", SFUD_MF_ID_WINBOND, 0x70, 0x20, 64L*1024L*1024L},
|
||
{"SST25VF080B", SFUD_MF_ID_SST, 0x25, 0x8E, 1L*1024L*1024L},
|
||
{"SST25VF016B", SFUD_MF_ID_SST, 0x25, 0x41, 2L*1024L*1024L},
|
||
{"EN25Q32B", SFUD_MF_ID_EON, 0x30, 0x16, 4L*1024L*1024L},
|
||
{"GD25Q64B", SFUD_MF_ID_GIGADEVICE, 0x40, 0x17, 8L*1024L*1024L},
|
||
{"GD25Q16B", SFUD_MF_ID_GIGADEVICE, 0x40, 0x15, 2L*1024L*1024L},
|
||
{"GD25Q32C", SFUD_MF_ID_GIGADEVICE, 0x40, 0x16, 4L*1024L*1024L},
|
||
{"S25FL216K", SFUD_MF_ID_CYPRESS, 0x40, 0x15, 2L*1024L*1024L},
|
||
{"S25FL032P", SFUD_MF_ID_CYPRESS, 0x02, 0x15, 4L*1024L*1024L},
|
||
{"A25L080", SFUD_MF_ID_AMIC, 0x30, 0x14, 1L*1024L*1024L},
|
||
{"F25L004", SFUD_MF_ID_ESMT, 0x20, 0x13, 512L*1024L},
|
||
{"PCT25VF016B", SFUD_MF_ID_SST, 0x25, 0x41, 2L*1024L*1024L},
|
||
{"IS25LP128F", SFUD_MF_ID_ISSI, 0x60, 0x18, 16L*1024L*1024L},
|
||
{"MX25L6433F", SFUD_MF_ID_MICRONIX, 0x20, 0x17, 8L*1024L*1024L},
|
||
{"MX25L12845G", SFUD_MF_ID_MICRONIX, 0x20, 0x18, 16L*1024L*1024L},
|
||
{"MX25L25645G", SFUD_MF_ID_MICRONIX, 0x20, 0x19, 32L*1024L*1024L},
|
||
{"W25Q512JVFM", SFUD_MF_ID_WINBOND, 0x70, 0x20, 64L*1024L*1024L},
|
||
{"GD25B512ME", SFUD_MF_ID_GIGADEVICE, 0x47, 0x1A, 64L*1024L*1024L},
|
||
};
|
||
|
||
static int addr_in_4_byte = 0;
|
||
|
||
static void SetCSGpioEnable(int enable)
|
||
{
|
||
gpio_direction_output(SPI_CS_GPIO, !enable);
|
||
}
|
||
|
||
static void SetSpiDataMode(unsigned int bitMode)
|
||
{
|
||
unsigned int val = 0;
|
||
|
||
(void)val;
|
||
while((rSPI_SR & SPI_BUSY));
|
||
rSPI_SSIENR = 0;
|
||
val = rSPI_CTLR0;
|
||
val &=~(0x1f<<16);
|
||
val |=((bitMode-1)<<16);
|
||
rSPI_CTLR0 = val;
|
||
rSPI_SSIENR = 1;
|
||
}
|
||
|
||
static void SpiWaitIdle(void)
|
||
{
|
||
while(rSPI_SR & SPIFLASH_BUSY);
|
||
udelay(2);
|
||
}
|
||
|
||
static void SpiEmptyRxFIFO(void)
|
||
{
|
||
INT32 data = 0;
|
||
|
||
(void)data;
|
||
|
||
while(rSPI_SR & SPI_RXFIFO_NOTEMPTY)
|
||
data = rSPI_DR;
|
||
}
|
||
|
||
#ifdef SPI0_QSPI_MODE
|
||
static void SpiWriteSta2(uint8_t status)
|
||
{
|
||
SpiWriteEnable();
|
||
SetSpiDataMode(8);
|
||
SetCSGpioEnable(1);
|
||
rSPI_DR = SPI_WRITE_STATUS2;
|
||
rSPI_DR = status;
|
||
SpiWaitIdle();
|
||
SetCSGpioEnable(0);
|
||
SetSpiDataMode(32);
|
||
}
|
||
|
||
static UINT8 SpiReadSta2(void)
|
||
{
|
||
UINT8 status;
|
||
|
||
SetSpiDataMode(8);
|
||
SetCSGpioEnable(1);
|
||
rSPI_DR = SPI_READ_STATUS2;
|
||
rSPI_DR = 0;
|
||
while(!(rSPI_SR & SPI_RXFIFO_NOTEMPTY));
|
||
status = rSPI_DR;
|
||
while(!(rSPI_SR & SPI_RXFIFO_NOTEMPTY));
|
||
status = rSPI_DR;
|
||
PrintVariableValueHex("status s2 :", status);
|
||
SpiWaitIdle();
|
||
SetCSGpioEnable(0);
|
||
SetSpiDataMode(32);
|
||
return status;
|
||
}
|
||
#endif
|
||
|
||
static UINT8 SpiReadSta3(void)
|
||
{
|
||
UINT8 status;
|
||
|
||
SetSpiDataMode(8);
|
||
SetCSGpioEnable(1);
|
||
rSPI_DR = SPI_READ_STATUS3;
|
||
rSPI_DR = 0;
|
||
while(!(rSPI_SR & SPI_RXFIFO_NOTEMPTY));
|
||
status = rSPI_DR;
|
||
while(!(rSPI_SR & SPI_RXFIFO_NOTEMPTY));
|
||
status = rSPI_DR;
|
||
PrintVariableValueHex("status s3 :", status);
|
||
SpiWaitIdle();
|
||
SetCSGpioEnable(0);
|
||
SetSpiDataMode(32);
|
||
return status;
|
||
}
|
||
|
||
static UINT8 SpiReadSta(void)
|
||
{
|
||
UINT8 status;
|
||
|
||
SetSpiDataMode(8);
|
||
SetCSGpioEnable(1);
|
||
rSPI_DR = SPI_READ_STATUS;
|
||
rSPI_DR = 0;
|
||
while(!(rSPI_SR & SPI_RXFIFO_NOTEMPTY));
|
||
status = rSPI_DR;
|
||
while(!(rSPI_SR & SPI_RXFIFO_NOTEMPTY));
|
||
status = rSPI_DR;
|
||
//PrintVariableValueHex("status:", status);
|
||
SpiWaitIdle();
|
||
SetCSGpioEnable(0);
|
||
SetSpiDataMode(32);
|
||
return status;
|
||
}
|
||
static void SpiWriteSta(uint8_t status)
|
||
{
|
||
SpiWriteEnable();
|
||
SetSpiDataMode(8);
|
||
SetCSGpioEnable(1);
|
||
rSPI_DR = SPI_WRITE_STATUS;
|
||
rSPI_DR = status;
|
||
SpiWaitIdle();
|
||
SetCSGpioEnable(0);
|
||
SetSpiDataMode(32);
|
||
}
|
||
static void SpiDisable4ByteMode(void)
|
||
{
|
||
SetSpiDataMode(8);
|
||
SetCSGpioEnable(1);
|
||
rSPI_DR = SPI_DISABLE_4BYTE_MODE;
|
||
while(!(rSPI_SR & SPI_TXFIFO_EMPTY));
|
||
SpiWaitIdle();
|
||
SetCSGpioEnable(0);
|
||
SetSpiDataMode(32);
|
||
}
|
||
|
||
static void SpiEnable4ByteMode(void)
|
||
{
|
||
SetSpiDataMode(8);
|
||
SetCSGpioEnable(1);
|
||
rSPI_DR = SPI_ENABLE_4BYTE_MODE;
|
||
while(!(rSPI_SR & SPI_TXFIFO_EMPTY));
|
||
SpiWaitIdle();
|
||
SetCSGpioEnable(0);
|
||
SetSpiDataMode(32);
|
||
}
|
||
|
||
static void SpiReadPage(UINT32 pagenum, UINT32 *buf)
|
||
{
|
||
UINT32 addr;
|
||
UINT32 val = 0;
|
||
INT32 i, j;
|
||
UINT8 tmpaddr[4];
|
||
UINT8 *data = (UINT8*)buf;
|
||
|
||
(void)val;
|
||
|
||
addr = pagenum*BYTESPERPAGE;
|
||
tmpaddr[0] = addr;
|
||
tmpaddr[1] = addr>>8;
|
||
tmpaddr[2] = addr>>16;
|
||
tmpaddr[3] = addr>>24;
|
||
|
||
SpiEmptyRxFIFO();
|
||
SetCSGpioEnable(1);
|
||
|
||
if (addr_in_4_byte) {
|
||
SetSpiDataMode(8);
|
||
rSPI_DR = SPI_4BYTEADDR_READ_DATA;
|
||
rSPI_DR = tmpaddr[3];
|
||
rSPI_DR = tmpaddr[2];
|
||
rSPI_DR = tmpaddr[1];
|
||
rSPI_DR = tmpaddr[0];
|
||
for (i = 0; i < 5; i++) {
|
||
while(!(rSPI_SR & SPI_RXFIFO_NOTEMPTY));
|
||
val = rSPI_DR;
|
||
}
|
||
} else {
|
||
rSPI_DR = (tmpaddr[0]<<24) | (tmpaddr[1]<<16) | (tmpaddr[2]<<8) | SPI_READ_DATA;
|
||
while(!(rSPI_SR & SPI_RXFIFO_NOTEMPTY));
|
||
val = rSPI_DR;
|
||
}
|
||
|
||
if (addr_in_4_byte) {
|
||
for (i = 0; i < 4; i++) {
|
||
for (j = 0; j < WORDSPERPAGE; j++) {
|
||
while(!(rSPI_SR & SPI_TXFIFO_NOTFULL));
|
||
rSPI_DR = 0;
|
||
}
|
||
for (j = 0; j < WORDSPERPAGE; j++) {
|
||
while(!(rSPI_SR & SPI_RXFIFO_NOTEMPTY));
|
||
*data++ = rSPI_DR;
|
||
}
|
||
}
|
||
} else {
|
||
for (i = 0; i < WORDSPERPAGE; i++) {
|
||
while(!(rSPI_SR & SPI_TXFIFO_NOTFULL));
|
||
rSPI_DR = 0;
|
||
}
|
||
for(i = 0; i < WORDSPERPAGE; i++) {
|
||
while(!(rSPI_SR & SPI_RXFIFO_NOTEMPTY));
|
||
*buf++ = rSPI_DR;
|
||
}
|
||
}
|
||
|
||
SpiWaitIdle();
|
||
SetCSGpioEnable(0);
|
||
if (addr_in_4_byte)
|
||
SetSpiDataMode(32);
|
||
}
|
||
|
||
#ifdef SPI0_QSPI_MODE
|
||
//********format*********
|
||
//00 – Standard SPI Format
|
||
// 01 – Dual SPI Format
|
||
// 10 – Quad SPI Format
|
||
// 11 – Reserved
|
||
//********tmod**********
|
||
//00 –- Transmit & Receive
|
||
//01 –- Transmit Only
|
||
//10 –- Receive Only
|
||
//11 –- EEPROM Read
|
||
static void SpiSetFrameFormatMode(unsigned char format, unsigned char tmod)
|
||
{
|
||
unsigned int val = 0;
|
||
|
||
while((rSPI_SR & SPI_BUSY));
|
||
rSPI_SSIENR = 0;
|
||
val = rSPI_CTLR0;
|
||
val &= ~((0x3 << 21) | (0x3 << 8));
|
||
val |= ((format << 21) | (tmod << 8));
|
||
rSPI_CTLR0 = val;
|
||
rSPI_SSIENR = 1;
|
||
}
|
||
|
||
static void SpiReadPageQuadMode(UINT32 pagenum, UINT32 *buf)
|
||
{
|
||
UINT32 addr;
|
||
UINT32 val = 0;
|
||
INT32 i;
|
||
UINT8 tmpaddr[4];
|
||
|
||
(void)val;
|
||
|
||
addr = pagenum*BYTESPERPAGE;
|
||
tmpaddr[0] = addr;
|
||
tmpaddr[1] = addr>>8;
|
||
tmpaddr[2] = addr>>16;
|
||
tmpaddr[3] = addr>>24;
|
||
|
||
SpiEmptyRxFIFO();
|
||
SetCSGpioEnable(1);
|
||
|
||
SpiSetFrameFormatMode(2, 2);
|
||
rSPI_SSIENR = 0;
|
||
if (addr_in_4_byte) {
|
||
//set instruction 8bits,1byte mode; addr 32bit,4bytes mode; 6 dummy clocks
|
||
rSPI_SPI_CTRLR0 = (6 << 11) | (2 << 8) | (8 << 2) | 1;
|
||
rSPI_CTLR1 = WORDSPERPAGE - 1;
|
||
rSPI_SSIENR = 1;
|
||
|
||
rSPI_DR = SPI_QUAD_IO_READ_DATA + 1;
|
||
rSPI_DR = (tmpaddr[0] << 24) | (tmpaddr[1] << 16) | (tmpaddr[2] << 8) | tmpaddr[3];
|
||
} else {
|
||
//set instruction 8bits,1byte mode; addr 24bit,4bytes mode; 6 dummy clocks
|
||
rSPI_SPI_CTRLR0 = (6 << 11) | (2 << 8) | (6 << 2) | 1;
|
||
rSPI_CTLR1 = WORDSPERPAGE - 1;
|
||
rSPI_SSIENR = 1;
|
||
|
||
rSPI_DR = SPI_QUAD_IO_READ_DATA;
|
||
rSPI_DR = (tmpaddr[0] << 16) | (tmpaddr[1] << 8) | (tmpaddr[2] << 0);
|
||
}
|
||
|
||
for(i=0; i<WORDSPERPAGE; i++)
|
||
{
|
||
while(!(rSPI_SR & SPI_RXFIFO_NOTEMPTY));
|
||
*buf++ = rSPI_DR;
|
||
}
|
||
|
||
SpiWaitIdle();
|
||
rSPI_SSIENR = 0;
|
||
rSPI_SPI_CTRLR0 = 0;
|
||
rSPI_CTLR1 = 0;
|
||
rSPI_SSIENR = 1;
|
||
SpiSetFrameFormatMode(0, 0);
|
||
|
||
SetCSGpioEnable(0);
|
||
}
|
||
#endif
|
||
|
||
void SpiSelectPad()
|
||
{
|
||
UINT32 val;
|
||
val = rSYS_PAD_CTRL02;
|
||
val &= ~0xfff;
|
||
val |= (0x1<<10)|(0x1 << 8)|(0x1 << 6)|(0x1 << 4)| (0x1 << 2);
|
||
rSYS_PAD_CTRL02 = val;
|
||
|
||
val = rSYS_SSP_CLK_CFG;
|
||
val &= ~((0x1<<31)|(0x1<<30));
|
||
val |= (0x1<<31)|(0x1<<30);
|
||
rSYS_SSP_CLK_CFG = val;
|
||
|
||
//cs inactive first
|
||
SetCSGpioEnable(0);
|
||
}
|
||
|
||
void Reset(void)
|
||
{
|
||
SetSpiDataMode(8);
|
||
rSPI_DR = 0x66;
|
||
while((SpiReadSta() & SPI_BUSY));
|
||
// while(!(SpiReadSta() & SPIFLASH_WRITEENABLE));
|
||
rSPI_DR = 0x99;
|
||
while((SpiReadSta() & SPI_BUSY));
|
||
// while(!(SpiReadSta() & SPIFLASH_WRITEENABLE));
|
||
|
||
SetSpiDataMode(32);
|
||
}
|
||
|
||
#define SPI0_CS0_GPIO 32
|
||
#define SPI0_IO0_GPIO 34
|
||
static void dwspi_jedec252_reset(void)
|
||
{
|
||
int i;
|
||
int si = 0;
|
||
UINT32 val;
|
||
|
||
val = rSYS_PAD_CTRL02;
|
||
val &= ~((3 << 4) | 3);
|
||
rSYS_PAD_CTRL02 = val;
|
||
|
||
gpio_direction_output(SPI0_CS0_GPIO, 1);
|
||
gpio_direction_output(SPI0_IO0_GPIO, 1);
|
||
udelay(300);
|
||
|
||
for (i = 0; i < 4; i++) {
|
||
gpio_direction_output(SPI0_CS0_GPIO, 0);
|
||
gpio_direction_output(SPI0_IO0_GPIO, si);
|
||
si = !si;
|
||
udelay(300);
|
||
gpio_direction_output(SPI0_CS0_GPIO, 1);
|
||
udelay(300);
|
||
}
|
||
}
|
||
|
||
static void SpiReadDeviceId(UINT8 *mfid, UINT8 *devid)
|
||
{
|
||
UINT8 val[6];
|
||
int i;
|
||
SetSpiDataMode(8);
|
||
SetCSGpioEnable(1);
|
||
rSPI_DR = SPI_MF_DEVICE_ID;
|
||
rSPI_DR = 0;
|
||
rSPI_DR = 0;
|
||
rSPI_DR = 0;
|
||
rSPI_DR = 0;
|
||
rSPI_DR = 0;
|
||
for (i = 0; i < 6; i++)
|
||
{
|
||
while(!(rSPI_SR & SPI_RXFIFO_NOTEMPTY));
|
||
val[i] = rSPI_DR;
|
||
}
|
||
*mfid = val[4];
|
||
*devid = val[5];
|
||
SpiWaitIdle();
|
||
SetCSGpioEnable(0);
|
||
SetSpiDataMode(32);
|
||
}
|
||
|
||
static void SpiReadJedecId(UINT8 *mfid, UINT8 *memid, UINT8 *capid)
|
||
{
|
||
UINT8 val[4];
|
||
int i;
|
||
|
||
SetSpiDataMode(8);
|
||
SetCSGpioEnable(1);
|
||
rSPI_DR = SPI_READ_JEDEC_ID;
|
||
rSPI_DR = 0;
|
||
rSPI_DR = 0;
|
||
rSPI_DR = 0;
|
||
|
||
for (i = 0; i < 4; i++)
|
||
{
|
||
while(!(rSPI_SR & SPI_RXFIFO_NOTEMPTY));
|
||
val[i] = rSPI_DR;
|
||
}
|
||
*mfid = val[1];
|
||
*memid = val[2];
|
||
*capid = val[3];
|
||
SpiWaitIdle();
|
||
SetCSGpioEnable(0);
|
||
SetSpiDataMode(32);
|
||
}
|
||
|
||
static void SpiuId(void)
|
||
{
|
||
UINT8 val[13];
|
||
int i;
|
||
|
||
(void)val;
|
||
|
||
SetSpiDataMode(8);
|
||
SetCSGpioEnable(1);
|
||
|
||
rSPI_DR = 0x4b;
|
||
for (i = 0; i < 12; i++)
|
||
rSPI_DR = 0;
|
||
|
||
for (i = 0; i < 13; i++) {
|
||
while(!(rSPI_SR & SPI_RXFIFO_NOTEMPTY));
|
||
val[i] = rSPI_DR;
|
||
}
|
||
|
||
SpiWaitIdle();
|
||
SetCSGpioEnable(0);
|
||
SetSpiDataMode(32);
|
||
}
|
||
|
||
void SpiReadId(void)
|
||
{
|
||
UINT8 mfid,devid,memid,capid;
|
||
|
||
SpiReadDeviceId(&mfid,&devid);
|
||
SpiReadJedecId(&mfid,&memid,&capid);
|
||
PrintVariableValueHex("ManufacturerID: ", mfid);
|
||
PrintVariableValueHex("DeviceID: ", devid);
|
||
PrintVariableValueHex("Memory Type ID: ", memid);
|
||
PrintVariableValueHex("Capacity ID: ", capid);
|
||
}
|
||
|
||
int SpiInit(void)
|
||
{
|
||
uint8_t mfid, typeid, capid;
|
||
unsigned int val;
|
||
int i;
|
||
|
||
dwspi_jedec252_reset();
|
||
SpiSelectPad();
|
||
|
||
val = rSYS_SOFT_RST;
|
||
val &= ~(0x1<<8);
|
||
rSYS_SOFT_RST = val;
|
||
udelay(10);
|
||
val |= (0x1<<8);
|
||
rSYS_SOFT_RST = val;
|
||
|
||
rSPI_SSIENR = 0;
|
||
rSPI_CTLR0 = 0;
|
||
rSPI_CTLR0 |=(0<<21)|(0x1f<<16)|(0x0<<12)|(0x0<<8)|(0x0<<4);
|
||
//rSPI_CTLR1 = 63;
|
||
rSPI_BAUDR = 4;//42;//16;//2;
|
||
rSPI_SER = 1;
|
||
rSPI_IMR = 0;
|
||
rSPI_SSIENR = 1;
|
||
SpiuId();
|
||
// Reset();
|
||
SpiReadJedecId(&mfid, &typeid, &capid);
|
||
for (i = 0; i < sizeof(flash_chip_table) / sizeof(flash_chip); i++) {
|
||
if ((flash_chip_table[i].mf_id == mfid)
|
||
&& (flash_chip_table[i].type_id == typeid)
|
||
&& (flash_chip_table[i].capacity_id == capid)) {
|
||
PrintVariableValueHex("i xxxxxxx ", i);
|
||
if (flash_chip_table[i].capacity > 0x1000000) {
|
||
addr_in_4_byte = 1;
|
||
SpiEnable4ByteMode();
|
||
}
|
||
break;
|
||
}
|
||
}
|
||
|
||
if (!addr_in_4_byte)
|
||
SpiDisable4ByteMode();
|
||
|
||
#ifdef SPI0_QSPI_MODE
|
||
if((i<sizeof(flash_chip_table)/sizeof(flash_chip))&&(SFUD_MF_ID_ISSI==flash_chip_table[i].mf_id))
|
||
{
|
||
uint8_t status =SpiReadSta();
|
||
status |= SPI_SSI_QE;
|
||
SpiWriteSta(status);
|
||
}
|
||
else if((i<sizeof(flash_chip_table)/sizeof(flash_chip))&&(SFUD_MF_ID_MICRONIX==flash_chip_table[i].mf_id))
|
||
{
|
||
uint8_t status =SpiReadSta();
|
||
status |= SPI_MIC_QE;
|
||
SpiWriteSta(status);
|
||
}
|
||
else
|
||
{
|
||
uint8_t status =SpiReadSta2();
|
||
status |= SPI_QE;
|
||
SpiWriteSta2(status);
|
||
}
|
||
#endif
|
||
SendUartString("Query register information .\n");
|
||
uint8_t status1 = SpiReadSta2();
|
||
if(status1 == 0x42){
|
||
status1&=0XBF;
|
||
udelay(10000);
|
||
SpiWriteSta2(status1);
|
||
udelay(10000);
|
||
SendUartString("Register information query completed .\n");
|
||
}else{
|
||
SendUartString("Flash status is normal .\n");
|
||
}
|
||
SpiReadSta3();
|
||
udelay(10000);
|
||
return 0;
|
||
}
|
||
|
||
#define SPI_READ_MAXLEN BYTESPERPAGE
|
||
|
||
// #define AMT630_BIN_OFFSET 0x41000
|
||
// #define BOOTANIM_BIN_OFFSET 0x341000
|
||
// #define ROM_BIN_OFFSET 0x641000
|
||
// #define NEW_APPFOOSET 0xB00000
|
||
// #define UPDATEFILE_MEDIA_OFFSET 0x40000
|
||
#define AMT630_BIN_OFFSET 0x41000
|
||
#define BOOTANIM_BIN_OFFSET 0x741000//0x501000//0x341000
|
||
#define ROM_BIN_OFFSET 0xb41000//0x801000
|
||
#define NEW_APPFOOSET 0x17F0000//0xb01000
|
||
#define AMT630_BIN_MAX_SIZE 0x700000//0x4c0000
|
||
|
||
#define IMAGE_PAGE_SIZE 0x100
|
||
#define IMAGE_RW_SIZE 0x10000
|
||
#define NEW_APPLDR_CHECKSUM_OFFSET 0x14
|
||
static unsigned int uup_buf_len = 0;
|
||
static unsigned char uup_buf[IMAGE_RW_SIZE];
|
||
int flash_copy_demo(void)
|
||
{
|
||
uint32_t calchecksum,appchecksum,imageoff,new_appoffset,new_appsize;
|
||
int i,j;
|
||
//unsigned int buf[IMAGE_PAGE_SIZE];
|
||
UINT32 *buf = (UINT32*)IMAGE_ENTRY;
|
||
SysInfo *sysinfo = GetSysInfo();
|
||
int count_max = 0;
|
||
|
||
SendUartString("enter copy flash .\n");
|
||
new_appsize=sysinfo->upgrade_appsize; //根据串口升级的协议获取
|
||
new_appoffset = NEW_APPFOOSET; //升级的程序固定写在这个地址,预留3M
|
||
int uup_file_type = sysinfo->reserved[9];
|
||
if(uup_file_type == UPFILE_TYPE_APP){
|
||
imageoff = AMT630_BIN_OFFSET; //固定的 运行区固定地址
|
||
}else if(uup_file_type == UPFILE_TYPE_ANIMATION){
|
||
imageoff = BOOTANIM_BIN_OFFSET; //固定的 运行区固定地址
|
||
}else if(uup_file_type == UPFILE_TYPE_RESOURCE){
|
||
imageoff = ROM_BIN_OFFSET;
|
||
}
|
||
//imageoff = AMT630_BIN_OFFSET; //固定的 运行区固定地址
|
||
|
||
SendUartString("start copy flash ok.\n");
|
||
|
||
//SpiReadPage(NEW_APPFOOSET / BYTESPERPAGE, buf);
|
||
count_max = new_appsize/IMAGE_RW_SIZE;
|
||
PrintVariableValueHex("max i ", count_max);
|
||
for(i=0;i<count_max;i++)
|
||
{
|
||
// PrintVariableValueHex("i", i);
|
||
// PrintVariableValueHex("update_progress_set ", (i*100 / count_max));
|
||
update_progress_set(i*100 / count_max);
|
||
//读取
|
||
for(j=0;j<256;j++){
|
||
SpiReadPage((new_appoffset/BYTESPERPAGE)+j ,buf);
|
||
memcpy(uup_buf + uup_buf_len, buf, BYTESPERPAGE);
|
||
uup_buf_len += BYTESPERPAGE;
|
||
}
|
||
//擦写
|
||
SpiNorBurn(uup_buf, imageoff+IMAGE_RW_SIZE*i, IMAGE_RW_SIZE, 0);
|
||
|
||
uup_buf_len = 0;
|
||
new_appoffset += IMAGE_RW_SIZE;
|
||
if(i==0)
|
||
{
|
||
if (uup_file_type == UPFILE_TYPE_APP) {//代码文件
|
||
unsigned int *tmp = (unsigned int *)(uup_buf + NEW_APPLDR_CHECKSUM_OFFSET);
|
||
appchecksum=*tmp;
|
||
*tmp = 0;
|
||
}else if (uup_file_type == UPFILE_TYPE_ANIMATION) {//动画文件
|
||
BANIHEADER *pheader = (BANIHEADER *)uup_buf;
|
||
appchecksum = pheader->checksum;
|
||
pheader->checksum = 0;
|
||
}else if (uup_file_type == UPFILE_TYPE_RESOURCE) {//资源文件
|
||
RomHeader *pheader = (RomHeader *)uup_buf;
|
||
appchecksum = pheader->checksum;
|
||
pheader->checksum = 0;
|
||
}
|
||
// unsigned int *tmp = (unsigned int *)(uup_buf + NEW_APPLDR_CHECKSUM_OFFSET);
|
||
// appchecksum=*tmp;
|
||
// *tmp=0;
|
||
calchecksum = xcrc32(uup_buf, IMAGE_RW_SIZE, 0xffffffff);
|
||
PrintVariableValueHex("appchecksum ", appchecksum);
|
||
PrintVariableValueHex("calchecksum ", calchecksum);
|
||
}
|
||
else
|
||
{
|
||
calchecksum = xcrc32(uup_buf, IMAGE_RW_SIZE, calchecksum);
|
||
// PrintVariableValueHex("calchecksum", calchecksum);
|
||
}
|
||
}
|
||
if(new_appsize%IMAGE_RW_SIZE)//若最后一包数据不满0x10000 则存数据并且继续计算校验和
|
||
{
|
||
// PrintVariableValueHex("update_progress_set ", 99);
|
||
update_progress_set(99);
|
||
uint32_t red_add,wri_add,size,count;
|
||
int k;
|
||
uup_buf_len = 0;
|
||
count = (new_appsize%IMAGE_RW_SIZE )/0x1000;
|
||
red_add = NEW_APPFOOSET+new_appsize- new_appsize%IMAGE_RW_SIZE;
|
||
wri_add = imageoff+new_appsize- new_appsize%IMAGE_RW_SIZE;
|
||
size = 0x1000;
|
||
// PrintVariableValueHex("max k ", count);
|
||
for(k=0;k<count;k++){
|
||
|
||
for(j=0;j<16;j++){
|
||
SpiReadPage(red_add/BYTESPERPAGE+j,buf);
|
||
memcpy(uup_buf + uup_buf_len, buf, BYTESPERPAGE);
|
||
uup_buf_len += BYTESPERPAGE;
|
||
}
|
||
//擦写
|
||
SpiNorBurn(uup_buf, wri_add, size, 0);
|
||
uup_buf_len = 0;
|
||
// PrintVariableValueHex("k", k);
|
||
//PrintVariableValueHex("red_add ", red_add);
|
||
//PrintVariableValueHex("wri_add ", wri_add);
|
||
calchecksum = xcrc32(uup_buf, size, calchecksum);
|
||
// PrintVariableValueHex("calchecksum", calchecksum);
|
||
red_add +=size;
|
||
wri_add +=size;
|
||
}
|
||
|
||
if(sysinfo->upgrade_flag){//若最后一包数据不满0x1000 则存数据并且继续计算校验和
|
||
uint32_t add,add_size;
|
||
add = sysinfo->upgrade_flag/256;
|
||
add_size = sysinfo->upgrade_flag%256;
|
||
uup_buf_len = 0;
|
||
for(j=0;j<add;j++){
|
||
SpiReadPage(red_add/BYTESPERPAGE +j,buf);
|
||
memcpy(uup_buf + uup_buf_len, buf, BYTESPERPAGE);
|
||
uup_buf_len += BYTESPERPAGE;
|
||
}
|
||
SpiReadPage(red_add/BYTESPERPAGE +j,buf);
|
||
memcpy(uup_buf + uup_buf_len, buf, add_size);
|
||
uup_buf_len += add_size;
|
||
|
||
//擦写
|
||
SpiNorBurn(uup_buf, wri_add, sysinfo->upgrade_flag, 0);
|
||
uup_buf_len = 0;
|
||
|
||
calchecksum = xcrc32(uup_buf, sysinfo->upgrade_flag, calchecksum);
|
||
// PrintVariableValueHex("end calchecksum", calchecksum);
|
||
}
|
||
|
||
}
|
||
// PrintVariableValueHex("update_progress_set ", 100);
|
||
update_progress_set(100);
|
||
// SendUartString("end flash copy.\n");
|
||
|
||
PrintVariableValueHex("calchecksum", calchecksum);
|
||
PrintVariableValueHex("appchecksum", appchecksum);
|
||
|
||
// if(calchecksum==appchecksum)
|
||
// {
|
||
// SendUartString("crc32 OK\n");
|
||
sysinfo = GetSysInfo();
|
||
if (uup_file_type == UPFILE_TYPE_APP) //代码文件
|
||
sysinfo->app_size = new_appsize;
|
||
sysinfo->image_offset=0x40000;
|
||
sysinfo->upgrade_flag = 0;
|
||
sysinfo->upgrade_appsize =0;
|
||
sysinfo->reserved[9] =0;
|
||
SaveSysInfo(sysinfo);
|
||
wdt_cpu_reboot();
|
||
return 0;
|
||
|
||
// }
|
||
// else
|
||
// {
|
||
// SendUartString("crc32 ERROR\n");
|
||
// return -1;
|
||
// }
|
||
|
||
}
|
||
|
||
|
||
static void SpiLoadImage(void (*readfunc)(UINT32, UINT32 *))
|
||
{
|
||
unsigned int i = 0;
|
||
UINT32 *buf = (UINT32*)IMAGE_ENTRY;
|
||
UpFileHeader *header;
|
||
UpFileInfo *appfile;
|
||
UINT32 nPageCount;
|
||
UINT32 nPageStart;
|
||
UINT32 appsize;
|
||
SysInfo *sysinfo = GetSysInfo();
|
||
|
||
PrintVariableValueHex("image_offset", sysinfo->image_offset);
|
||
readfunc(sysinfo->image_offset / BYTESPERPAGE, buf);
|
||
header = (UpFileHeader*)buf;
|
||
appfile = &header->files[0];
|
||
if (appfile->offset & (BYTESPERPAGE - 1)) {
|
||
SendUartString("\nImage positon is not align to flash pagesize, can't load.\r\n");
|
||
while(1);
|
||
}
|
||
|
||
if (sysinfo->app_size)
|
||
appsize = sysinfo->app_size;
|
||
else
|
||
appsize = appfile->size;
|
||
PrintVariableValueHex("appsize", appsize);
|
||
nPageCount = (appsize + BYTESPERPAGE - 1) / BYTESPERPAGE;
|
||
nPageStart = (appfile->offset + sysinfo->image_offset) / BYTESPERPAGE;
|
||
for(i = nPageStart; i < nPageStart + nPageCount; i++)
|
||
{
|
||
readfunc(i, buf);
|
||
buf += BYTESPERPAGE/4;
|
||
}
|
||
|
||
PrintVariableValueHex("upgrade_flag", sysinfo->upgrade_flag);
|
||
PrintVariableValueHex("upgrade_appsize", sysinfo->upgrade_appsize);
|
||
PrintVariableValueHex("checksum", sysinfo->checksum);
|
||
if(sysinfo->upgrade_flag !=0 && sysinfo->upgrade_appsize!=0 ){
|
||
if(sysinfo->upgrade_flag == 0xffffffff && sysinfo->upgrade_appsize == 0xffffffff){
|
||
SysInfo *sysinfo = GetSysInfo();
|
||
sysinfo->upgrade_flag = 0;
|
||
sysinfo->upgrade_appsize =0;
|
||
SaveSysInfo(sysinfo);
|
||
}else{
|
||
lcd_init();
|
||
wdt_stop();
|
||
SendUartString("update_logo_init... \r\n");
|
||
update_logo_init();
|
||
SendUartString("PWM2 .\r\n");
|
||
gpio_direction_output(6,1);
|
||
flash_copy_demo();
|
||
wdt_start();
|
||
}
|
||
}
|
||
|
||
#ifdef MMU_ENABLE
|
||
CP15_clean_dcache_for_dma(IMAGE_ENTRY, IMAGE_ENTRY + appsize);
|
||
#endif
|
||
}
|
||
|
||
static void SpiWriteEnable(void)
|
||
{
|
||
SetSpiDataMode(8);
|
||
SetCSGpioEnable(1);
|
||
rSPI_DR = SPI_WRITE_ENABLE;
|
||
SpiWaitIdle();
|
||
SetCSGpioEnable(0);
|
||
while((SpiReadSta() & SPI_BUSY));
|
||
while(!(SpiReadSta() & SPIFLASH_WRITEENABLE));
|
||
SetSpiDataMode(32);
|
||
}
|
||
|
||
static void SpiEraseSector(UINT32 sectorNum)
|
||
{
|
||
UINT32 addr;
|
||
UINT8 tmpaddr[4];
|
||
|
||
addr = BYTESPERSECTOR*sectorNum;
|
||
tmpaddr[0] = addr;
|
||
tmpaddr[1] = addr>>8;
|
||
tmpaddr[2] = addr>>16;
|
||
tmpaddr[3] = addr>>24;
|
||
|
||
SpiWriteEnable();
|
||
SetCSGpioEnable(1);
|
||
if (addr_in_4_byte) {
|
||
SetSpiDataMode(8);
|
||
rSPI_DR = SPI_4BYTEADD_SECTOR_ERASE;
|
||
rSPI_DR = tmpaddr[3];
|
||
rSPI_DR = tmpaddr[2];
|
||
rSPI_DR = tmpaddr[1];
|
||
rSPI_DR = tmpaddr[0];
|
||
} else {
|
||
rSPI_DR = (tmpaddr[0]<<24) | (tmpaddr[1]<<16) | (tmpaddr[2]<<8) | SPI_SECTOR_ERASE;
|
||
}
|
||
SpiWaitIdle();
|
||
SetCSGpioEnable(0);
|
||
while((SpiReadSta() & SPIFLASH_WRITEENABLE));
|
||
}
|
||
|
||
static void SpiEraseBlock(UINT32 blockNum)
|
||
{
|
||
UINT32 addr;
|
||
UINT8 tmpaddr[4];
|
||
|
||
addr = BYTESPERBLOCK*blockNum;
|
||
tmpaddr[0] = addr;
|
||
tmpaddr[1] = addr>>8;
|
||
tmpaddr[2] = addr>>16;
|
||
tmpaddr[3] = addr>>24;
|
||
|
||
SpiWriteEnable();
|
||
SetCSGpioEnable(1);
|
||
if (addr_in_4_byte) {
|
||
SetSpiDataMode(8);
|
||
rSPI_DR = SPI_4BYTEADD_BLOCK_ERASE;
|
||
rSPI_DR = tmpaddr[3];
|
||
rSPI_DR = tmpaddr[2];
|
||
rSPI_DR = tmpaddr[1];
|
||
rSPI_DR = tmpaddr[0];
|
||
} else {
|
||
rSPI_DR = (tmpaddr[0]<<24) | (tmpaddr[1]<<16) | (tmpaddr[2]<<8) | SPI_BLOCK_ERASE;
|
||
}
|
||
SpiWaitIdle();
|
||
SetCSGpioEnable(0);
|
||
while((SpiReadSta() & SPIFLASH_WRITEENABLE));
|
||
}
|
||
|
||
static void SpiWritePage(UINT32 pagenum, UINT32 *buf)
|
||
{
|
||
UINT32 addr;
|
||
UINT32 val = 0;;
|
||
INT32 i;
|
||
UINT8 tmpaddr[4];
|
||
UINT8 *data = (UINT8*)buf;
|
||
|
||
(void)val;
|
||
|
||
addr = pagenum*BYTESPERPAGE;
|
||
tmpaddr[0] = addr;
|
||
tmpaddr[1] = addr>>8;
|
||
tmpaddr[2] = addr>>16;
|
||
tmpaddr[3] = addr>>24;
|
||
|
||
SpiWriteEnable();
|
||
SetCSGpioEnable(1);
|
||
if (addr_in_4_byte) {
|
||
SetSpiDataMode(8);
|
||
rSPI_DR = SPI_4BYTEADD_PAGE_PROGRAM;
|
||
rSPI_DR = tmpaddr[3];
|
||
rSPI_DR = tmpaddr[2];
|
||
rSPI_DR = tmpaddr[1];
|
||
rSPI_DR = tmpaddr[0];
|
||
} else {
|
||
rSPI_DR = (tmpaddr[0]<<24) | (tmpaddr[1]<<16) | (tmpaddr[2]<<8) | SPI_PAGE_PROGRAM;
|
||
}
|
||
|
||
if (addr_in_4_byte) {
|
||
for (i = 0; i < BYTESPERPAGE; i++) {
|
||
while(!(rSPI_SR & SPI_TXFIFO_NOTFULL));
|
||
rSPI_DR = *data++;
|
||
}
|
||
} else {
|
||
for (i = 0; i < WORDSPERPAGE; i++) {
|
||
while(!(rSPI_SR & SPI_TXFIFO_NOTFULL));
|
||
rSPI_DR = *buf++;
|
||
}
|
||
}
|
||
SpiWaitIdle();
|
||
SetCSGpioEnable(0);
|
||
while(SpiReadSta() & SPI_BUSY);
|
||
}
|
||
|
||
void bootFromSPI(void)
|
||
{
|
||
void (*funPtr)(void);
|
||
|
||
#ifdef SPI0_QSPI_MODE
|
||
SpiLoadImage(SpiReadPageQuadMode);
|
||
#else
|
||
SpiLoadImage(SpiReadPage);
|
||
#endif
|
||
|
||
funPtr = (void (*)(void))IMAGE_ENTRY;
|
||
funPtr();
|
||
}
|
||
|
||
static unsigned int pagecheck[WORDSPERPAGE];
|
||
/* offset is at least align to SECOTR_SIZE */
|
||
int SpiNorBurnPage(int pagenum, unsigned int *buf)
|
||
{
|
||
int timeout = 3;
|
||
unsigned int *tmp = (unsigned int *)buf;
|
||
int i;
|
||
|
||
retry:
|
||
SpiWritePage(pagenum, buf);
|
||
SpiReadPage(pagenum, pagecheck);
|
||
for (i = 0; i < WORDSPERPAGE; i++) {
|
||
if (tmp[i] != pagecheck[i]) {
|
||
if (timeout-- > 0) {
|
||
PrintVariableValueHex("write: ", tmp[i]);
|
||
PrintVariableValueHex("read: ", pagecheck[i]);
|
||
SendUartString("burn check data fail, retry...\r\n");
|
||
goto retry;
|
||
} else {
|
||
SendUartString("burn error!\r\n");
|
||
return -1;
|
||
}
|
||
}
|
||
}
|
||
|
||
return 0;
|
||
}
|
||
|
||
/* offset is at least align to SECOTR_SIZE */
|
||
int SpiNorBurn(void *buf, unsigned int offset, unsigned int size, int show_progress)
|
||
{
|
||
int i, j;
|
||
int secstart, secnum;
|
||
int blkstart, blknum;
|
||
int pagestart, pagenum, pageburned;
|
||
int remain = size;
|
||
unsigned int *pbuf = (unsigned int *)buf;
|
||
|
||
pagestart = offset / BYTESPERPAGE;
|
||
pagenum = (size + BYTESPERPAGE - 1) / BYTESPERPAGE;
|
||
pageburned = 0;
|
||
|
||
while (remain > 0) {
|
||
unsigned int tmp = offset & (BYTESPERBLOCK - 1);
|
||
if (tmp) {
|
||
tmp = (BYTESPERBLOCK - tmp) / BYTESPERSECTOR;
|
||
secnum = (remain + BYTESPERSECTOR - 1) / BYTESPERSECTOR;
|
||
secnum = min(tmp, secnum);
|
||
secstart = offset / BYTESPERSECTOR;
|
||
for (i = 0; i < secnum; i++) {
|
||
SpiEraseSector(secstart + i);
|
||
for (j = 0; j < PAGESPERSECTORS; j++) {
|
||
if (SpiNorBurnPage(pagestart + j, pbuf))
|
||
return -1;
|
||
pbuf += WORDSPERPAGE;
|
||
pageburned++;
|
||
remain -= BYTESPERPAGE;
|
||
if (remain <= 0) goto finish;
|
||
if (show_progress)
|
||
update_progress_set(pageburned * 100 / pagenum);
|
||
}
|
||
pagestart += PAGESPERSECTORS;
|
||
}
|
||
offset += secnum * BYTESPERSECTOR;
|
||
} else {
|
||
blkstart = offset / BYTESPERBLOCK;
|
||
blknum = remain / BYTESPERBLOCK;
|
||
for (i = 0; i < blknum; i++) {
|
||
SpiEraseBlock(blkstart + i);
|
||
for (j = 0; j < PAGESPERSECTORS * SECTORSPERBLOCK; j++) {
|
||
if (SpiNorBurnPage(pagestart + j, pbuf))
|
||
return -1;
|
||
pbuf += WORDSPERPAGE;
|
||
pageburned++;
|
||
remain -= BYTESPERPAGE;
|
||
if (remain <= 0) goto finish;
|
||
if (show_progress)
|
||
update_progress_set(pageburned * 100 / pagenum);
|
||
}
|
||
pagestart += PAGESPERSECTORS * SECTORSPERBLOCK;
|
||
}
|
||
offset += blknum * BYTESPERBLOCK;
|
||
if (remain > 0) {
|
||
secstart = offset / BYTESPERSECTOR;
|
||
secnum = (remain + BYTESPERSECTOR - 1) / BYTESPERSECTOR;
|
||
for (i = 0; i < secnum; i++) {
|
||
SpiEraseSector(secstart + i);
|
||
for (j = 0; j < PAGESPERSECTORS; j++) {
|
||
if (SpiNorBurnPage(pagestart + j, pbuf))
|
||
return -1;
|
||
pbuf += WORDSPERPAGE;
|
||
pageburned++;
|
||
remain -= BYTESPERPAGE;
|
||
if (remain <= 0) goto finish;
|
||
if (show_progress)
|
||
update_progress_set(pageburned * 100 / pagenum);
|
||
}
|
||
pagestart += PAGESPERSECTORS;
|
||
}
|
||
offset += secnum * BYTESPERSECTOR;
|
||
}
|
||
}
|
||
}
|
||
|
||
finish:
|
||
if (show_progress)
|
||
update_progress_set(100);
|
||
|
||
return 0;
|
||
}
|
||
|
||
int FlashBurn(void *buf, unsigned int offset, unsigned int size, int show_progress)
|
||
{
|
||
return SpiNorBurn(buf, offset, size, show_progress);
|
||
}
|
||
|
||
int SpiReadSysInfo(SysInfo *info)
|
||
{
|
||
UINT32 *buf = (UINT32*)IMAGE_ENTRY;
|
||
int pagestart;
|
||
int pagenum;
|
||
UINT32 checksum;
|
||
UINT32 calc_checksum;
|
||
int i;
|
||
|
||
pagestart = SYSINFOA_OFFSET / BYTESPERPAGE;
|
||
pagenum = (sizeof(SysInfo) + BYTESPERPAGE - 1) / BYTESPERPAGE;
|
||
for(i = pagestart; i < pagestart + pagenum; i++)
|
||
{
|
||
SpiReadPage(i, buf);
|
||
buf += BYTESPERPAGE/4;
|
||
}
|
||
|
||
checksum = *(UINT32*)(IMAGE_ENTRY + sizeof(SysInfo) - 4);
|
||
calc_checksum = xcrc32((unsigned char*)IMAGE_ENTRY, sizeof(SysInfo) - 4, 0xffffffff);
|
||
if (calc_checksum == checksum) {
|
||
memcpy(info, (void*)IMAGE_ENTRY, sizeof(SysInfo));
|
||
return 0;
|
||
}
|
||
|
||
buf = (UINT32*)IMAGE_ENTRY;
|
||
pagestart = SYSINFOB_OFFSET / BYTESPERPAGE;
|
||
for(i = pagestart; i < pagestart + pagenum; i++)
|
||
{
|
||
SpiReadPage(i, buf);
|
||
buf += BYTESPERPAGE/4;
|
||
}
|
||
|
||
checksum = *(UINT32*)(IMAGE_ENTRY + sizeof(SysInfo) - 4);
|
||
calc_checksum = xcrc32((unsigned char*)IMAGE_ENTRY, sizeof(SysInfo) - 4, 0xffffffff);
|
||
if (calc_checksum == checksum) {
|
||
memcpy(info, (void*)IMAGE_ENTRY, sizeof(SysInfo));
|
||
return 0;
|
||
}
|
||
|
||
return -1;
|
||
}
|
||
|
||
void SpiWriteSysInfo(SysInfo *info)
|
||
{
|
||
SpiNorBurn(info, SYSINFOB_OFFSET, sizeof(SysInfo), 0);
|
||
SpiNorBurn(info, SYSINFOA_OFFSET, sizeof(SysInfo), 0);
|
||
}
|
||
|
||
unsigned int SpiGetUpfileOffset(int type)
|
||
{
|
||
SysInfo *sysinfo = GetSysInfo();
|
||
|
||
if (type == UPFILE_TYPE_WHOLE) {
|
||
if (sysinfo->image_offset == IMAGE_OFFSET)
|
||
sysinfo->image_offset = IMAGEB_OFFSET;
|
||
else
|
||
sysinfo->image_offset = IMAGE_OFFSET;
|
||
return sysinfo->image_offset;
|
||
} else if (type == UPFILE_TYPE_FIRSTLDR) {
|
||
return LOADER_OFFSET;
|
||
} else if (type == UPFILE_TYPE_STEPLDR) {
|
||
if (sysinfo->stepldr_offset == STEPLDRA_OFFSET)
|
||
sysinfo->stepldr_offset = STEPLDRB_OFFSET;
|
||
else
|
||
sysinfo->stepldr_offset = STEPLDRA_OFFSET;
|
||
return sysinfo->stepldr_offset;
|
||
} else {
|
||
unsigned int buf[WORDSPERPAGE];
|
||
UpFileHeader *header;
|
||
UpFileInfo *appfile;
|
||
unsigned int offset;
|
||
int i;
|
||
|
||
SpiReadPage(sysinfo->image_offset / BYTESPERPAGE, buf);
|
||
header = (UpFileHeader*)buf;
|
||
if (header->magic != MKTAG('U', 'P', 'D', 'F')) {
|
||
SendUartString("old update file isn't found in flash, can't support module update.\n");
|
||
return 0xffffffff;
|
||
}
|
||
for (i = 0; i < header->filenum; i++) {
|
||
appfile = &header->files[i];
|
||
if ((appfile->magic == UPFILE_APP_MAGIC && type == UPFILE_TYPE_APP) ||
|
||
(appfile->magic == MKTAG('R', 'O', 'M', 'A') && type == UPFILE_TYPE_RESOURCE) ||
|
||
(appfile->magic == MKTAG('B', 'A', 'N', 'I') && type == UPFILE_TYPE_ANIMATION)) {
|
||
offset = appfile->offset;
|
||
if (offset & (BYTESPERSECTOR - 1)) {
|
||
SendUartString("offset isn't align to sector erase size, can't support module update.\n");
|
||
return 0xffffffff;
|
||
}
|
||
return offset + sysinfo->image_offset;
|
||
}
|
||
}
|
||
}
|
||
|
||
return 0xffffffff;
|
||
}
|
||
#endif
|