lpcware

writing and reading serial flash memory W25Q12BV with a LPC1114

Discussion created by lpcware Employee on Jun 15, 2016
Content originally posted in LPCWare by ALERICO90 on Tue Feb 03 06:30:19 MST 2015
Hello, I have some routines to read and write to a memory made by someone else but I can't find how to make them work properly, here is the code
#include "includes.h"

#define opcodeStatusRegisterRead (0x05)
#define BUSY (1 << 0)
#define WEL (1 << 1)
#define BP0 (1 << 2)
#define BP1 (1 << 3)
#define BP2 (1 << 4)
#define RESERVED (1 << 5)
#define AAI (1 << 6)
#define BPL (1 << 7)
#define opcodeWriteEnable (0x06)
#define opcodeWriteDisable (0x04)
#define opcodeBusyOutputEnable (0x70)
#define opcodeBusyOutputDisable (0x80)
#define opcodeStatusRegisterWriteEnable (0x50)
#define opcodeStatusRegisterWrite (0x01)
#define opcodeReadElectronicSignature (0xab)
#define opcodeReadJedecId (0x9f)
#define opcodeReadId (0x90)

#define opcodeRead (0x03)
#define opcodeFastRead (0x0b)
#define opcodeByteProgram (0x02)
#define opcodeAAIWordProgram (0xad)
#define opcodePageProgram (0x02)
#define opcodeBlockErase (0xd8)
#define opcodeSectorErase (0x20)
#define opcodeChipErase (0xc7)

static uint8_t F25L_manufactory;

static void F25L_ShiftOutAddrWrite(uint8_t opcode, uint32_t addr)
{
SPIShiftDataMSB(opcode);
SPIShiftDataMSB(addr >> 16);
SPIShiftDataMSB(addr >> 8);
SPIShiftDataMSB(addr >> 0);
}

static uint8_t F25L_StatusRegisterRead(void)
{
uint8_t ret;

SPICSLow();
SPIShiftDataMSB(opcodeStatusRegisterRead);
ret = SPISwapDataMSB(0xFF);
SPICSHigh();

return ret;
}

static void F25L_WriteEnable(void)
{
SPICSLow();
SPIShiftDataMSB(opcodeWriteEnable);
SPICSHigh();
}

static void F25L_WriteDisable(void)
{
SPICSLow();
SPIShiftDataMSB(opcodeWriteDisable);
SPICSHigh();
}

#if 0
static void F25L_BusyOutputEnable(void)
{
SPICSLow();
SPISwapDataMSB(opcodeBusyOutputEnable);
SPICSHigh();
}
#endif

#if 0
static void F25L_BusyOutputDisable(void)
{
SPICSLow();
SPISwapDataMSB(opcodeBusyOutputDisable);
SPICSHigh();
}
#endif
static void F25L_StatusRegisterWriteEnable(void)
{
SPICSLow();
SPIShiftDataMSB(opcodeStatusRegisterWriteEnable);
SPICSHigh();
}

static void F25L_StatusRegisterWrite(uint8_t status)
{
F25L_StatusRegisterWriteEnable();

SPICSLow();
SPIShiftDataMSB(opcodeStatusRegisterWrite);
SPIShiftDataMSB(status);
SPICSHigh();
}

extern void F25L_Init(void)
{
/* Deselect the FLASH: Chip Select high */
SPICSHigh();
}

extern void F25L_ReadJedecId(uint8_t *buf)
{
SPISemGet();
SPICSLow();
SPISwapDataMSB(opcodeReadJedecId);
*buf++ = F25L_manufactory = SPISwapDataMSB(0xFF); // Manufactory
*buf++ = SPISwapDataMSB(0xFF); // ID(15~8)
*buf = SPISwapDataMSB(0xFF); // ID(7~0)
SPICSHigh();
SPISemPut();
}

extern void F25L_ReadId(uint8_t *buf)
{
SPISemGet();
SPICSLow();
SPIShiftDataMSB(opcodeReadId);
SPIShiftDataMSB(0);
SPIShiftDataMSB(0);
SPIShiftDataMSB(0);
*buf++ = F25L_manufactory = SPISwapDataMSB(0xFF); // Manufactory
*buf = SPISwapDataMSB(0xFF); // ID(7~0)
SPICSHigh();
SPISemPut();
}

extern uint8_t F25L_ReadElectronicSignature(void)
{
uint8_t ret;

SPISemGet();
SPICSLow();
SPIShiftDataMSB(opcodeReadElectronicSignature);
ret = SPISwapDataMSB(0xFF);
SPICSHigh();
SPISemPut();

return ret;
}

extern void F25L_Read(uint32_t addr, uint8_t *buf, uint32_t bytes)
{
SPISemGet();
SPICSLow();
F25L_ShiftOutAddrWrite(opcodeRead, addr);
for (; bytes; bytes--)
{
*buf++ = SPISwapDataMSB(0xFF);
}
SPICSHigh();
SPISemPut();
}

