ATtiny1624 - Interrupts when BOOTEND is utilized

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

Hi everyone,

 

I am using ATtiny1624 configured into two memory sections: BOOT and APPDATA as described in the datasheet (3rd line in the table):

 

Setting Up Flash Sections

 

The goal is to have the application in BOOT section while APPDATA will be used as a storage place accesses from the BOOT. For this reason, both BOOTEND and APPEND are set to 0x28 providing thus 10K for the BOOT and 6K for the APPDATA sections. I can verify the flash write functionality to the APPDATA and everything seems to work fine except the interrupts. Setting BOOTEND to a value other than 0 causes interrupt issues (no IRQs are issued). I know that in this case interrupt vector relocation takes place and IVSEL needs to be set in order to use the interrupt vectors placed at the beginning of the BOOT section. In my case though, setting IVSEL did not produce the expected result. Bellow is a snapshot from the lss file:

Disassembly of section .text:

00000000 <__vectors>:
   0:	0c 94 3c 00 	jmp	0x78	; 0x78 <__ctors_end>
   4:	0c 94 4e 00 	jmp	0x9c	; 0x9c <__bad_interrupt>
   8:	0c 94 4e 00 	jmp	0x9c	; 0x9c <__bad_interrupt>
   c:	0c 94 4e 00 	jmp	0x9c	; 0x9c <__bad_interrupt>
  10:	0c 94 4e 00 	jmp	0x9c	; 0x9c <__bad_interrupt>
  14:	0c 94 4e 00 	jmp	0x9c	; 0x9c <__bad_interrupt>
  18:	0c 94 4e 00 	jmp	0x9c	; 0x9c <__bad_interrupt>
  1c:	0c 94 4e 00 	jmp	0x9c	; 0x9c <__bad_interrupt>
  20:	0c 94 4e 00 	jmp	0x9c	; 0x9c <__bad_interrupt>
  24:	0c 94 4e 00 	jmp	0x9c	; 0x9c <__bad_interrupt>
  28:	0c 94 4e 00 	jmp	0x9c	; 0x9c <__bad_interrupt>
  2c:	0c 94 4e 00 	jmp	0x9c	; 0x9c <__bad_interrupt>
  30:	0c 94 4e 00 	jmp	0x9c	; 0x9c <__bad_interrupt>
  34:	0c 94 4e 00 	jmp	0x9c	; 0x9c <__bad_interrupt>
  38:	0c 94 98 02 	jmp	0x530	; 0x530 <__vector_14>
  3c:	0c 94 4e 00 	jmp	0x9c	; 0x9c <__bad_interrupt>
  40:	0c 94 4e 00 	jmp	0x9c	; 0x9c <__bad_interrupt>
  44:	0c 94 19 03 	jmp	0x632	; 0x632 <__vector_17>
  48:	0c 94 4e 00 	jmp	0x9c	; 0x9c <__bad_interrupt>
  4c:	0c 94 4e 00 	jmp	0x9c	; 0x9c <__bad_interrupt>
  50:	0c 94 4e 00 	jmp	0x9c	; 0x9c <__bad_interrupt>
  54:	0c 94 4e 00 	jmp	0x9c	; 0x9c <__bad_interrupt>
  58:	0c 94 4e 00 	jmp	0x9c	; 0x9c <__bad_interrupt>
  5c:	0c 94 4e 00 	jmp	0x9c	; 0x9c <__bad_interrupt>
  60:	0c 94 4e 00 	jmp	0x9c	; 0x9c <__bad_interrupt>
  64:	0c 94 4e 00 	jmp	0x9c	; 0x9c <__bad_interrupt>
  68:	0c 94 48 03 	jmp	0x690	; 0x690 <__vector_26>
  6c:	0c 94 4e 00 	jmp	0x9c	; 0x9c <__bad_interrupt>
  70:	0c 94 4e 00 	jmp	0x9c	; 0x9c <__bad_interrupt>
  74:	0c 94 4e 00 	jmp	0x9c	; 0x9c <__bad_interrupt>

