EEPROM and ATTiny816

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

Hi, I seams there are some major changes accessing the EEPROM on the new 1-series Tinys. Has anyone a code sample or a link how to write and read bytes in the EEPROM of an ATTiny816 (or compatible) ? Assembler preferred.

Thanx in advance!

 

Mike

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

I will put the code I tested.

 

/*
 * Assembler1.s
 */
#include <avr/io.h>

#define DATA    0xAB
#define ADDR    0x1400

.section .text

.global test_eep
test_eep:

 ; Set EEPROM addr
    ldi     r24, lo8(ADDR)
    ldi     r25, hi8(ADDR)
    sts     NVMCTRL_ADDRL, r24
    sts     NVMCTRL_ADDRH, r25

; Page Buffer Clear
    in      r0, SREG
    cli
    ldi     r25, 0x04               ; NVMCTRL_CMD_PAGEBUFCLR_gc
    ldi     r24, 0x9D               ; CCP_SPM_gc
    out     CCP, r24
    sts     NVMCTRL_CTRLA, r25      ; Clear
    out     SREG, r0
    nop

; Put data
    ldi     r24, DATA
    sts     ADDR, r24

; Rewrite
    in      r0, SREG
    cli
    ldi     r25, 0x03               ; NVMCTRL_CMD_PAGEERASEWRITE_gc
    ldi     r24, 0x9D               ; CCP_SPM_gc
    out     CCP, r24
    sts     NVMCTRL_CTRLA, r25      ; Clear
    out     SREG, r0
    nop

; wait ready
1:  lds     r24, NVMCTRL_INTFLAGS
    sbrs    r24, 0
    rjmp    1b
    ldi     r24, 0x01
    sts     NVMCTRL_INTFLAGS, r24

    ret

 

Last Edited: Mon. Mar 12, 2018 - 07:43 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi kabasan,

 

Thanx a lot! works as advertised :)

I see a lot of interrupt handling in your code. I tested it without all this and it works. Is it necessary for correct function?

 

Mike

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

I put cli and sei as promises where I have to be atomic processing.
If you omit it, you will be in trouble in the future.
The sts instruction after out CCP, r24 must be within 4 instructions.

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

MikeRD03 wrote:
I see a lot of interrupt handling in your code. I tested it without all this and it works. Is it necessary for correct function?

FULL BLOWN EDIT: See post #8 for the correct answer!  I'll leave the stuff below for reference.

 

​Mike, that is not interrupt handling in the code, that is CCP - Configuration Change Protection and NVMCTRL - Non Volatile Memory Controller handling, they are needed.  Read the datasheet.  Did you test it on real hardware?

 

EDIT:  I missed the cli in there, if you are not using interrupts, then no you don't need the cli. Just don't forget to use them when you do use interrupts.  I agree with kabasan's advice in his post above.

 

8.5.7 CCP - Configuration Change Protection

System critical I/O register settings are protected from accidental modification. Flash self-programming
(via store to NVM controller) is protected from accidental execution. This is handled globally by the
configuration change protection (CCP) register.

Changes to the protected I/O registers or bits, or execution of protected instructions, are only possible
after the CPU writes a signature to the CCP register. The different signatures are listed in the description
of the CCP register (CPU.CCP).

There are two modes of operation: one for protected I/O registers, and one for the protected self-programming.

Also see paragraph 9.3.2.4 Commands in section 9. NVMCTRL - Non Volatile Memory Controller, in fact read all of that section. 

"I may make you feel but I can't make you think" - Jethro Tull - Thick As A Brick

"void transmigratus(void) {transmigratus();} // recursio infinitus" - larryvc

"It's much more practical to rely on the processing powers of the real debugger, i.e. the one between the keyboard and chair." - JW wek3

"When you arise in the morning think of what a privilege it is to be alive: to breathe, to think, to enjoy, to love." -  Marcus Aurelius

Last Edited: Mon. Mar 12, 2018 - 06:59 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Ok, I understand. I have interrupt handling in my code, so I added the CLI and SEI before and after. Thank you for advise!

 

Mike

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

MikeRD03 wrote:
so I added the CLI and SEI before and after
I would suggest doing it as shown by kabasan:

save SREG

CLI

Do stuff that must not be interrupted

restore SREG

 

This will restore the interrupt status to whatever it was prior to disabling the interrupts.

You can do CLI / Do Stuff / SEI iff you KNOW the routine is never entered while interrupts are disabled.

 

