|
|
View previous topic :: View next topic |
Author |
Message |
Tagge
Joined: 23 Aug 2005 Posts: 93
|
read/write ext flash M45PE20 |
Posted: Thu Apr 30, 2009 8:13 am |
|
|
Hi, I dont seem to get the ext flash working, propably some wrong thinking.. any ideas? Im aware of that the W pin on the flash is to be kept high for using addresses 0-256. I havent find anyone who has been using this flash here on the ccs. But anyway here is the driver for it, it should be working.. altough I cant get anything out of it
The string light_table consists of int8's.
Code: | void test_flash(void)
{
int8 my_string[256];
strcpy(my_string, light_table);
flashWriteBlock(0,&my_string,256);
flashReadBlock(0,&my_string,256);
fprintf(USER,"TestInts: %s end\r\n",my_string);
}
|
The driver for the M45 flash..
Code: | bool_t flashIsWriteInProgress()
{
uint8_t status;
output_low(PIN_C2);
// Read Status Register (RDSR) flash command.
flashSendByte (0x05);
status = flashGetByte();
output_high(PIN_C2);
return (((status & 0x01) == 0x01) ? TRUE : FALSE);
}
/**
* Read a block of memory from the flash device.
*
* @param address of desired location in the range 0x00000 to 0xFFFFF (1MB)
* @param block pointer to locate of data block
* @param length number of bytes to read
*/
void flashReadBlock(uint32_t address, uint8_t *block, uint16_t length)
{
uint16_t i;
output_low(FLASH_CS);nop();nop();nop();
// Read Data Byte(s) (READ) flash command.
flashSendByte (0x03);
flashSendAddress (address);
for (i = 0; i < length; ++i)
*block++ = flashGetByte();
output_high(FLASH_CS);
}
/**
* Write a block of memory to the flash device.
*
* @param address of desired location in the range 0x00000 to 0xFFFFF (1MB)
* @param block pointer data block to write
* @param length number of bytes to write
*/
void flashWriteBlock(uint32_t address, uint8_t *block, uint8_t length)
{
uint8_t i;
output_low(FLASH_CS);
// Write Enable (WREN) flash command.
flashSendByte (0x06);
output_high(FLASH_CS);
output_low(FLASH_CS);
// Page Program (PP) flash command.
flashSendByte (0x02);
flashSendAddress (address);
for (i = 0; i < length; ++i)
{
// Send each byte in the data block.
flashSendByte (*block++);
// Track the address in the flash device.
++address;
// If we cross a page boundary (a page is 256 bytes) we need to stop and send the address again.
if ((address & 0xff) == 0x00)
{
output_high(FLASH_CS);
// Write this block of data.
while (flashIsWriteInProgress());
output_low(FLASH_CS);
// Write Enable (WREN) flash command.
flashSendByte (0x06);
output_high(FLASH_CS);
output_low(FLASH_CS);
// Page Program (PP) flash command.
flashSendByte (0x02);
flashSendAddress (address);
} // END if
} // END for
output_high (FLASH_CS);
// Wait for the final write operation to complete.
while (flashIsWriteInProgress());
}
/**
* Erase the entire flash device (all locations set to 0xff).
*/
void flashErase()
{
output_low(FLASH_CS);
// Write Enable (WREN) flash command.
flashSendByte (0x06);
output_high(FLASH_CS);
output_low(FLASH_CS);
// Bulk Erase (BE) flash command.
flashSendByte (0xc7);
output_high(FLASH_CS);
while (flashIsWriteInProgress());
}
/**
* Read a single byte from the flash device through the serial interface. This function
* only controls the clock line. The chip select must be configured before calling
* this function.
*
* @return byte read from device
*/
uint8_t flashGetByte()
{
uint8_t i, value;
value = 0;
// Bit bang the 8-bits.
for (i = 0; i < 8; ++i)
{
// Data is ready on the rising edge of the clock.
output_high (FLASH_CLK);
// MSB is first, so shift left.
value = value << 1;
if (input (FLASH_Q))
value = value | 0x01;
output_low (FLASH_CLK);
} // END for
return value;
}
/**
* Initialize the flash memory subsystem.
*/
void flashInit()
{
// I/O lines to control flash.
output_high(FLASH_CS);
output_low(FLASH_CLK);
output_low(FLASH_D);
}
/**
* Write a single byte to the flash device through the serial interface. This function
* only controls the clock line. The chip select must be configured before calling
* this function.
*
* @param value byte to write to device
*/
void flashSendByte(uint8_t value)
{
uint8_t i;
// Bit bang the 8-bits.
for (i = 0; i < 8; ++i)
{
// Drive the data input pin.
if ((value & 0x80) == 0x80)
output_high (FLASH_D);
else
output_low (FLASH_D);
// MSB is first, so shift leeft.
value = value << 1;
// Data is accepted on the rising edge of the clock.
output_high (FLASH_CLK);
output_low (FLASH_CLK);
} // END for
}
/**
* Write the 24-bit address to the flash device through the serial interface. This function
* only controls the clock line. The chip select must be configured before calling
* this function.
*
* @param address 24-bit flash device address
*/
void flashSendAddress(uint32_t address)
{
uint8_t i;
// Bit bang the 24-bits.
for (i = 0; i < 24; ++i)
{
// Drive the data input pin.
if ((address & 0x800000) == 0x800000)
output_high (FLASH_D);
else
output_low (FLASH_D);
// MSB is first, so shift left.
address = address << 1;
// Data is accepted on the rising edge of the clock.
output_high (FLASH_CLK);
output_low (FLASH_CLK);
} // END for
} |
As seen Im using sw SPI but I could use the hw SPI its those pins..
But Im not sure how to rewrite it for that? |
|
|
FvM
Joined: 27 Aug 2008 Posts: 2337 Location: Germany
|
|
Posted: Thu Apr 30, 2009 2:45 pm |
|
|
Do you expect to write somewhat complex code from the scratch without any debugging and test? It possibly works in some rare cases, but not generally, even if you are an experienced programmer.
The present code doesn't write at all, because you try to write 256 bytes with an unsigned int8 length parameter, which is simply zero. There may be other bugs, too. But I stopped reviewing the code at this point.
You can use MPLAB simulator or, better, a JTAG in circuit debugger with the real memory device connected to the processor to check your code.
Best regards,
Frank |
|
|
Tagge
Joined: 23 Aug 2005 Posts: 93
|
|
Posted: Thu Apr 30, 2009 4:05 pm |
|
|
Well, I suppose it isnt proper to write a byte at a time, when the flash is a page programmed device?
The page is 256 bytes, and thats why I try to write a page at one time.
The code did work but not the whole string when trying to write it byte by byte.
as
Code: | for(i=0;i<length_of_string;i++){
flashWriteBlock(address,&my_string[i],1);
address++;
} |
This works at most flash memorys as Atmels.
Why? |
|
|
FvM
Joined: 27 Aug 2008 Posts: 2337 Location: Germany
|
|
Posted: Thu Apr 30, 2009 4:13 pm |
|
|
You seem not to have read my post well.
I've been talking of a simple obvious coding error rather than particular memory properties. (And I wondered, why you apparently never checked the code thoroughly). |
|
|
Tagge
Joined: 23 Aug 2005 Posts: 93
|
|
Posted: Thu Apr 30, 2009 6:49 pm |
|
|
Read your post but didn't get any wiser.
What do you mean? That it's wrong to try to write a string to the memory or to write it byte by byte? or that the whole driver is wrong? or the use of the driver?
I used this driver to other projects with other flash memory devices and it works fine.
But in this particular case it doesn't seem to work at all.
Only thing I changed is the case if the data is transmitted in the front or the end of the clock pulse and the addressing.
By writing the whole string at once it should save writing cycles to the flash, and therefor add some life to it.
Why is it always a zero? as you said.
The driver takes the length of the string as long as its 8-bits chars.
And, yes, I assume it's mostly the case that you can write code without debugging it in some "expensive" debugging equipment, except an mplab icd2 debugger. No jtag needed, as I used it in some Atmel projects.
That's the reason I chose the CCS compiler. |
|
|
FvM
Joined: 27 Aug 2008 Posts: 2337 Location: Germany
|
|
Posted: Fri May 01, 2009 12:03 am |
|
|
Quote: | you try to write 256 bytes with an unsigned int8 length parameter, which is simply zero. |
How many bytes do you expect to be written here?
Code: | void flashWriteBlock(uint32_t address, uint8_t *block, uint8_t length);
for (i = 0; i < length; ++i)
{
} |
Code: | flashWriteBlock(0,&my_string,256); |
I also want to refer to my first point. It's quite normal to implement bugs like above in your code, it happens to me "every day". Sometimes you simply don't recognize them, although others say, they are obvious. But they immediately reveal, when you single-step the code, or just look at the output to the SPI produced from the code, either with an oscilloscope or MPLAB simulator. |
|
|
Tagge
Joined: 23 Aug 2005 Posts: 93
|
|
Posted: Fri May 01, 2009 2:55 am |
|
|
Well, its true, I cant have a length of 256 with an int8. But its really not the main problem with the code, I have tryed it with a length of 1 or any length..
Im not sure how this memory behaves, it seems that all the pins is driven as supposed in the datasheet. But Im not sure how its supposed to be written to, erased first.. and how does it do when written a byte at the time.. a block.. does it erase it self.. |
|
|
FvM
Joined: 27 Aug 2008 Posts: 2337 Location: Germany
|
|
Posted: Fri May 01, 2009 2:29 pm |
|
|
Quote: | Well, its true, I cant have a length of 256 with an int8. But its really not the main problem with the code | I don't know. As I said, there may be other bugs, too. But it has been the main problem for me, when I seriously tried to test the code and found, that it doesn't write at all. You didn't tell about other codes you possibly tested before. |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|