And the following code is used to enable interrupt vector relocation in BOOT section :

 

void SystemInit()
{
	_PROTECTED_WRITE(CPUINT.CTRLA, (CPUINT.CTRLA | CPUINT_IVSEL_bm));
	ClockInit();	
	UsartInit();
	sei();
}

  

Please note that when BOOTEND and APPEND are set to 0, interrupts work without issues.

Moreover, I did not modify the linker script and I am using the default one. 

 

I would appreciate any info about using the interrupts when BOOTEND is utilized.

 

Thanks in advance,

 

 

This topic has a solution.
Last Edited: Fri. Nov 12, 2021 - 11:15 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You are splitting your application into two memory sections that are not used for the application program.  The BOOT section is for loading a new application program and the APP DATA section is for storage of constants or configuration values.

 

What happens when you set up your application as suggested: a bootloader, followed by the application, and at the top of the flash memory, a section for storing data?  Is the amount of data that will be stored less than 256 bytes?  If yes, then I recommend using the EEPROM of the tiny1624.

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

It's not strange and not a mistake to split the flash into a BOOT section and an APPDATA section as the OP did.

It's a natural act, and of course I do it too.

I'm interested in this phenomenon, but now that I'm working from home, I don't have a device to test. It's a shame.

I have never manipulated IVSEL when I did the same.

Last Edited: Thu. Nov 11, 2021 - 03:58 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

 Setting bootend and AppEnd and makes 3 memory sections not 2.  Only use bootend and if you want to have application section and boot loader section. Bootend is the size of the bootloader. Example 0x01 is 256 bytes of bootloader and App section starts at byte offset 256.  The methodology is different than old avr technology. AppEnd  Is used as a second type of Eeprom but is flash, you can take the end of your unused app section and use it to store settings and stuff.

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

Why do you need 3 sections?

For OP applications, the BOOT and APPDATA sections are sufficient, and there is no need for an APP section

Why do you force a "boot loader" in the BOOT section?

 

I have already made a number of products with OP-like configurations.
I don't use a "boot loader" so I don't create an APP section. That's no problem.

 

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

Hi,

 

Thank you for replying.

 

@Simonetta

Unfortunately, I need about 5K storage area which will be updated (not frequently) by an external host machine through the UART. This is the reason I need a specific memory section in the flash (to write/read in/from that section from the application).

 

@12oclocker

I understand, but according to the datasheet, when APPEND equals BOOTEND, there are two sections (BOOT and APPDATA) as described in the table of this post.

 

@kabasan

That's what I want also to achieve using ATtiny1624 with the interrupt vector placed in the BOOT section. 

 

------------------------------------------------------------------------------------------------------------------------------------

 

If I need BOOT, APPCODE and APPDATA sections that's fine. I can live with that. But, what I do not understand:

  • Why the option of using only BOOT and APPDATA is given if someone cannot use it
  • Why interrupts work fine in the default values of BOOTEND/APPEND (these fuses are set by default to 0). In this case, the entire flash is considered a single BOOT section.
  • IVSEL is assumed to do the job of relocating the interrupt vector. In my case this did not work.       

 

 

Best regards

 

 

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

