ATMEGA8A + SPI memory strange behavior

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

I've bought SPI memory MX25L8006EPI and now I try to connect it to ATMEGA8A to test it. The schematic is very simple and doesn't change from others over the internet:

ATMEGA8A works at 8Mz internal oscillator, 3.3V. The fuses are HIGH: 0xD1, LOW: 0xE4.

I use Atmel Studio 7 for coding and AVRISP mkII to programming the uC.
Since EEPROM needs 3.3V I've connected 5V 700mA power supply module using LM317 as you can see on the scheme. I don't think it matters but anyway ...

The code is also very simple, I've partly copied that from some page in the Internet:
 

#define SLAVESELECT (PORTB &= ~(1<<PORTB2))
    #define SLAVEDESELECT (PORTB |= (1<<PORTB2))

    #define WREN  6
    #define WRDI  4
    #define RDSR  5
    #define WRSR  1
    #define READ  3
    #define WRITE 2
    #define RDID 0x9F

    #define byte unsigned char

    void SPI_Init()
    {
        DDRB = (1<<PORTB2)|(1<<PORTB3)|(1<<PORTB5);
        SLAVEDESELECT;
        //SPSR |= (1<<SPI2X);
        SPCR |= (1<<SPE)|(1<<MSTR)|(1 << SPR1);
        _delay_ms(10);
    }

    byte SPI_Transfer(volatile byte data)
    {
        SPDR = data;
        while (!(SPSR & (1<<SPIF)));
        return SPDR;
    }

    void Get_Identification(byte data[3])
    {
        SLAVESELECT;
        SPI_Transfer(RDID);
        data[0] = SPI_Transfer(0xFF);
        data[1] = SPI_Transfer(0xFF);
        data[2] = SPI_Transfer(0xFF);
        SLAVEDESELECT;
    }

    byte GetStatus()
    {
        byte status;
        SLAVESELECT;
        SPI_Transfer(RDSR);
        status = SPI_Transfer(0xFF);
        SLAVEDESELECT;
        return status;
    }

    void SetWriteEnable(short ebable)
    {
        SLAVESELECT;
        SPI_Transfer((ebable != 0) ? WREN : WRDI);
        SLAVEDESELECT;
    }

    void SetStatus(byte status)
    {
        SetWriteEnable(1);
        SLAVESELECT;
        SPI_Transfer(WRSR);
        SPI_Transfer(status);
        SLAVEDESELECT;
        _delay_ms(100);
    }

    int main(void)
    {
        SPI_Init();
        byte status = 0x1C;
        DEBUG_PRINT("\r\nSet status:%d\r\n",status);
        SetStatus(status);
        status = GetStatus();
        DEBUG_PRINT("\r\nGet status:%d\r\n",status);
        byte buffer[3];
        Get_Identification(buffer);
        DEBUG_PRINT("Byte0:%x\r\n", buffer[0]);
        DEBUG_PRINT("Byte1:%x\r\n", buffer[1]);
        DEBUG_PRINT("Byte2:%x\r\n", buffer[2]);

        while (1)
        {
        }
    }

 

 

DEBUG_PRINT is my function to send formatted string throught USART. I use it to print out debug info.

Everything looks fine but when I run that I get some strange behavior. The output is:

 

    Set status:28
    Get status:24
    Byte0:80
    Byte1:0
    Byte2:10

 

Firstly I set status register using WRSR opcode. it should set it to 00011100 but when I read the status using RDSR opcode I get 00011000.

Ok, maybe there is some trouble with status register. Then I try to read ID register using RDID opcode. It should return 3 bytes - 0xC2 0x20 0x14. But insted I get 0x80 0x0 0x10.

It would be understandable if I get no answer or all 0x00 or 0xFF. But here I read some answer, the problem that the response is totally wrong. Even more interesting is that if I connect the EEPROM to Arduino using almost the same code it works without problem.

I feel that the problem is quite small. It looks that maybe some data order wrong or transfer speed or something like that but I can't get it work.

Last Edited: Sun. Aug 27, 2017 - 08:44 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi !

 

try to insert some pauses between two write actions to EEPROM.

 

Check SPI MODE.

 

Why do you use EEPROM?

I use F-RAM instead.

 

 

 

 

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

This memory chip works with SPI modes 0 and 3. Currently CPOL=0, CPHA=0 so it in mode 0 but I've also tried mode 3 - the same result.

I've inserted delay but unfortunately that doesn't help.
As for FRAM I  think it's too expensive, now my 8M chip costs about 1$.

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