extern uint8_t F25L_BuffCmpCanWrite(uint32_t addr, uint8_t *buf, uint32_t
bytes)
{
SPISemGet();
SPICSLow();
F25L_ShiftOutAddrWrite(opcodeRead, addr);
for (; bytes; bytes--,buf++)
{
if ((*buf & SPISwapDataMSB(0xFF)) != *buf)
{
SPICSHigh();
SPISemPut();
return FALSE;
}
}
SPICSHigh();
SPISemPut();
return TRUE;
}

extern void F25L_FastRead(uint32_t addr, uint8_t *buf, uint32_t bytes)
{
SPISemGet();
SPICSLow();
F25L_ShiftOutAddrWrite(opcodeFastRead, addr);
SPIShiftDataMSB(0xff); // dummy
for (; bytes; bytes--)
{
*buf++ = SPISwapDataMSB(0xFF);
}
SPICSHigh();
SPISemPut();
}

static uint8_t F25L_ByteProgram(uint32_t addr, uint8_t dat)
{
uint8_t ret;

SPISemGet();
F25L_StatusRegisterWrite(0x00);
F25L_WriteEnable();
SPICSLow();
F25L_ShiftOutAddrWrite(opcodeByteProgram, addr);
SPIShiftDataMSB(dat);
SPICSHigh();
while (F25L_StatusRegisterRead() & BUSY);

SPICSLow();
F25L_ShiftOutAddrWrite(opcodeRead, addr);
if(dat == SPISwapDataMSB(0xFF))
{
ret = TRUE;
}
else
{
ret  = FALSE;
}
SPICSHigh();

SPISemPut();

return ret;
}

static uint8_t F25L_AAIWordProgram(uint32_t addr, uint8_t *dat, uint32_t
words)
{
uint8_t *p;
uint32_t i;
uint8_t ret;

if(words == 0) return TRUE;

p = dat;
i = words;

SPISemGet();
F25L_StatusRegisterWrite(0x00);

F25L_WriteEnable();
SPICSLow();
F25L_ShiftOutAddrWrite(opcodeAAIWordProgram, addr);
SPIShiftDataMSB(*p++);
SPIShiftDataMSB(*p++);
SPICSHigh();
while (F25L_StatusRegisterRead() & BUSY);
i--;
for (; i; i--)
{
SPICSLow();
SPIShiftDataMSB(opcodeAAIWordProgram);
SPIShiftDataMSB(*p++);
SPIShiftDataMSB(*p++);
SPICSHigh();
while (F25L_StatusRegisterRead() & BUSY);
}
F25L_WriteDisable();
while (F25L_StatusRegisterRead() & BUSY);

SPICSLow();
F25L_ShiftOutAddrWrite(opcodeRead, addr);
for (i=(words << 1),ret=TRUE; i; i--)
{
if(*dat != SPISwapDataMSB(0xFF))
{
ret = FALSE;
break;
}
dat++;
}
SPICSHigh();

SPISemPut();
return ret;
}

static uint8_t F16_PageProgram(uint32_t addr, uint8_t *dat, uint32_t len)
{
uint8_t *p;
uint32_t i;
uint8_t ret;

if(len == 0) return TRUE;
p = dat;
i = len;
ret = TRUE;

SPISemGet();
F25L_StatusRegisterWrite(0x00);
F25L_WriteEnable();
SPICSLow();
F25L_ShiftOutAddrWrite(opcodePageProgram, addr);
while(i--)
{
SPIShiftDataMSB(*p++);
}
SPICSHigh();
while (F25L_StatusRegisterRead() & BUSY);

SPICSLow();
F25L_ShiftOutAddrWrite(opcodeRead, addr);
for (; len; len--)
{
if (*dat++ != SPISwapDataMSB(0xFF))
{
ret = FALSE;
break;
}
}
SPICSHigh();

SPISemPut();
return ret;
}

extern uint8_t F25L_BuffProgram(uint32_t addr, uint8_t *dat, uint32_t bytes)
{
uint8_t ret = TRUE;
uint32_t max_len;

switch(F25L_manufactory)
{
case 0x1c: // EON
case 0xc2: // MXIC
case 0xef: // Winbond
default:
while(bytes)
{
max_len = 0x100 - (addr & 0xff);
if(max_len > bytes)
{
max_len = bytes;
}
ret &= F16_PageProgram(addr, dat, max_len);
addr += max_len;
dat += max_len;
bytes -= max_len;
}
break;
case 0x8c: // ESMT
if (addr & 0x01)
{
ret &= F25L_ByteProgram(addr,*dat);
addr++;
dat++;
bytes--;
if (bytes == 0)
{
return ret;
}
}
ret &= F25L_AAIWordProgram(addr,dat,bytes/2);
if (bytes & 0x01)
{
ret &= F25L_ByteProgram(addr+(bytes/2)2,(dat + bytes-1));
}
break;
}
return ret;
}

and here is the other part

-----------------------------------------------------------------------------------------------------------------------

#include "includes.h"