What happens if you have AppEnd only?  That would achieve the same write permissions (as I read the datasheet (Application can write to Appdata), but you wouldn't need to change ivsel...

(or for that matter, BOOTEND and APPEnd==FlashEnd, WITH ivsel.)

I'm not sure why one would use AppEnd unless you really need all three different "protections", and the "Boot + AppData" seems the most "weird."

 

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

Setting bootend and AppEnd and makes 3 memory sections not 2

There are 2 fuses to set, and w​​​​​​hen they are the same value then there is no APPCODE section as the datasheet indicates. So only 2 sections are in use here- BOOT and APPDATA.

 

I have a tiny416 hooked up, set the boot and append fuses to 8- simple rtc interrupt app toggling an led, if IVSEL remains 0 then it does not work so will just assume the vector table address is tied to the fuse BOOTEND value when IVSEL is 0 (even though we do not have an APPCODE section). When IVSEL is set to 1, then the blinky works since the vector table is now at 0x0000 (BOOT).

 

The tiny 1624 should be no different as they are all basically the same mcu. Setting IVSEL should get the vector address to 0x0000 no matter what, so hard to imagine what could be going on- reduce your test to something very simple like I did, if its not already simple. You could also probably use a debugger- single step, get an interrupt to fire and see where you end up.

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

@westfw

I don't remember if I tried this setting but I will do that. According to the datasheet though, this seems not a valid combination of the fuse settings.

 

@curtvm

Yeah, I will modify the implementation to make it as simple as possible (I will use only the init and UART IRQ). In your case, you didn't have to modify the linker script. The only required action was to set the IVSEL bit. Right?

 

I don't have access to the hardware right now but I will conduct these tests in the afternoon and let you know about the results.

 

Best regards, 

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

APPEND sets the end of the App section. BOOTEND sets the end of boot section.

Attachment(s): 

Last Edited: Thu. Nov 11, 2021 - 09:26 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

This is not clear to me. According to the datasheet (ATtiny1624-26-27-DataSheet-DS40002234A.pdf, page 66, Table 10.1, line 3):

BOOTEND can be > 0 and APPEND can be == BOOTEND

In this case there is no APPCODE but only BOOT and APPDATA.

 

Best regards, 

This reply has been marked as the solution. 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0


 

I have tiny1616, so I tried it.

Reads data from the APPDATA section, blinking the LED with an interrupt.

My memory was wrong about IVSEL.

 

BOOT section: 0-2KB

APP section: None

APPDATA section: 2KB-

 

#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <avr/cpufunc.h>
////////////////////////////////////////////////////////////////
// FUSES
////////////////////////////////////////////////////////////////
FUSES = {
    .WDTCFG     = FUSE_WDTCFG_DEFAULT,
    .BODCFG     = FUSE_BODCFG_DEFAULT,
    .OSCCFG     = FUSE_OSCCFG_DEFAULT,
    .TCD0CFG    = FUSE_TCD0CFG_DEFAULT,
    .SYSCFG0    = FUSE_SYSCFG0_DEFAULT,
    .SYSCFG1    = FUSE_SYSCFG1_DEFAULT,
    .APPEND     = 8,
    .BOOTEND    = 8,
};

////////////////////////////////////////////////////////////////
// APPDATA
////////////////////////////////////////////////////////////////
static const uint8_t __attribute__ ((section (".darea"))) data[] = {
    0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF,
};
////////////////////////////////////////////////////////////////
// MAIN
////////////////////////////////////////////////////////////////
volatile uint8_t test_buf[16] = {0};
int main(void){
    // PORT
    PORTA.PIN0CTRL = PORT_ISC_INPUT_DISABLE_gc;
    PORTA.PIN1CTRL = PORT_ISC_INPUT_DISABLE_gc;
    PORTA.PIN2CTRL = PORT_ISC_INPUT_DISABLE_gc;
    PORTA.PIN3CTRL = PORT_ISC_INPUT_DISABLE_gc;
    PORTA.PIN4CTRL = PORT_ISC_INPUT_DISABLE_gc;
    PORTA.PIN5CTRL = PORT_ISC_INPUT_DISABLE_gc;
    PORTA.PIN6CTRL = PORT_ISC_INPUT_DISABLE_gc;
    PORTA.PIN7CTRL = PORT_ISC_INPUT_DISABLE_gc;

    PORTB.PIN0CTRL = PORT_ISC_INPUT_DISABLE_gc;
    PORTB.PIN1CTRL = PORT_ISC_INPUT_DISABLE_gc;
    PORTB.PIN2CTRL = PORT_ISC_INPUT_DISABLE_gc;
    PORTB.PIN3CTRL = PORT_ISC_INPUT_DISABLE_gc;
    PORTB.PIN4CTRL = PORT_ISC_INPUT_DISABLE_gc;
    PORTB.PIN5CTRL = PORT_ISC_INPUT_DISABLE_gc;

    PORTC.PIN0CTRL = PORT_ISC_INPUT_DISABLE_gc;
    PORTC.PIN1CTRL = PORT_ISC_INPUT_DISABLE_gc;
    PORTC.PIN2CTRL = PORT_ISC_INPUT_DISABLE_gc;
    PORTC.PIN3CTRL = PORT_ISC_INPUT_DISABLE_gc;

    // LED ON
    PORTB.DIRSET = PIN0_bm;
    PORTC.DIRSET = PIN0_bm;
    PORTC.OUTSET = PIN0_bm;

    // TCA 1Hz
    TCA0.SINGLE.PER = 1627;
    TCA0.SINGLE.INTFLAGS = TCA0.SINGLE.INTCTRL = TCA_SINGLE_OVF_bm;
    TCA0.SINGLE.CTRLA = TCA_SINGLE_CLKSEL_DIV1024_gc | TCA_SINGLE_ENABLE_bm;

    _PROTECTED_WRITE(CPUINT.CTRLA, CPUINT_IVSEL_bm);
    sei();
    _NOP(); // break point 1

    memcpy_P((uint8_t*)test_buf, (uint8_t*)data, 16);
    _NOP(); // break point 2

    while (1) {
    }
}
////////////////////////////////////////////////////////////////
// TCA0 INTERRUPT(LED TOGGLE)
////////////////////////////////////////////////////////////////
ISR(TCA0_OVF_vect){
    TCA0.SINGLE.INTFLAGS = TCA_SINGLE_OVF_bm;
    PORTC.OUTTGL = PIN0_bm;
}

 

 

At breakpoint 1, the initial value in the test buffer is zero.

At breakpoint 2, the data in the APPDATA section is copied to the test buffer.

From the address of data(0x0800) you can see that this is in the flash area.

Then the interrupt works fine and the LED flashes at 1Hz.

If this doesn't work on tiny2, you should definitely verify it.

It's a serious problem for me.

 

 

Last Edited: Thu. Nov 11, 2021 - 05:06 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

They CANNOT BE EQUAL, unless both are zero. Otherwise the END of both sections is the same location, and WRONG.

They can be equal, which then means there is no appcode section in use. You need to look in the NVMCTRL section of the datasheet, which was shown in the original post.

 

In your case, you didn't have to modify the linker script. The only required action was to set the IVSEL bit. Right?

I simply set the fuses as I described (just picked values 8/8 for the test), created small app with irq, tested with/without IVSEL=1.

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

I've always used a bootloader with application section and a settings section, I tried it and I see what you are saying. That part in the datasheet is confusing compared to the old methodology.

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

Hi all and thank you very much for the time you spent to reply.

 

I used the example provided by @kabasan (many thanks!) with minor modifications to comply with my hardware setup. The example helped me to verify that ISR works as expected! Moreover, I added the UART configuration with the associated ISR, in the provided example, and that worked too!

 

So, something in my initial implementation causes the described misbehavior. Actually, I did some early simplification of my initial implementation and noticed that the write-to-flash function might produce this kind of issue. Maybe it corrupts the interrupt vectors (although I don't see how this could happen). I will look into this tomorrow and let you know about the outcome.

 

Best regards,

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

I'm twice as happy that it helped you and that the device didn't have an Elatta.

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

Hi again,

 

I did some debugging in my implementation and found that the behavior I described was caused by the EEREADY interrupt which was not properly handled. Since this interrupt will be fired as soon as it is enabled (usually EEPROM will be ready to accept read/write commands), it blocks other interrupts from being serviced. Fixing the EEREADY interrupt handling, fixed also the issue I described in this post. It seems my initial tests were not as comprehensive as needed to catch the EEAREDY handling bug.

 

To summarize:

  • Software implementation having BOOT and APPDATA sections (and without APPCODE) works fine (configured as described in the datasheet)
  • Using ISRs in the BOOT section needs IVSEL to be set '1  

 

Again, thanks all for replying.

 

Best regards,