Your code looks fine to me. However it is UNWISE to use |= when initialising SPI.
The device should work ok @ 8Mhz.
There is no need for any delays. You can poll STATUS to check for busy.
.
I don't have your particular Flash chip but a regular 25Qxxx should work the same. I will try your code later.
.
David.

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

I ran your program on a 3.3V XMINI-328P with an A25L032.   My /CS is on PD5.  Only other change to your code is:

void DEBUG_PRINT(const char *fmt, int arg)
{
    char buf[40];
    sprintf(buf, fmt, arg);
    Serial.print(buf);
}

void setup(void)
{
    Serial.begin(9600);
    SPI_Init();

    byte status = 0x1C;
    DEBUG_PRINT("\r\nSet status:%d\r\n", status);
    ...

Output was:


Set status:28

Get status:28
Byte0:37
Byte1:30
Byte2:16

I will have to read what the status bits mean.   But the ID is correct : 37 30 16

 

David.

Last Edited: Sat. Aug 26, 2017 - 07:31 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The schematic is very simple

And WRONG! if that's exactly how it is wired.

John Samperi

Ampertronics Pty. Ltd.

https://www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

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

I hope you actually have some bypass caps. LM317 needs one for stability and MCU needs one for proper operation. One good cap, say 1uf to 10uf, ceramic, should serve both functions.

 

Also, you MUST power AVcc. If you are not using an analog function, just connect it to Vcc.

 

How do you program the Mega8? Most programming systems use the /RESET line for programming. That is REALLY hard when it is tied to Vcc.

 

Also, I see no serial connections. Kinda hard for DEBUG_PRINT() to work without serial!

 

Clearly, there is either a lot that you are not showing us, OR you are giving us meaningless numbers.

 

Jim

 

Until Black Lives Matter, we do not have "All Lives Matter"!

 

 

Last Edited: Sat. Aug 26, 2017 - 10:43 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thank you guys for your response!!
Probably I was a bit inaccurate while describing the problem. 

I'm more of a programmer than hardware engineer. This is just my hobby.

I've updated the scheme to complete missing components.

I program the chip using AVRISP mkii programmer (like here)

To communicate with serial port I use USB to TTL UART Module (like here)

RESET connected to 5V through 470R resistor. I don't really know why, but this is the only way I could connect  AVRISP to uC. I've just found this scheme in the Internet.

david.prentice, thanks for testing the code. If that works for you the only point I guess is a power supply.

ka7ehk, how should I connect capacitors as you advised?

 

I am very grateful to all who responded. Any edits/corrections will be greatly appreciated.

Last Edited: Sun. Aug 27, 2017 - 09:03 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I am utterly gobsmacked.
.
You can find proven schematics for the megaxx8 family. Just copy them religiously. e.g. same schematic, same components, same layout.
The Atmel app notes will give advice on external components. Useful reading but it is far easier to just replicate an existing commercial design. I say commercial because this means they have designed properly. Do NOT copy hobbyist tutorials from the internet.
.
470R on the Reset pin is wrong. What value do real boards use?
AVCC pin must be connected.
LM317 needs capacitors. ATmegaxx8 needs 100nF ceramic capacitors. Likewise your memory chip.
As I said. COPY a proven design.
.
David.
.
p.s. I am happier with software. But not too proud to steal the electrical design from a hardware engineer.

Last Edited: Sun. Aug 27, 2017 - 09:29 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks David.
I can't find any good example of connecting ATMEGA8 to a serial flash memory.
Ok, I understand that my schematic is terrible. But what I can't understand is how can I improve that.

That was a reason I've started the topic.

The scheme is exactly the same as real board. Everything works fine except of course serial memory chip.

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

If that is a real board, you should shoot the designer.
.
My first step is always to look at Arduino schematics. But there must be thousands of publicly available schematics for mega8.
You just connect the SPI chip. (100nF on VCC,GND pins)
.
I suggest that you fix your hardware first. Then post the accurate schematic.
.
A confession. My SPI chip is mounted on a Protoshield without specific 100nF. However the commercial 3.3V "Uno" does have the correct 100nF on the proven pcb. So the Shield relies on the main board capacitors.
.
David.

Last Edited: Sun. Aug 27, 2017 - 12:07 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

No uC circuit can work reliably without decoupling Cap's.

 

I haven't analysed it too closely, but what is your memory chip doing during programmin of the AVR?

Doing magic with a USD 7 Logic Analyser: https://www.avrfreaks.net/comment/2421756#comment-2421756

Bunch of old projects with AVR's: http://www.hoevendesign.com