//=============================================================================
#define SPI_NCS_HIGH() do{ \
GPIOSetValue(0, P0_SPICS, 1);\
}while(0)
#define SPI_NCS_LOW() do{ \
        GPIOSetValue(0, P0_SPICS, 0);    \
}while(0)
#define SPISclkHigh() \
do{ \
GPIOSetValue(0, P0_SPICLK, 1);   \
}while(0)
#define SPISclkLow() \
do{ \
GPIOSetValue(0, P0_SPICLK, 0);   \
}while(0)
#define SPIMOSIHigh() \
do{ \
GPIOSetValue(0, P0_SPIMOSI, 1);   \
}while(0)
#define SPIMOSILow() \
do{ \
GPIOSetValue(0, P0_SPIMOSI, 0);   \
}while(0)
#define SPIMISORead()   (LPC_GPIO0->DATA &(1<<P0_SPIMISO))
//=============================================================================
static void SPIDelay(uint32_t tm)
{
volatile uint32_t t;
tm <<= 4;
t = tm;
while(t--);
}
//=============================================================================
//static OS_EVENT *spi_sem_event;
static void SPISemInit(void)
{
//spi_sem_event = OSSemCreate(1);
}
extern void SPISemGet(void)
{
//uint8_t err;
//OSSemPend(spi_sem_event, 0, &err);
}
extern void SPISemPut(void)
{
//OSSemPost(spi_sem_event);
}
//=============================================================================
extern void SPIInit(void)
{
/* Configure I/O for Flash Chip select */
GPIOSetDir(0, P0_SPICS, 1);
LPC_IOCON->PIO0_2 = IOCON_PIO;
SPICSHigh();
/* SCLK */
GPIOSetDir(0, P0_SPICLK, 1);
LPC_IOCON->SWCLK_PIO0_10 = (2<<3)|(1<<0);
SPISclkHigh(); // rising edge latch
/* MOSI */
GPIOSetDir(0, P0_SPIMOSI, 1);
LPC_IOCON->PIO0_9 = IOCON_PIO;
/* MISO */
GPIOSetDir(0, P0_SPIMISO, 0);
LPC_IOCON->PIO0_8 = IOCON_PIO;
SPISemInit();
}
//=============================================================================
extern void SPICSLow(void)
{
SPI_NCS_LOW();
}
extern void SPICSHigh(void)
{
SPI_NCS_HIGH();
}
//=============================================================================
extern uint32_t SPISwapDataLSB(uint32_t dat, uint8_t bits)
{
uint8_t i;
uint32_t rx;
for (i=0, rx=0; i<bits; i++)
{
if (dat & (1 << i))         // LSB first
{
SPIMOSIHigh();
}
else
{
SPIMOSILow();
}
SPISclkLow();
if(SPIMISORead())
{
rx |= (1 << i);
}
SPISclkHigh();          // rising edge latch
}
return rx;
}
//=============================================================================
extern void SPIShiftDataMSB(uint8_t dat)
{
uint8_t i;
i = 7;
do
{
if (dat & (1 << i))         // MSB first
{
SPIMOSIHigh();
}
else
{
SPIMOSILow();
}
SPISclkLow();
SPISclkHigh();          // rising edge latch
}while(i--);
}
//=============================================================================
extern uint8_t SPISwapDataMSB(uint8_t out)
{
uint8_t in;
uint8_t i;
in = 0;
i = 7;
do
{
SPISclkLow(); // clk = 0;
if(out & (1 << i))
{
SPIMOSIHigh();
}
else
{
SPIMOSILow();
}
SPIDelay(1);
if(SPIMISORead())
{
in |= (1 << i);
}
SPISclkHigh(); // clk = 1;
SPIDelay(2);
}while(i--);
return in;
}
//=============================================================================
extern uint8_t SPISwapDataMSBSlow(uint8_t out)
{
uint8_t in;
uint8_t i;
in = 0;
i = 7;
do
{
SPISclkLow(); // clk = 0;
if(out & (1 << i))
{
SPIMOSIHigh();
}
else
{
SPIMOSILow();
}
SPIDelay(75); // 7.5us
if(SPIMISORead())
{
in |= (1 << i);
}
SPISclkHigh(); // clk = 1;
SPIDelay(75); // 7.5us
}while(i--);
return in;
}
----------------------------------------------------------------------------------------------------------- 
int main( void )

{
EVENT_T evt;
//SysTick_Config(SystemFrequency/100000);
// No se utliza OSTimeDly en esta sección
__disable_irq();
system_init();
if(1)
{//uint8_t buf[6];
uint8_t buf[SPEC12832RowNum*SPEC12832ColumnNum/8];
uint8_t c;
SPEC12832Select(LCD_SELECT_USER | LCD_SELECT_CUSTOM);
memset(buf, 0x00, sizeof(buf));
SPEC12832DisplayPattern(buf);
memset(screen1,'0',sizeof(screen1));
      screen1[0]='A';
screen1[1]='B';
while(1)
{
//KeyScanProc(buf,screen1);
//F25L_AAIWordProgram(0x80000,screen1,2);
F25L_BuffCmpCanWrite(0x0, screen1, sizeof(screen1));
F25L_FastRead(0x0,screen22,sizeof(screen22));
CharToDot(screen22[5],5,16*16,1,buf);
CharToDot('I',6,16*16,1,buf);
}
}

Outcomes