1
\$\begingroup\$

Hello everyone

I'm writing a C program that will access a flash AT45DB041B from the controller ATmega169. I'm using a Butterfly development kit.

I have succeeded to read the status register and get correct data so I'm quite sure that the flash works and can communicate. But I haven't been able to write and read to flash, the only thing that I can read from it is zeros.

I unfortunately I don't have any possibility to snoop the traffic either.

init:

 void init_flash_as_master(void)
 {

// double speed, p 150 mega169 manual
SPSR = 0x01; // the other bits are don't care or set by hardware

//      MOSI        SCK         !SS    are outputs
DDRB |= _BV(PB2) | _BV(PB1) | _BV(PB0);


// p 148 in mega169 manual
/* bit 7, 0 interrupt not enabled
 * bit 6, 1 SPI enable,
 * bit 5, 0, MSB first, ch 5 flash datasheet
 * bit 4, 1, Master
 * bit 3,2, 00, CPOL,CPHA, SPI mode 0, p 5 flash datasheet
 * bit 1,0, 10, /32, flash max operating frequency 20 MHz p 1 flash datasheet
 */

SPCR = 0x52;

}

send:

inline void send_byte(uint8_t byte)
{
    SPDR = byte;
    while (!(SPSR & _BV(SPIF))) {;}
}

recive:

inline uint8_t recieve_byte(void) 
{
SPDR = 'A'; //load SPDR to start clock generation
while (!(SPSR & _BV(SPIF))) {;}
return SPDR;
}

start transmission:

inline void start_transmission(void) 
{
    // set chip select for sending data
    PORTB &= 0xFE; // setting bit 0 on port B low
}

stop transmission:

inline void stop_transmission(void) 
{
    // finish transmission
    PORTB |= 0x01;
}

clear flag:

inline void clear_SPIF(void)
{
    uint8_t temp = 0;

    // clear SPIF
    if(SPSR & _BV(SPIF)) { temp = SPDR; }
}

write operation:

// write a struct song_t to specified page in the flash memory
void flash_write_song(uint16_t page, const song_t * song)
{
    if (direction != master) init_flash_as_master();

    clear_SPIF();
    start_transmission();
    // ch. 12.2 flash datasheet 
    send_byte(0x84); // write to buffer 1, 84h
    send_byte(0x00); // three address bytes, starting at byte 0
    send_byte(0x00); // table 7, flash application note
    send_byte(0x00);

    // push name
    for (int i = 0; i != NAME_LEN; i++)
    {
        send_byte(song->name[i]);
    }
    int j = 0;
    while (j < TUNE_LEN) 
    {
        send_byte(song->tune[j]);
        j++;
}
stop_transmission();

flash_ready();

start_transmission();
// ch. 12.3 flash datasheet

    // Buffer 1 to Main Memory Page Program with Built-in Erase
send_byte(0x83); 

    // first byte contains the 4 uppermost bits
send_byte(get_high_byte(page));

    // second byte contains the 7 lowest bits, starting at bit 1
send_byte(get_low_byte(page)); 
send_byte(0x00); // table 7, flash application note

stop_transmission();
flash_ready();

}

read operation:

// read a struct song_t from specified page in the flash memory
void flash_read_song(uint16_t page, song_t * song)
{

if (direction != master) init_flash_as_master();

clear_SPIF();

// flash datasheet 16.2
start_transmission();

// table 7, flash application note
send_byte(0xD2); // read page from main memory,
// first byte contains the 4 uppermost bits
send_byte(get_high_byte(page)); 
// second byte contains the 7 lowest bits, starting at bit 1
send_byte(get_low_byte(page)); 
send_byte(0x00); // controller says, read from byte 0

send_byte(0x00); // 4 don't care bytes
send_byte(0x00);
send_byte(0x00);
send_byte(0x00);

// read name
for (int i = 0; i != NAME_LEN; i++)
{
    song->name[i] = recieve_byte(); 
}
/*  // and now we will read the data until we find a 0
int j = 0;
uint8_t byte_popped = recieve_byte();
while (j < 4) //TODO
{
    song->tune[j] = byte_popped;
    j++;
    byte_popped = recieve_byte();
}
*/
stop_transmission();

}

The question

I am quite sure that the error is in my code, as I can read the status register. But I can't see any problems in my code. Am I pulling the right signals in the right time?

If you want any clarifications or more descriptions, please tell.
Regards
Gorgen

\$\endgroup\$
  • \$\begingroup\$ can you give probes of signals? Can you please post your code to this site instead of pastebin? We really cannot help easily without for more information. I am closing this and when you are ready to make updates let me know and I will reopen(just flag for moderator attention). \$\endgroup\$ – Kortuk Apr 17 '11 at 20:41
  • \$\begingroup\$ it seems someone already helped you. I have reopened, but it seems the question is pretty much solved. The things I want to note is that someone really could use a schematic and probed signals for a more complicated problem. As the solution seems to be relatively easy and very specific to your situation I closed it. With code someone now has a full guide for interfacing with this flash. Good luck and have fun. \$\endgroup\$ – Kortuk Apr 25 '11 at 2:35
  • 1
    \$\begingroup\$ @Kortuk: I will.. :) \$\endgroup\$ – Gorgen Apr 25 '11 at 5:18
2
\$\begingroup\$

The only thing I can spot is that stop_transmission() is missing from flash_ready().

Your programming sequence is:

  1. fill buffer
  2. wait for ready
  3. program
  4. wait for ready

The program command may be lost since it is not preceded by a falling edge of $\overline{\text{CS}}$.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.