Trouble making a flash programmer with an ATmega1284p

Go To Last Post
14 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

As far as I can tell I am following the data sheet of the flash and I don't see how my code is different from this guy's but nothing I have tried will work and I was hoping someone on here might be able to help me.

 

The flash is an SST39SF040, I've tirelessly double-checked on my breadboard that all 19 address pins go to the right places and my code works as expected on the mc but I am waiting for more jumper wires and another breadboard in the mail to properly test if it is all working correctly, so it's still possible that something isn't working correctly. But even if that is the case, this code should theoretically work, right?

 

// right-side top-bottom = A0-A7, C7-C0, and D7
// left side bottom up D6, D5. D5 is least significant bit, A0 most significant
// PORTB will be the data
// D0 and D1 are RX0 and TX0 respectively
// D3 and D4 will be the OE and WE respectively

#define F_CPU 8000000UL

#include <avr/io.h>
#include <util/delay.h>

const int delay = 250;

const unsigned char reverseByteTable[] = {
    0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
    0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
    0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
    0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
    0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
    0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
    0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
    0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
    0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
    0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
    0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
    0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
    0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
    0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
    0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
    0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
    0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
    0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
    0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
    0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
    0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
    0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
    0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
    0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
    0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
    0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
    0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
    0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
    0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
    0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
    0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
    0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff,
};

inline void setAddress(const uint32_t address){
    PORTD &= (255 >> 3);
    PORTD |= address << 5; // D5-7 are bits 0-2
    PORTC = address >> 3; // C0-C7 are bits 3-10
    PORTA = reverseByteTable[address >> 11]; // A7-0 are bits 11-18
}

inline void setData(const uint8_t data){
    PORTB = reverseByteTable[data]; // B0 is most significant bit
}

inline void enableWrite(){
    PORTD &= ~(1 << 4);  
}
inline void disableWrite(){
    PORTD |= 1 << 4; 
}

inline void enableOutput(){
    PORTD &= ~(1 << 3); 
}
inline void disableOutput(){
    PORTD |= 1 << 3; 
}

inline void writeMode(){
    DDRB = 255; // setting PORTB to output
    disableWrite();
    disableOutput();
}
inline void readMode(){
    DDRB = 0; // setting PORTB to input
    PORTB = 0; // switching off pull-up resistors
    enableOutput();
}

inline void programFlash(const uint32_t address, const uint8_t data){
    
    disableWrite();

    setAddress(address);
    setData(data); 
    
    _delay_ms(delay);

    enableWrite();
    
    _delay_ms(delay);
    
    disableWrite(); 
        
}

void writeToFlash(const uint32_t adr, const uint8_t data){
    
    unsigned char counter = 0;
    
    do{
        
        writeMode();
        _delay_ms(delay);
        
        // the byte program command sequence
        programFlash((uint32_t)0x5555, 0xaa);
        _delay_ms(delay);
        
        programFlash((uint32_t)0x2aaa, 0x55);
        _delay_ms(delay);
        
        programFlash((uint32_t)0x5555, 0xa0);
        _delay_ms(delay);
        
        // writing the data
        programFlash(adr, data);
        _delay_ms(delay);
        
        readMode();    
        _delay_ms(delay);
        
        counter++;    
    } while (PINB != data && counter < 10); // repeatedly try and write data
        
}

void setup(){

    PORTA = 0;
    PORTB = 0;
    PORTC = 0;
    PORTD = 0;    
    disableWrite();

    DDRA = 255;
    DDRB = 255;
    DDRC = 255;
    DDRD = 255;
}

int main(void)
{

    setup();
    
    writeToFlash((uint32_t)1, 128); 
    _delay_ms(2000);
    
    writeToFlash((uint32_t)2, 254); 
    _delay_ms(1000);
    
    
    while (1) 
    {
        setAddress((uint32_t)1); // reading an address, should be 128
        _delay_ms(500);
        
        setAddress((uint32_t)2); // reading an address
        _delay_ms(500);    
        
    }
}

Thank you

 

Edit: I cleaned some things up and just used a lookup table I found on stack overflow to reverse the bytes instead of doing them bit by bit so it's both readable and in the order I need the wires on my breadboard for now lol OTHER EDITS: just making it more readable and trying to copy that other guy's code more closely but still doesn't work.