David (aka frog_jr)

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

Learn something new every day!

 

Kabasan, Mike, David, and Larry,  there is absolutely no need whatsoever to worry about interrupts while performing a CCP operation!  Atomicity is guaranteed and handled automatically during the CCP operation.

 

8.7 Register Description

 

8.7.1 Configuration Change

 

ProtectionBits 7:0 – CCP[7:0]: Configuration Change Protection

 

Writing the correct signature to this bit field allows changing protected I/O registers or executing protected
instructions within the next four CPU instructions executed.

 

All interrupts are ignored during these cycles. After these cycles, interrupts will automatically be handled
again by the CPU, and any pending interrupts will be executed according to their level and priority.

 

When the protected I/O register signature is written, CCP[0] will read as '1' as long as the CCP feature is
enabled.

 

When the protected self-programming signature is written, CCP[1] will read as '1' as long as the CCP
feature is enabled.

 

CCP[7:2] will always read as zero.

kabasan's code can now become this:

/*
 * Assembler1.s
 */
#include <avr/io.h>

#define DATA    0xAB
#define ADDR    0x1400

.section .text

.global test_eep
test_eep:

 ; Set EEPROM addr
    ldi     r24, lo8(ADDR)
    ldi     r25, hi8(ADDR)
    sts     NVMCTRL_ADDRL, r24
    sts     NVMCTRL_ADDRH, r25

; Page Buffer Clear
    ldi     r25, 0x04               ; NVMCTRL_CMD_PAGEBUFCLR_gc
    ldi     r24, 0x9D               ; CCP_SPM_gc
    out     CCP, r24
    sts     NVMCTRL_CTRLA, r25      ; Clear
    nop

; Put data
    ldi     r24, DATA
    sts     ADDR, r24

; Rewrite
    ldi     r25, 0x03               ; NVMCTRL_CMD_PAGEERASEWRITE_gc
    ldi     r24, 0x9D               ; CCP_SPM_gc
    out     CCP, r24
    sts     NVMCTRL_CTRLA, r25      ; Clear
    nop

; wait ready
1:  lds     r24, NVMCTRL_INTFLAGS
    sbrs    r24, 0
    rjmp    1b
    ldi     r24, 0x01
    sts     NVMCTRL_INTFLAGS, r24

    ret

I knew I had read that before, and Mike's questioning the interrupt handling and my post about CCP and NVMCTL started to gnaw at me.  Glad I took a second look.

 

"I may make you feel but I can't make you think" - Jethro Tull - Thick As A Brick

"void transmigratus(void) {transmigratus();} // recursio infinitus" - larryvc

"It's much more practical to rely on the processing powers of the real debugger, i.e. the one between the keyboard and chair." - JW wek3

"When you arise in the morning think of what a privilege it is to be alive: to breathe, to think, to enjoy, to love." -  Marcus Aurelius

Last Edited: Mon. Mar 12, 2018 - 07:25 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Ok, thanks for clearing it up. I do understand the problem. In this case I CAN be sure the Interrupt is ON when entered. But I see this small detail :) Thanx! 

 

Mike

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

larryvc wrote:
I knew I had read that before, and Mike's questioning the interrupt handling and my post about CCP and NVMCTL started to gnaw at me.  Glad I took a second look.

 

I saw your answer after replying. And now you quoted this part of the datasheet I remembered, too. Read it one day before. :) Seams Microchip made its homework. ;)

Thanx a lot - great community here.

 

Mike

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

What is that!
I missed that cli is unnecessary even at xmega.
I learned very much.

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

I know this is over a year old, but for those trying to squeeze code on TinyAvr1 TinyAvr0 series...

Setting of NVMCTRL_ADDRL and NVMCTRL_ADDRH is not necessary. You can skip that step.

You simply copy the data to the mapped memory address.

Only when the UPDI is writing a Fuse Byte (which only the UPDI can do) is it necessary to use NVMCTRL_ADDR and NVMCTRL_DATA.

NVMCTRL_ADDR will be the address of the last data written, once data is written, and it is not necessary to set it for EEPROM or Flash data writes.

 

//not necessary
 ; Set EEPROM addr
    ldi     r24, lo8(ADDR)
    ldi     r25, hi8(ADDR)
    sts     NVMCTRL_ADDRL, r24
    sts     NVMCTRL_ADDRH, r25
//the processor gets the write address from this instruction.
; Put data
    ldi     r24, DATA
    sts     ADDR, r24