2013-04-08 21:30:33 +02:00
|
|
|
|
/*****************************************************************************
|
|
|
|
|
*
|
|
|
|
|
* Copyright(C) 2011, Embedded Artists AB
|
|
|
|
|
* All rights reserved.
|
|
|
|
|
*
|
|
|
|
|
******************************************************************************
|
|
|
|
|
* Software that is described herein is for illustrative purposes only
|
|
|
|
|
* which provides customers with programming information regarding the
|
|
|
|
|
* products. This software is supplied "AS IS" without any warranties.
|
|
|
|
|
* Embedded Artists AB assumes no responsibility or liability for the
|
|
|
|
|
* use of the software, conveys no license or title under any patent,
|
|
|
|
|
* copyright, or mask work right to the product. Embedded Artists AB
|
|
|
|
|
* reserves the right to make changes in the software without
|
|
|
|
|
* notification. Embedded Artists AB also make no representation or
|
|
|
|
|
* warranty that such application will be suitable for the specified
|
|
|
|
|
* use without further testing or modification.
|
|
|
|
|
*****************************************************************************/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
|
|
|
* Includes
|
|
|
|
|
*****************************************************************************/
|
2018-03-02 08:53:40 +01:00
|
|
|
|
#include "../../board.h"
|
2014-03-19 12:12:51 +01:00
|
|
|
|
|
|
|
|
|
#if BOARD == BOARD_EA4357
|
2013-04-08 21:30:33 +02:00
|
|
|
|
|
|
|
|
|
#include "lpc_types.h"
|
|
|
|
|
#include "lpc43xx_scu.h"
|
|
|
|
|
#include "lpc43xx_timer.h"
|
2013-04-22 06:22:56 +02:00
|
|
|
|
#include "norflash.h"
|
2013-04-08 21:30:33 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
|
|
|
* Defines and typedefs
|
|
|
|
|
*****************************************************************************/
|
|
|
|
|
|
|
|
|
|
#define CMD_SWID 0x90
|
|
|
|
|
#define CMD_CFI_QRY 0x98
|
|
|
|
|
#define CMD_ID_EXIT 0xF0
|
|
|
|
|
|
|
|
|
|
#define CMD_ERASE_BLOCK 0x0050
|
|
|
|
|
#define CMD_ERASE_SECTOR 0x0030
|
|
|
|
|
#define CMD_ERASE_CHIP 0x0010
|
|
|
|
|
|
|
|
|
|
#define MAN_ID_SST 0x00BF
|
|
|
|
|
#define DEV_ID_SST39VF3201 0x235B
|
|
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
|
|
|
* External global variables
|
|
|
|
|
*****************************************************************************/
|
|
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
|
|
|
* Local variables
|
|
|
|
|
*****************************************************************************/
|
|
|
|
|
|
|
|
|
|
static geometry_t chip_info;
|
|
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
|
|
|
* Local Functions
|
|
|
|
|
*****************************************************************************/
|
|
|
|
|
|
|
|
|
|
static void pinConfig(void)
|
|
|
|
|
{
|
|
|
|
|
/* Set up EMC pin */
|
|
|
|
|
scu_pinmux( 2 , 9 , MD_PLN_FAST , 3 );//A0
|
|
|
|
|
scu_pinmux( 2 , 10 , MD_PLN_FAST , 3 );//A1
|
|
|
|
|
scu_pinmux( 2 , 11 , MD_PLN_FAST , 3 );//A2
|
|
|
|
|
scu_pinmux( 2 , 12 , MD_PLN_FAST , 3 );//A3
|
|
|
|
|
scu_pinmux( 2 , 13 , MD_PLN_FAST , 3 );//A4
|
|
|
|
|
scu_pinmux( 1 , 0 , MD_PLN_FAST , 2 );//A5
|
|
|
|
|
scu_pinmux( 1 , 1 , MD_PLN_FAST , 2 );//A6
|
|
|
|
|
scu_pinmux( 1 , 2 , MD_PLN_FAST , 2 );//A7
|
|
|
|
|
scu_pinmux( 2 , 8 , MD_PLN_FAST , 3 );//A8
|
|
|
|
|
scu_pinmux( 2 , 7 , MD_PLN_FAST , 3 );//A9
|
|
|
|
|
scu_pinmux( 2 , 6 , MD_PLN_FAST , 2 );//A10
|
|
|
|
|
scu_pinmux( 2 , 2 , MD_PLN_FAST , 2 );//A11
|
|
|
|
|
scu_pinmux( 2 , 1 , MD_PLN_FAST , 2 );//A12
|
|
|
|
|
scu_pinmux( 2 , 0 , MD_PLN_FAST , 2 );//A13
|
|
|
|
|
scu_pinmux( 6 , 8 , MD_PLN_FAST , 1 );//A14
|
|
|
|
|
scu_pinmux( 6 , 7 , MD_PLN_FAST , 1 );//A15
|
|
|
|
|
scu_pinmux( 13 , 16 , MD_PLN_FAST , 2 );//A16
|
|
|
|
|
scu_pinmux( 13 , 15 , MD_PLN_FAST , 2 );//A17
|
|
|
|
|
scu_pinmux( 14 , 0 , MD_PLN_FAST , 3 );//A18
|
|
|
|
|
scu_pinmux( 14 , 1 , MD_PLN_FAST , 3 );//A19
|
|
|
|
|
scu_pinmux( 14 , 2 , MD_PLN_FAST , 3 );//A20
|
|
|
|
|
scu_pinmux( 14 , 3 , MD_PLN_FAST , 3 );//A21
|
|
|
|
|
scu_pinmux( 14 , 4 , MD_PLN_FAST , 3 );//A22
|
|
|
|
|
scu_pinmux( 10 , 4 , MD_PLN_FAST , 3 );//A23
|
|
|
|
|
|
|
|
|
|
scu_pinmux( 1 , 7 , MD_PLN_FAST , 3 );//D0
|
|
|
|
|
scu_pinmux( 1 , 8 , MD_PLN_FAST , 3 );//D1
|
|
|
|
|
scu_pinmux( 1 , 9 , MD_PLN_FAST , 3 );//D2
|
|
|
|
|
scu_pinmux( 1 , 10 , MD_PLN_FAST , 3 );//D3
|
|
|
|
|
scu_pinmux( 1 , 11 , MD_PLN_FAST , 3 );//D4
|
|
|
|
|
scu_pinmux( 1 , 12 , MD_PLN_FAST , 3 );//D5
|
|
|
|
|
scu_pinmux( 1 , 13 , MD_PLN_FAST , 3 );//D6
|
|
|
|
|
scu_pinmux( 1 , 14 , MD_PLN_FAST , 3 );//D7
|
|
|
|
|
scu_pinmux( 5 , 4 , MD_PLN_FAST , 2 );//D8
|
|
|
|
|
scu_pinmux( 5 , 5 , MD_PLN_FAST , 2 );//D9
|
|
|
|
|
scu_pinmux( 5 , 6 , MD_PLN_FAST , 2 );//D10
|
|
|
|
|
scu_pinmux( 5 , 7 , MD_PLN_FAST , 2 );//D11
|
|
|
|
|
scu_pinmux( 5 , 0 , MD_PLN_FAST , 2 );//D12
|
|
|
|
|
scu_pinmux( 5 , 1 , MD_PLN_FAST , 2 );//D13
|
|
|
|
|
scu_pinmux( 5 , 2 , MD_PLN_FAST , 2 );//D14
|
|
|
|
|
scu_pinmux( 5 , 3 , MD_PLN_FAST , 2 );//D15
|
|
|
|
|
scu_pinmux( 13 , 2 , MD_PLN_FAST , 2 );//D16
|
|
|
|
|
scu_pinmux( 13 , 3 , MD_PLN_FAST , 2 );//D17
|
|
|
|
|
scu_pinmux( 13 , 4 , MD_PLN_FAST , 2 );//D18
|
|
|
|
|
scu_pinmux( 13 , 5 , MD_PLN_FAST , 2 );//D19
|
|
|
|
|
scu_pinmux( 13 , 6 , MD_PLN_FAST , 2 );//D20
|
|
|
|
|
scu_pinmux( 13 , 7 , MD_PLN_FAST , 2 );//D21
|
|
|
|
|
scu_pinmux( 13 , 8 , MD_PLN_FAST , 2 );//D22
|
|
|
|
|
scu_pinmux( 13 , 9 , MD_PLN_FAST , 2 );//D23
|
|
|
|
|
scu_pinmux( 14 , 5 , MD_PLN_FAST , 3 );//D24
|
|
|
|
|
scu_pinmux( 14 , 6 , MD_PLN_FAST , 3 );//D25
|
|
|
|
|
scu_pinmux( 14 , 7 , MD_PLN_FAST , 3 );//D26
|
|
|
|
|
scu_pinmux( 14 , 8 , MD_PLN_FAST , 3 );//D27
|
|
|
|
|
scu_pinmux( 14 , 9 , MD_PLN_FAST , 3 );//D28
|
|
|
|
|
scu_pinmux( 14 , 10 , MD_PLN_FAST , 3 );//D29
|
|
|
|
|
scu_pinmux( 14 , 11 , MD_PLN_FAST , 3 );//D30
|
|
|
|
|
scu_pinmux( 14 , 12 , MD_PLN_FAST , 3 );//D31
|
|
|
|
|
|
|
|
|
|
scu_pinmux( 1 , 3 , MD_PLN_FAST , 3 );//OE
|
|
|
|
|
scu_pinmux( 1 , 6 , MD_PLN_FAST , 3 );//WE
|
|
|
|
|
|
|
|
|
|
scu_pinmux( 1 , 4 , MD_PLN_FAST , 3 );//BLS0
|
|
|
|
|
scu_pinmux( 6 , 6 , MD_PLN_FAST , 1 );//BLS1
|
|
|
|
|
scu_pinmux( 13 , 13 , MD_PLN_FAST , 2 );//BLS2
|
|
|
|
|
scu_pinmux( 13 , 10 , MD_PLN_FAST , 2 );//BLS3
|
|
|
|
|
|
|
|
|
|
scu_pinmux( 1 , 5 , MD_PLN_FAST , 3 );//CS0
|
|
|
|
|
scu_pinmux( 6 , 3 , MD_PLN_FAST , 3 );//CS1
|
|
|
|
|
scu_pinmux( 13 , 12 , MD_PLN_FAST , 2 );//CS2
|
|
|
|
|
scu_pinmux( 13 , 11 , MD_PLN_FAST , 2 );//CS3
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
|
static void getIdString(uint16_t idString[11])
|
|
|
|
|
{
|
|
|
|
|
int i = 0;
|
|
|
|
|
|
|
|
|
|
*(GET_ADDR(0x5555)) = 0x00AA;
|
|
|
|
|
*(GET_ADDR(0x2aaa)) = 0x0055;
|
|
|
|
|
*(GET_ADDR(0x5555)) = CMD_CFI_QRY;
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < 11; i++) {
|
|
|
|
|
idString[i] = *(GET_ADDR(0x10 + i));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
*(GET_ADDR(0x5555)) = 0x00AA;
|
|
|
|
|
*(GET_ADDR(0x2aaa)) = 0x0055;
|
|
|
|
|
*(GET_ADDR(0x5555)) = CMD_ID_EXIT;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
static void getGeoInfo(uint16_t info[14])
|
|
|
|
|
{
|
|
|
|
|
int i = 0;
|
|
|
|
|
|
|
|
|
|
*(GET_ADDR(0x5555)) = 0x00AA;
|
|
|
|
|
*(GET_ADDR(0x2aaa)) = 0x0055;
|
|
|
|
|
*(GET_ADDR(0x5555)) = CMD_CFI_QRY;
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < 14; i++) {
|
|
|
|
|
info[i] = *(GET_ADDR(0x27 + i));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
*(GET_ADDR(0x5555)) = 0x00AA;
|
|
|
|
|
*(GET_ADDR(0x2aaa)) = 0x0055;
|
|
|
|
|
*(GET_ADDR(0x5555)) = CMD_ID_EXIT;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static uint32_t getProductId(void)
|
|
|
|
|
{
|
|
|
|
|
uint16_t manuid = 0;
|
|
|
|
|
uint16_t devid = 0;
|
|
|
|
|
uint32_t result = 0;
|
|
|
|
|
|
|
|
|
|
*(GET_ADDR(0x5555)) = 0x00AA;
|
|
|
|
|
*(GET_ADDR(0x2aaa)) = 0x0055;
|
|
|
|
|
*(GET_ADDR(0x5555)) = CMD_SWID;
|
|
|
|
|
|
|
|
|
|
manuid = *(GET_ADDR(0x00));
|
|
|
|
|
devid = *(GET_ADDR(0x01));
|
|
|
|
|
|
|
|
|
|
result = ((manuid << 16) | devid);
|
|
|
|
|
|
|
|
|
|
*(GET_ADDR(0x5555)) = 0x00AA;
|
|
|
|
|
*(GET_ADDR(0x2aaa)) = 0x0055;
|
|
|
|
|
*(GET_ADDR(0x5555)) = CMD_ID_EXIT;
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
|
|
|
*
|
|
|
|
|
* Description:
|
|
|
|
|
* When the SST39VF160x/320x are in the internal Program operation, any
|
|
|
|
|
* attempt to read DQ7 will produce the complement of the true data. Once
|
|
|
|
|
* the Program operation is completed, DQ7 will produce true data. Note
|
|
|
|
|
* that even though DQ7 may have valid data immediately following the
|
|
|
|
|
* completion of an internal Write operation, the remaining data outputs
|
|
|
|
|
* may still be invalid: valid data on the entire data bus will appear in
|
|
|
|
|
* subsequent successive Read cycles after an interval of 1 <EFBFBD>s. During
|
|
|
|
|
* internal Erase operation, any attempt to read DQ7 will produce a '0'.
|
|
|
|
|
* Once the internal Erase operation is completed, DQ7 will produce a '1'.
|
|
|
|
|
*
|
|
|
|
|
* Parameters:
|
|
|
|
|
* addr The device address
|
|
|
|
|
* data The original (true) data
|
|
|
|
|
* timeout Maximum number of loops to delay
|
|
|
|
|
*
|
|
|
|
|
* Returns:
|
|
|
|
|
* TRUE if success
|
|
|
|
|
*
|
|
|
|
|
*****************************************************************************/
|
|
|
|
|
static uint16_t check_data_polling(uint32_t addr, uint16_t data, uint32_t timeout)
|
|
|
|
|
{
|
|
|
|
|
volatile uint16_t *p = (uint16_t*) addr;
|
|
|
|
|
uint16_t true_data = data & 0x80;
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < timeout; i++)
|
|
|
|
|
{
|
|
|
|
|
if ( true_data == (*p &0x80) )
|
|
|
|
|
{
|
|
|
|
|
TIM_Waitus(1);
|
|
|
|
|
return (TRUE);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return (FALSE);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
|
|
|
*
|
|
|
|
|
* Description:
|
|
|
|
|
* During the internal Program or Erase operation, any consecutive attempts
|
|
|
|
|
* to read DQ6 will produce alternating <EFBFBD>1<EFBFBD>s and <EFBFBD>0<EFBFBD>s, i.e., toggling
|
|
|
|
|
* between 1 and 0. When the internal Program or Erase operation is
|
|
|
|
|
* completed, the DQ6 bit will stop toggling. The device is then ready
|
|
|
|
|
* for the next operation.
|
|
|
|
|
*
|
|
|
|
|
* Parameters:
|
|
|
|
|
* addr The device address
|
|
|
|
|
* timeout Maximum number of loops to delay
|
|
|
|
|
*
|
|
|
|
|
* Returns:
|
|
|
|
|
* TRUE if success
|
|
|
|
|
*
|
|
|
|
|
*****************************************************************************/
|
|
|
|
|
static uint16_t check_toggle_ready(uint32_t addr, uint32_t timeout)
|
|
|
|
|
{
|
|
|
|
|
volatile uint16_t *p = (uint16_t*) addr;
|
|
|
|
|
uint16_t predata, currdata;
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
predata = *p & 0x40;
|
|
|
|
|
for (i = 0; i < timeout; i++)
|
|
|
|
|
{
|
|
|
|
|
currdata = *p & 0x40;
|
|
|
|
|
if (predata == currdata)
|
|
|
|
|
{
|
|
|
|
|
TIM_Waitus(1);
|
|
|
|
|
return (TRUE);
|
|
|
|
|
}
|
|
|
|
|
predata = currdata;
|
|
|
|
|
}
|
|
|
|
|
return (FALSE);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
|
|
|
* Public Functions
|
|
|
|
|
*****************************************************************************/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
|
|
|
*
|
|
|
|
|
* Description:
|
|
|
|
|
* Initialize the NOR Flash
|
|
|
|
|
*
|
|
|
|
|
*****************************************************************************/
|
|
|
|
|
uint32_t norflash_init()
|
|
|
|
|
{
|
|
|
|
|
uint32_t prodId = 0;
|
|
|
|
|
|
|
|
|
|
// LPC_SC->PCONP |= 0x00000800;
|
|
|
|
|
|
|
|
|
|
LPC_EMC->CONTROL = 0x00000001;
|
|
|
|
|
|
|
|
|
|
LPC_EMC->CONFIG = 0x00000000;
|
|
|
|
|
|
|
|
|
|
//Disable Auto-Byte Addressing (on boards designed for LPC24xx)
|
|
|
|
|
//LPC_SC->SCS |= 0x00000001;
|
|
|
|
|
|
|
|
|
|
pinConfig();
|
|
|
|
|
|
|
|
|
|
LPC_EMC->STATICCONFIG0 = 0x00000081;
|
|
|
|
|
|
|
|
|
|
LPC_EMC->STATICWAITWEN0 = 0x00000003; /* ( n + 1 ) -> 4 clock cycles */
|
|
|
|
|
LPC_EMC->STATICWAITOEN0 = 0x00000003; /* ( n ) -> 0 clock cycles */
|
|
|
|
|
LPC_EMC->STATICWAITRD0 = 0x00000006; /* ( n + 1 ) -> 7 clock cycles */
|
|
|
|
|
LPC_EMC->STATICWAITPAG0 = 0x00000003; /* ( n + 1 ) -> 4 clock cycles */
|
|
|
|
|
LPC_EMC->STATICWAITWR0 = 0x00000005; /* ( n + 2 ) -> 7 clock cycles */
|
|
|
|
|
LPC_EMC->STATICWAITTURN0 = 0x00000003; /* ( n + 1 ) -> 4 clock cycles */
|
|
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
|
M32(0x40086400) = 3;//SFSP8_0, pin config P8_0, FUNC3, (PUP_DISABLE | PDN_DISABLE | INBUF_DISABLE | FILTER_ENABLE)
|
|
|
|
|
M32(0x40086404) = 3;//SFSP8_1, pin config P8_1, FUNC3, (PUP_DISABLE | PDN_DISABLE | INBUF_DISABLE | FILTER_ENABLE)
|
|
|
|
|
M32(0x40086408) = 3;//SFSP8_2, pin config P8_2, FUNC3, (PUP_DISABLE | PDN_DISABLE | INBUF_DISABLE | FILTER_ENABLE)
|
|
|
|
|
M32(0x4008640C) = 3;//SFSP8_3, pin config P8_3, FUNC3, (PUP_DISABLE | PDN_DISABLE | SLEWRATE_SLOW | INBUF_DISABLE | FILTER_ENABLE)
|
|
|
|
|
M32(0x40086410) = 3;//SFSP8_4, pin config P8_4, FUNC3, (PUP_DISABLE | PDN_DISABLE | SLEWRATE_SLOW | INBUF_DISABLE | FILTER_ENABLE)
|
|
|
|
|
M32(0x40086414) = 3;//SFSP8_5, pin config P8_5, FUNC3, (PUP_DISABLE | PDN_DISABLE | SLEWRATE_SLOW | INBUF_DISABLE | FILTER_ENABLE)
|
|
|
|
|
M32(0x40086418) = 3;//SFSP8_6, pin config P8_6, FUNC3, (PUP_DISABLE | PDN_DISABLE | SLEWRATE_SLOW | INBUF_DISABLE | FILTER_ENABLE)
|
|
|
|
|
M32(0x4008641C) = 3;//SFSP8_7, pin config P8_7, FUNC3, (PUP_DISABLE | PDN_DISABLE | SLEWRATE_SLOW | INBUF_DISABLE | FILTER_ENABLE)
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
prodId = getProductId();
|
|
|
|
|
|
|
|
|
|
if (prodId == ((MAN_ID_SST << 16) | DEV_ID_SST39VF3201)) {
|
|
|
|
|
|
|
|
|
|
uint16_t info[14];
|
|
|
|
|
getGeoInfo(info);
|
|
|
|
|
chip_info.device_size = 1 << info[0];
|
|
|
|
|
chip_info.num_sectors = ((info[7] << 8) | info[6]) + 1;
|
|
|
|
|
chip_info.sector_size = ((info[9] << 8) | info[8]) * 256;
|
|
|
|
|
chip_info.num_blocks = ((info[11] << 8) | info[10]) + 1;
|
|
|
|
|
chip_info.block_size = ((info[13] << 8) | info[12]) * 256;
|
|
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void norflash_getGeometry(geometry_t* geometry)
|
|
|
|
|
{
|
|
|
|
|
*geometry = chip_info;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
uint32_t norflash_eraseSector(uint32_t addr)
|
|
|
|
|
{
|
|
|
|
|
volatile uint16_t* p;
|
|
|
|
|
|
|
|
|
|
*(GET_ADDR(0x5555)) = 0x00AA;
|
|
|
|
|
*(GET_ADDR(0x2AAA)) = 0x0055;
|
|
|
|
|
*(GET_ADDR(0x5555)) = 0x0080;
|
|
|
|
|
*(GET_ADDR(0x5555)) = 0x00AA;
|
|
|
|
|
*(GET_ADDR(0x2AAA)) = 0x0055;
|
|
|
|
|
|
|
|
|
|
p = (uint16_t*) addr;
|
|
|
|
|
*p = CMD_ERASE_SECTOR;
|
|
|
|
|
|
|
|
|
|
return check_data_polling(addr, 0xffff, 500000);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uint32_t norflash_eraseBlock(uint32_t addr)
|
|
|
|
|
{
|
|
|
|
|
volatile uint16_t* p;
|
|
|
|
|
|
|
|
|
|
*(GET_ADDR(0x5555)) = 0x00AA;
|
|
|
|
|
*(GET_ADDR(0x2AAA)) = 0x0055;
|
|
|
|
|
*(GET_ADDR(0x5555)) = 0x0080;
|
|
|
|
|
*(GET_ADDR(0x5555)) = 0x00AA;
|
|
|
|
|
*(GET_ADDR(0x2AAA)) = 0x0055;
|
|
|
|
|
|
|
|
|
|
p = (uint16_t*) addr;
|
|
|
|
|
*p = CMD_ERASE_BLOCK;
|
|
|
|
|
|
|
|
|
|
return check_toggle_ready(addr, 500000);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uint32_t norflash_eraseEntireChip(void)
|
|
|
|
|
{
|
|
|
|
|
*(GET_ADDR(0x5555)) = 0x00AA;
|
|
|
|
|
*(GET_ADDR(0x2AAA)) = 0x0055;
|
|
|
|
|
*(GET_ADDR(0x5555)) = 0x0080;
|
|
|
|
|
*(GET_ADDR(0x5555)) = 0x00AA;
|
|
|
|
|
*(GET_ADDR(0x2AAA)) = 0x0055;
|
|
|
|
|
*(GET_ADDR(0x5555)) = CMD_ERASE_CHIP;
|
|
|
|
|
|
|
|
|
|
return check_toggle_ready(NORFLASH_BASE, 500000);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uint32_t norflash_writeWord(uint32_t addr, uint16_t data)
|
|
|
|
|
{
|
|
|
|
|
volatile uint16_t *p;
|
|
|
|
|
|
|
|
|
|
*(GET_ADDR(0x5555)) = 0x00AA;
|
|
|
|
|
*(GET_ADDR(0x2AAA)) = 0x0055;
|
|
|
|
|
*(GET_ADDR(0x5555)) = 0x00A0;
|
|
|
|
|
|
|
|
|
|
p = (uint16_t*) addr;
|
|
|
|
|
*p = data;
|
|
|
|
|
|
|
|
|
|
return check_toggle_ready(addr, 500000);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uint32_t norflash_writeBuff(uint32_t addr, uint16_t* data, uint16_t len)
|
|
|
|
|
{
|
|
|
|
|
uint16_t i;
|
|
|
|
|
for (i = 0; i < len; i++)
|
|
|
|
|
{
|
|
|
|
|
if (!norflash_writeWord(addr, data[i]))
|
|
|
|
|
{
|
|
|
|
|
return (FALSE);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return (TRUE);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
|
|
|
*
|
|
|
|
|
* Description:
|
|
|
|
|
* Reads the security information from the chip. For an explanation
|
|
|
|
|
* see the user manual.
|
|
|
|
|
*
|
|
|
|
|
* Parameters:
|
|
|
|
|
* SST_SecID The factory programmed security segment
|
|
|
|
|
* User_SecID The user defined security segment
|
|
|
|
|
*
|
|
|
|
|
*****************************************************************************/
|
|
|
|
|
void norflash_secid_read(uint16_t SST_SecID[8], uint16_t User_SecID[8])
|
|
|
|
|
{
|
|
|
|
|
uint16_t i;
|
|
|
|
|
|
|
|
|
|
*(GET_ADDR(0x5555)) = 0x00AA;
|
|
|
|
|
*(GET_ADDR(0x2AAA)) = 0x0055;
|
|
|
|
|
*(GET_ADDR(0x5555)) = 0x0088;
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < 7; i++)
|
|
|
|
|
{
|
|
|
|
|
SST_SecID[i] = *(GET_ADDR(i)); // SST security is 0x00 - 0x07
|
|
|
|
|
User_SecID[i] = *(GET_ADDR(i + 0x10)); // User security is 0x10 - 0x17
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// exit command
|
|
|
|
|
*(GET_ADDR(0x5555)) = CMD_ID_EXIT;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
|
|
|
*
|
|
|
|
|
* Description:
|
|
|
|
|
* Checks if the user defined security segment has been locked or not.
|
|
|
|
|
* See the user manual for more information.
|
|
|
|
|
*
|
|
|
|
|
* Returns:
|
|
|
|
|
* TRUE if the segment is locked
|
|
|
|
|
*
|
|
|
|
|
*****************************************************************************/
|
|
|
|
|
uint32_t norflash_secid_getLockStatus(void)
|
|
|
|
|
{
|
|
|
|
|
uint16_t status;
|
|
|
|
|
|
|
|
|
|
*(GET_ADDR(0x5555)) = 0x00AA;
|
|
|
|
|
*(GET_ADDR(0x2AAA)) = 0x0055;
|
|
|
|
|
*(GET_ADDR(0x5555)) = 0x0088;
|
|
|
|
|
|
|
|
|
|
// read status
|
|
|
|
|
status = *(GET_ADDR(0xff));
|
|
|
|
|
status &= 0x0008;
|
|
|
|
|
|
|
|
|
|
*(GET_ADDR(0x5555)) = 0x00AA;
|
|
|
|
|
*(GET_ADDR(0x2AAA)) = 0x0055;
|
|
|
|
|
*(GET_ADDR(0x5555)) = CMD_ID_EXIT;
|
|
|
|
|
|
|
|
|
|
if (!status)
|
|
|
|
|
return TRUE; // locked
|
|
|
|
|
return FALSE; // not locked
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
|
|
|
*
|
|
|
|
|
* Description:
|
|
|
|
|
* Lock the user security segment. CANNOT BE UNDONE.
|
|
|
|
|
* See the user manual for more information.
|
|
|
|
|
*
|
|
|
|
|
* Returns:
|
|
|
|
|
* TRUE if the segment is locked after programming
|
|
|
|
|
*
|
|
|
|
|
*****************************************************************************/
|
|
|
|
|
uint32_t norflash_secid_lockOut()
|
|
|
|
|
{
|
|
|
|
|
// Code not verified. Use at own risk
|
|
|
|
|
#if 0
|
|
|
|
|
*(GET_ADDR(0x5555)) = 0x00AA;
|
|
|
|
|
*(GET_ADDR(0x2AAA)) = 0x0055;
|
|
|
|
|
*(GET_ADDR(0x5555)) = 0x0085;
|
|
|
|
|
*(GET_ADDR(0x0 )) = 0x0000; // Write 0x0000 to any address
|
|
|
|
|
|
|
|
|
|
if (check_toggle_ready(GET_ADDR(0x0), 500000))
|
|
|
|
|
{
|
|
|
|
|
return norflash_secid_getLockStatus();
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
|
|
|
*
|
|
|
|
|
* Description:
|
|
|
|
|
* Writes data to the user security segment (0x0010 - 0x0017).
|
|
|
|
|
* See the user manual for more information.
|
|
|
|
|
*
|
|
|
|
|
* Parameters:
|
|
|
|
|
* target Must be in the range 0x10 to 0x17
|
|
|
|
|
* data The data to write
|
|
|
|
|
* len The number of words to write
|
|
|
|
|
*
|
|
|
|
|
* Returns:
|
|
|
|
|
* TRUE if the programming was successful
|
|
|
|
|
*
|
|
|
|
|
*****************************************************************************/
|
|
|
|
|
uint32_t norflash_secid_writeWord(uint16_t target, uint16_t* data, uint16_t len)
|
|
|
|
|
{
|
|
|
|
|
// Code not verified. Use at own risk
|
|
|
|
|
#if 0
|
|
|
|
|
uint16_t i;
|
|
|
|
|
|
|
|
|
|
if ((target < 0x10) || (target > 0x17))
|
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
|
|
if ((len > 8) || ((target + len) > 0x17))
|
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < len; i++)
|
|
|
|
|
{
|
|
|
|
|
*(GET_ADDR(0x5555)) = 0x00AA;
|
|
|
|
|
*(GET_ADDR(0x2AAA)) = 0x0055;
|
|
|
|
|
*(GET_ADDR(0x5555)) = 0x00A5;
|
|
|
|
|
*(GET_ADDR(target + i)) = data;
|
|
|
|
|
|
|
|
|
|
data++;
|
|
|
|
|
|
|
|
|
|
/* Read the toggle bit to detect end-of-programming for User Sec ID.
|
|
|
|
|
Do Not use Data# Polling for User_SecID_Word_Program!! */
|
|
|
|
|
if (!check_toggle_ready(GET_ADDR(target + i), 500000))
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
2014-03-19 12:12:51 +01:00
|
|
|
|
#endif
|