This topic has a solution.
Last Edited: Tue. Jul 20, 2021 - 10:26 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

TristanAVR wrote:

DDRB = 0; // turning off pull up resistors of PORTB which is the data

for a start that is not a true comment...... you make the lines input instead of what ever they were, nothing to do with pull-ups.

 

Also at first glance you can simplify the address mapping by just shifting and masking instead of going through each bit.

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Oh ok and ya I know I just wanted to get it working first, I don't really have a great way of testing if the address is working correctly right now (I ran out of jumper wires), but maybe I should do it that way so it's easier for you guys to read, I'll edit the post if I do.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
    if ((address & 1) == 1){
        PORTD |= 32; // D5
    }
    if (((address >> 1) & 1) == 1){
        PORTD |= 64; // D6
    }
    if (((address >> 2) & 1) == 1){
        PORTD |= 128; // D7
    }
    if (((address >> 3) & 1) == 1){
        PORTC |= 1;
    }

    etc.
    etc.
    etc.

OMG! With code like that why didn't you choose a Serial Flash Memory ? You don't need the speed of a parallel interface and with only 8-pins, it would have been far - far easier to breadboard also.

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

It's for a homebrew 8-bit computer, I'm actually just using the microcontroller to see if I understand how the flash works and clearly I don't lol I wouldn't use code like that in a final product, the order of the pins has mainly to do with the physical orientation on the chip so it is easier for me to wire up on a breadboard and in the only order that works with the length of jumper wires I have lol I'm gonna edit that part for you guys so you stop commenting about it lol but thanks

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

OK - I got the wrong end-of-the-stick. I thought you were making an AVR programmer and the Flash chip was going to store the target binary.

 

I see you're making an old-fashioned memory device programmer. (OMG - I haven't used mine in over 20 years)

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

As you appear to be using avr-gcc did you know that it comes with a function to reverse bits?:

 

https://www.avrfreaks.net/commen...

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Oh nice no I did not know that I'll have to check out some more of those functions. I think I'm fine with this way though it's only 256 bytes.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

It turns out it works but only sometimes, I was able to flip some 1's to 0's twice but now it doesn't work at all again. I've tried using different delay values, no delay, without LEDs on the data lines, et cetera. I was about to check the address lines after another breadboard came in the mail and just turned it on after not using for like a week and it magically worked, I tried again and it worked again, then I tried again, and it stopped working. I'm going to test the address lines to make sure they are correct now but after seeing it work twice in a row I don't think that is the problem.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

And now after connecting all the LED's up and seeing that my address pins were all correct, the data byte from the flash I was able to write to now somehow got erased and is all 1's again, I don't even have a sector erase function.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Can we assume you've properly dealt with the chip-enable (CE) pin  ?  I see no code for that.

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Yes, it is tied low so it is always enabled. BTW I just updated the code again all I did was move a few things into inline functions so it is easier to read and I tried to make it more like the guy's code which I linked to like implementing a data polling loop but it still doesn't work.

Last Edited: Tue. Jul 20, 2021 - 07:23 AM
This reply has been marked as the solution. 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

Hey sorry everyone it turns out it is just bad connections on the breadboard, I discovered this by getting it to work by very firmly pressing down on it. At first I even tried bending the pins of the flash so they would have more force pressing against the sockets but this didn't help so I assumed that wasn't the problem. And you have to press like REALLY hard on it, so there must be some crud or something in there. But the code does in fact work, so I guess I'll rewire on another breadboard and hope for the best? I could also just make a little dev PCB for it. Thanks guys.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

TristanAVR wrote:
But the code does in fact work, so I guess I'll rewire on another breadboard and hope for the best?
or a quality breadboard; IIRC, some lecturers specify 3M breadboards.

TristanAVR wrote:
I could also just make a little dev PCB for it.
in-lieu of, a protoboard

 


How can I judge the quality of a breadboard? | Frequently Asked Questions | BusBoard Prototype Systems

 

Through Hole Boards - Schmartboard, Inc.

 

"Dare to be naïve." - Buckminster Fuller