User data on SPI Flash
-
- Respected Member
- Posts: 395
- Joined: Tue May 18, 2010 12:25 am
User data on SPI Flash
With the standard connections for system Flash, Can I store my own data to the Flash, by referencing the ports as standard ports?
-
- XCore Addict
- Posts: 228
- Joined: Thu Jan 27, 2011 3:30 pm
- Location: Argenteuil - France
-
- Active Member
- Posts: 51
- Joined: Fri Jan 29, 2010 4:36 pm
Look at flash.h and flashlib.h They describe the different routines for accessing the flash. there are separate routines for both the data and boot image. I wound up writing my own though, because I wanted to be able to manage individual sectors on the flash. As far as I can tell, the data sector routines use 32k or 64k (I can't remember which) as the minimum erase/write size. I wanted to use the 4k sectors my flash supports.
regards mike
regards mike
-
- Active Member
- Posts: 51
- Joined: Fri Jan 29, 2010 4:36 pm
I didn't read your question well enough.
These are the routines I use:
These are the routines I use:
Code: Select all
void spi_shutdown() {
// need clock ticks in order to stop clock blocks
timer t;
unsigned int time;
printuint(0);
SPI.spiCLK <: 0;
t :> time;
time += M41T93_BIT_TIME;
for (int i=0;i<16;i++)
{
t when timerafter ( time ) :> void;
time += M41T93_BIT_TIME;
SPI.spiCLK <: 1;
t when timerafter ( time ) :> void;
time += M41T93_BIT_TIME;
SPI.spiCLK <: 0;
}
printuint(1);
stop_port(SPI.spiMOSI);
printuint(2);
stop_port(SPI.spiMISO);
printuint(3);
stop_port(SPI.spiCLK);
printuint(4);
stop_clock(SPI.spiClkblk);
printuint(5);
}
void spi_init( unsigned rate,
unsigned clk_div,
unsigned clk_delay,
unsigned clk_pad_delay,
unsigned miso_pad_delay,
unsigned mosi_pad_delay) {
timer t;
unsigned int time;
set_port_use_off(SPI.spiCLK);
set_port_use_on(SPI.spiCLK);
// stop_port(SPI.spiMOSI);
// stop_port(SPI.spiMISO);
// stop_port(SPI.spiCLK);
// stop_clock( SPI.spiClkblk);
configure_out_port(SPI.spiMOSI, SPI.spiClkblk, 0);
configure_clock_src(SPI.spiClkblk, SPI.spiCLK);
//printuint(1);
configure_out_port(SPI.spiMOSI, SPI.spiClkblk, 0);
//printuint(2);
configure_in_port(SPI.spiMISO, SPI.spiClkblk);
//printuint(3);
set_clock_fall_delay(SPI.spiClkblk, clk_delay); // need to understand this better
set_clock_rise_delay(SPI.spiClkblk, clk_delay); // need to understand this better
// set_pad_delay(spi1_sclk, 5);
set_pad_delay(SPI.spiMISO, miso_pad_delay);
set_pad_delay(SPI.spiMOSI, mosi_pad_delay);
// start_port(SPI.spiCLK);
//printuint(4);
start_clock(SPI.spiClkblk);
//printuint(5);
SPI.spiCLK <: 0;
t :> time;
time += M41T93_BIT_TIME;
//printuint(6);
for (int i=0;i<8;i++)
{
t when timerafter ( time ) :> void;
time += M41T93_BIT_TIME;
SPI.spiCLK <: 1;
t when timerafter ( time ) :> void;
time += M41T93_BIT_TIME;
SPI.spiCLK <: 0;
}
//printuint(7);
clearbuf(SPI.spiMISO);
//printuint(8);
clearbuf(SPI.spiMOSI);
//printuint(9);
}
void spi_in_bytes(unsigned addr, unsigned outLen, unsigned char outData[],unsigned inLen, unsigned char inData[], unsigned enableSS, unsigned disableSS) {
// MSb-first bit order - SPI standard
unsigned bitTime = AT_25DF_041_BIT_TIME/2;
timer t;
unsigned int time;
unsigned x;
unsigned j=0;
SPI.spiSS <: disableSS;
rtc_ss <: disableSS;
SPI.spiCLK <: 0;
if (outLen >0)
{
t :> time;
time += bitTime;
x = bitrev(outData[j++]) >> 24;
SPI.spiMOSI <: x;
t when timerafter ( time ) :> time;
time += bitTime;
SPI.spiCLK <: 1;
t when timerafter ( time ) :> time;
time += bitTime;
time += bitTime;
SPI.spiCLK <: 0;
switch(addr){
case FLASH:
SPI.spiSS <: enableSS;
break;
case RTC:
rtc_ss <: enableSS;
break;
}
// it requires only 7 more clocks to finish the first word
for (int i=0;i<7;i++)
{
t when timerafter ( time ) :> time;
time += bitTime;
SPI.spiCLK <: 1;
t when timerafter ( time ) :> time;
time += bitTime;
SPI.spiCLK <: 0;
}
SPI.spiMISO :> void;
for(;j<outLen;j++)
{
time += bitTime;
x = bitrev(outData[j]) >> 24;
SPI.spiMOSI <: x;
for (int i=0;i<8;i++)
{
t when timerafter ( time ) :> time;
time += bitTime;
SPI.spiCLK <: 1;
t when timerafter ( time ) :> time;
time += bitTime;
SPI.spiCLK <: 0;
}
SPI.spiMISO :> void;
}
//one last clock cycle required
time += bitTime;
t when timerafter ( time ) :> time;
time += bitTime;
SPI.spiCLK <: 1;
t when timerafter ( time ) :> time;
time += bitTime;
SPI.spiCLK <: 0;
}
else
{
switch(addr){
case FLASH:
SPI.spiSS <: enableSS;
break;
case RTC:
rtc_ss <: enableSS;
break;
}
}
clearbuf(SPI.spiMISO);
t :> time;
time += bitTime;
for(j=0;j<inLen;j++)
{
for (int i=0;i<8;i++)
{
t when timerafter ( time ) :> time;
time += bitTime;
SPI.spiCLK <: 1;
t when timerafter ( time ) :> time;
time += bitTime;
SPI.spiCLK <: 0;
}
SPI.spiMISO :> x;
inData[j] = (bitrev(x) >> 24);
}
SPI.spiSS <: disableSS;
rtc_ss <: disableSS;
}
void spi_out_bytes(unsigned addr, unsigned len, unsigned char data[], unsigned enableSS, unsigned disableSS) {
// MSb-first bit order - SPI standard
unsigned bitTime = AT_25DF_041_BIT_TIME/2;
timer t;
unsigned int time;
unsigned x;
unsigned j=0;
SPI.spiSS <: disableSS;
rtc_ss <: disableSS;
SPI.spiCLK <: 0;
t :> time;
time += bitTime;
x = bitrev(data[j++]) >> 24;
SPI.spiMOSI <: x;
t when timerafter ( time ) :> time;
time += bitTime;
SPI.spiCLK <: 1;
t when timerafter ( time ) :> time;
time += bitTime;
time += bitTime;
SPI.spiCLK <: 0;
switch(addr){
case FLASH:
SPI.spiSS <: enableSS;
break;
case RTC:
rtc_ss <: enableSS;
break;
}
// it requires only 7 more clocks to finish the first word
for (int i=0;i<7;i++)
{
t when timerafter ( time ) :> time;
time += bitTime;
SPI.spiCLK <: 1;
t when timerafter ( time ) :> time;
time += bitTime;
SPI.spiCLK <: 0;
}
SPI.spiMISO :> void;
for(;j<len;j++)
{
time += bitTime;
x = bitrev(data[j]) >> 24;
SPI.spiMOSI <: x;
for (int i=0;i<8;i++)
{
t when timerafter ( time ) :> time;
time += bitTime;
SPI.spiCLK <: 1;
t when timerafter ( time ) :> time;
time += bitTime;
SPI.spiCLK <: 0;
}
SPI.spiMISO :> void;
}
//one last clock cycle required
time += bitTime;
t when timerafter ( time ) :> time;
time += bitTime;
SPI.spiCLK <: 1;
t when timerafter ( time ) :> void;
SPI.spiCLK <: 0;
SPI.spiSS <: disableSS;
rtc_ss <: disableSS;
}
void writeEnable()
{
unsigned char cData[1];
cData[0] = WRITE_ENABLE_CMD;
spi_out_bytes(FLASH,1,cData, 0, 1);
}
void writeDisable()
{
unsigned char cData[1];
cData[0] = WRITE_DISABLE_CMD;
spi_out_bytes(FLASH,1,cData, 0, 1);
}
void sectorUnprotect(unsigned addr)
{
unsigned char cData[4];
writeEnable();
cData[0] = SECTOR_UNPROTECT_CMD;
uintToChar(cData, addr, 1,3);
spi_out_bytes(FLASH,4,cData, 0, 1);
writeDisable();
}
void sectorProtect(unsigned addr)
{
unsigned char cData[4];
writeEnable();
cData[0] = SECTOR_PROTECT_CMD;
uintToChar(cData, addr, 1,3);
spi_out_bytes(FLASH,4,cData, 0, 1);
writeDisable();
}
unsigned char statusRegister()
{
unsigned char outData[1];
unsigned char inData[1];
outData[0] = READ_STATUS_CMD;
spi_in_bytes (FLASH, 1,outData,1,inData, 0, 1);
return inData[0];
}
unsigned erase4k(unsigned addr)
{
unsigned char cData[4];
timer t;
unsigned int time;
unsigned elapsedTime = 0;
cData[0] = ERASE_4k_CMD;
uintToChar(cData, addr, 1,3);
sectorUnprotect(addr);
writeEnable();
spi_out_bytes(FLASH,4,cData, 0, 1);
// add timeout
t :> time;
time += 10000; //100us
while (((statusRegister() & READY_BUSY_STATUS ) > 0) && (elapsedTime < ERASE_4k_TIME));
{
t when timerafter ( time ) :> void;
time += 10000; //100us
elapsedTime += 100;
}
sectorProtect(addr);
return elapsedTime;
}
unsigned writeArray (unsigned len, unsigned char cData[], unsigned addr)
{
unsigned char cOutData[260];
timer t;
unsigned int time;
unsigned elapsedTime = 0;
if (len <= 256)
{
cOutData[0] = WRITE_ARRAY_CMD;
uintToChar(cOutData, addr, 1,3);
for (int i=0;i<len;i++)
cOutData[i+4] = cData[i];
sectorUnprotect(addr);
writeEnable();
spi_out_bytes(FLASH,4+len,cOutData, 0, 1);
t :> time;
time += 10000; //100us
while (((statusRegister() & READY_BUSY_STATUS ) > 0) && (elapsedTime < WRITE_PAGE_TIME));
{
t when timerafter ( time ) :> void;
time += 10000; //100us
elapsedTime+100;
}
sectorProtect(addr);
return elapsedTime;
}
else
{
return 0xffffffff;
}
}
void readArray (unsigned len, unsigned char cData[], unsigned addr)
{
unsigned char cOutData[4];
cOutData[0] = READ_ARRAY_CMD;
uintToChar(cOutData,addr,1,3);
spi_in_bytes(FLASH, 4, cOutData, len, cData, 0, 1);
}
Last edited by octal on Tue Mar 22, 2011 8:42 pm, edited 2 times in total.
Reason: Added [code][/code] tag arround sources
Reason: Added [code][/code] tag arround sources
-
- Active Member
- Posts: 51
- Joined: Fri Jan 29, 2010 4:36 pm
I am glad I posted the above code, as I just noticed a flaw:
I use the enableSS and disableSS values to enable and disable the chip selects for an RTC and the onboasrd flash chip. The RTC uses a 4bit port shared with some status lines, and the calling routine bit masks the enableSS and disableSS values. The flash CS line is on a 1 bit port, and I should have just used a one or zero, or had separate enable disable values for each. Actually I can assume that if I am dealing with the flash the RTC is already disabled, and vice versa.
I use the enableSS and disableSS values to enable and disable the chip selects for an RTC and the onboasrd flash chip. The RTC uses a 4bit port shared with some status lines, and the calling routine bit masks the enableSS and disableSS values. The flash CS line is on a 1 bit port, and I should have just used a one or zero, or had separate enable disable values for each. Actually I can assume that if I am dealing with the flash the RTC is already disabled, and vice versa.
-
- XCore Legend
- Posts: 1274
- Joined: Thu Dec 10, 2009 10:20 pm
Hi boeserbaer
For long code postings it often worth using a service like https://gist.github.com/ or others. The reason I suggest this one is because github is where Xcore opensource code is now so its useful to have an account there as its free. It makes the thread more readable that way.
here is an Example I've used before.
P.S. for small snippets of code you can use the built in "" feature here.
regards
Al
For long code postings it often worth using a service like https://gist.github.com/ or others. The reason I suggest this one is because github is where Xcore opensource code is now so its useful to have an account there as its free. It makes the thread more readable that way.
here is an Example I've used before.
P.S. for small snippets of code you can use the built in "
Code: Select all
regards
Al