Skip to content

riotboot/Makefile.include: increase RIOTBOOT_HRD_LEN for ARMv7*-M#11641

Merged
fjmolinas merged 2 commits intoRIOT-OS:masterfrom
fjmolinas:pr_riotboot_m4
Jun 18, 2019
Merged

riotboot/Makefile.include: increase RIOTBOOT_HRD_LEN for ARMv7*-M#11641
fjmolinas merged 2 commits intoRIOT-OS:masterfrom
fjmolinas:pr_riotboot_m4

Conversation

@fjmolinas
Copy link
Contributor

Contribution description

"ARMv7-M Architecture Reference Manual" B1.5.3 The vector table

The Vector table must be naturally aligned to a power of two whose alignment value is greater than or equal to (Number of Exceptions supported x 4), with a minimum alignment of 128 bytes.

"Cortex-M4 Devices Generic User Guide" 4.3.4. Vector Table Offset Register

The minimum alignment is 32 words, enough for up to 16 interrupts. For more interrupts, adjust the alignment by rounding up to the next power of two. For example, if you require 21 interrupts, the alignment must be on a 64-word boundary because the required table size is 37 words, and the next power of two is 64.

Currently by default RIOTBOOT_HDR_LEN is defined at 0x100 this is fine for M0/M0+/M1 who only have 48 interrupts so round_po2(4x48) = 0x100. But for ARMv7*-M the maximum number of interrups is 256 and in this case round_po2(4x256) = 0x400.

In must cases supported ISR in our boards is around 100, not more than 127. But the default case should work for all cpu/boards and when implementing riotboot for specific board this should be trimmed accordingly (for most ARMv7*-M 0x200 would be enough)

If the alignment isn't fixed form the 0x100 a hardfault occurs when trying to make riotboot work on otherwise almost enabled boards.

Testing procedure

With this PR running the following command succeeds with no hard fault:

FEATURES_REQUIRED+=riotboot BOARD=pba-d-01-kw2x make -C tests/xtimer_usleep/ clean riotboot/flash term

Without this PR running the following command succeeds with no hard fault:

2019-06-06 11:26:18,080 - INFO # Context before hardmain(): This is RIOT! (Version: 2019.07-devel-603-g86720-pr_riotboot_kw2x)
2019-06-06 11:26:18,085 - INFO # Running test 5 times with 7 distinct sleep times
2019-06-06 11:26:18,089 - INFO # Please hit any key and then ENTER to continue
2019-06-06 11:26:18,101 - INFO # 
2019-06-06 11:26:18,102 - INFO # Context before hardfault:
2019-06-06 11:26:18,104 - INFO #    r0: 0x00000000
2019-06-06 11:26:18,106 - INFO #    r1: 0x0000000b
2019-06-06 11:26:18,107 - INFO #    r2: 0x1fffc274
2019-06-06 11:26:18,109 - INFO #    r3: 0x00008080
2019-06-06 11:26:18,112 - INFO #   r12: 0x00000000
2019-06-06 11:26:18,113 - INFO #    lr: 0x0000174d
2019-06-06 11:26:18,115 - INFO #    pc: 0x0000174e
2019-06-06 11:26:18,116 - INFO #   psr: 0x01000041
2019-06-06 11:26:18,116 - INFO # 
2019-06-06 11:26:18,116 - INFO # FSR/FAR:
2019-06-06 11:26:18,117 - INFO #  CFSR: 0x00000000
2019-06-06 11:26:18,118 - INFO #  HFSR: 0x40000000
2019-06-06 11:26:18,120 - INFO #  DFSR: 0x00000000
2019-06-06 11:26:18,122 - INFO #  AFSR: 0x00000000
2019-06-06 11:26:18,122 - INFO # Misc
2019-06-06 11:26:18,123 - INFO # EXC_RET: 0xfffffff1
2019-06-06 11:26:18,128 - INFO # Attempting to reconstruct state for debugging...
2019-06-06 11:26:18,129 - INFO # In GDB:
2019-06-06 11:26:18,131 - INFO #   set $pc=0x174e
2019-06-06 11:26:18,131 - INFO #   frame 0
2019-06-06 11:26:18,132 - INFO #   bt
2019-06-06 11:26:18,132 - INFO # 
2019-06-06 11:26:18,135 - INFO # ISR stack overflowed by at least 72 bytes.

Issues/PRs references

@fjmolinas fjmolinas added Platform: ARM Platform: This PR/issue effects ARM-based platforms Area: OTA Area: Over-the-air updates labels Jun 6, 2019
@fjmolinas fjmolinas requested review from cladmi and kaspar030 June 6, 2019 09:28
@cladmi
Copy link
Contributor

cladmi commented Jun 6, 2019

The testing procedure in here cannot work currently.
It requires to have FEATURES_PROVIDED += riotboot in the board first so need to be tested with #11642 (setting FEATURES_PROVIDED from the command line cannot work due to the env -i in the build of the bootloader).

On my side, I currently have no output for my pba-d-01-kw2x even with tests/riotboot

@cladmi
Copy link
Contributor

cladmi commented Jun 6, 2019

Would it be possible to assert this requirement in the code too ?
As the issue is not only specific to this test but only shown in this case.

@fjmolinas
Copy link
Contributor Author

I'm seeing other options for inforcing this... Alignment could be forced in the linker script itself

@fjmolinas fjmolinas added the Discussion: RFC The issue/PR is used as a discussion starting point about the item of the issue/PR label Jun 6, 2019
@cladmi
Copy link
Contributor

cladmi commented Jun 6, 2019

@fjmolinas you should rebase this PR on the current master, it does not include the kinetis.ld changes

@fjmolinas
Copy link
Contributor Author

@cladmi done, it should work now

@cladmi
Copy link
Contributor

cladmi commented Jun 6, 2019

@fjmolinas indeed it is better now :D

It now runs without crash

FEATURES_REQUIRED+=riotboot BOARD=pba-d-01-kw2x make -C tests/xtimer_usleep/ clean riotboot/flash term

...

2019-06-06 12:18:01,721 - INFO # SleptSlept for 12138 us (expected: 12122 us) Offset: 16 us
2019-06-06 12:18:01,722 - INFO # Slept for 98780 us (expected: 98765 us) Offset: 15 us
2019-06-06 12:18:01,722 - INFO # Slept for 75016 us (expected: 75000 us) Offset: 16 us
2019-06-06 12:18:01,723 - INFO # Slept for 10016 us (expected: 10000 us) Offset: 16 us
2019-06-06 12:18:01,723 - INFO # Slept for 50016 us (expected: 50000 us) Offset: 16 us
2019-06-06 12:18:01,724 - INFO # Slept for 10249 us (expected: 10234 us) Offset: 15 us
2019-06-06 12:18:01,725 - INFO # Slept for 56795 us (expected: 56780 us) Offset: 15 us
2019-06-06 12:18:01,725 - INFO # Slept for 12137 us (expected: 12122 us) Offset: 15 us
2019-06-06 12:18:01,726 - INFO # Slept for 98780 us (expected: 98765 us) Offset: 15 us
2019-06-06 12:18:01,726 - INFO # Slept for 75016 us (expected: 75000 us) Offset: 16 us
2019-06-06 12:18:01,727 - INFO # Slept for 10016 us (expected: 10000 us) Offset: 16 us
2019-06-06 12:18:01,727 - INFO # Slept for 50016 us (expected: 50000 us) Offset: 16 us
2019-06-06 12:18:01,728 - INFO # Slept for 10249 us (expected: 10234 us) Offset: 15 us
2019-06-06 12:18:01,728 - INFO # Slept for 56795 us (expected: 56780 us) Offset: 15 us
2019-06-06 12:18:01,729 - INFO # Slept for 12137 us (expected: 12122 us) Offset: 15 us
2019-06-06 12:18:01,730 - INFO # Slept for 98780 us (expected: 98765 us) Offset: 15 us
2019-06-06 12:18:01,730 - INFO # Slept for 75016 us (expected: 75000 us) Offset: 16 us
2019-06-06 12:18:01,731 - INFO # Slept for 10016 us (expected: 10000 us) Offset: 16 us
2019-06-06 12:18:01,732 - INFO # Slept for 50016 us (expected: 50000 us) Offset: 16 us
2019-06-06 12:18:01,732 - INFO # Slept for 10249 us (expected: 10234 us) Offset: 15 us
2019-06-06 12:18:01,753 - INFO # Slept for 56795 us (expected: 56780 us) Offset: 15 us
2019-06-06 12:18:01,770 - INFO # Slept for 12137 us (expected: 12122 us) Offset: 15 us
2019-06-06 12:18:01,873 - INFO # Slept for 98780 us (expected: 98765 us) Offset: 15 us
2019-06-06 12:18:01,953 - INFO # Slept for 75015 us (expected: 75000 us) Offset: 15 us
2019-06-06 12:18:01,967 - INFO # Slept for 10016 us (expected: 10000 us) Offset: 16 us
2019-06-06 12:18:02,022 - INFO # Slept for 50016 us (expected: 50000 us) Offset: 16 us
2019-06-06 12:18:02,037 - INFO # Slept for 10249 us (expected: 10234 us) Offset: 15 us
2019-06-06 12:18:02,098 - INFO # Slept for 56795 us (expected: 56780 us) Offset: 15 us
2019-06-06 12:18:02,115 - INFO # Slept for 12137 us (expected: 12122 us) Offset: 15 us
2019-06-06 12:18:02,219 - INFO # Slept for 98780 us (expected: 98765 us) Offset: 15 us
2019-06-06 12:18:02,298 - INFO # Slept for 75015 us (expected: 75000 us) Offset: 15 us
2019-06-06 12:18:02,301 - INFO # Test ran for 1727095 us

with this diff:

diff --git a/boards/pba-d-01-kw2x/Makefile.features b/boards/pba-d-01-kw2x/Makefile.features
index ee69accdd..a87c01d0d 100644
--- a/boards/pba-d-01-kw2x/Makefile.features
+++ b/boards/pba-d-01-kw2x/Makefile.features
@@ -8,6 +8,8 @@ FEATURES_PROVIDED += periph_spi
 FEATURES_PROVIDED += periph_timer
 FEATURES_PROVIDED += periph_uart
 
+FEATURES_PROVIDED += riotboot
+
 # The board MPU family (used for grouping by the CI system)
 FEATURES_MCU_GROUP = cortex_m4_3
 

and I have the crash in master as shown (with the diff applied too).

@cladmi
Copy link
Contributor

cladmi commented Jun 6, 2019

One good thing for the variable, we put the start address of a slot in the slot header and so it is not set at from compile time configuration in the type/bootloader code. (was a good choice @kYc0o :))

Which means that a bootloader compiled now would work in the future even if changing the RIOTBOOT_HDR_LEN.

So it is not required to always put the highest possible value as it is really board+firmware specific. Having it by default to this value could still be a sane default.

Local test to verify this:

BOARD=pba-d-01-kw2x make -C tests/riotboot clean flash test
2019-06-06 12:29:59,739 - INFO # slot 0: metadata: 0x1000 image: 0x00001200 # 0x200
2019-06-06 12:29:59,743 - INFO # slot 1: metadata: 0x20800 image: 0x00000000

RIOTBOOT_HDR_LEN=0x400 BOARD=pba-d-01-kw2x make -C tests/riotboot clean riotboot/flash-slot1 test
2019-06-06 12:30:26,540 - INFO # slot 0: metadata: 0x1000 image: 0x00001200
2019-06-06 12:30:26,544 - INFO # slot 1: metadata: 0x20800 image: 0x00020c00 # 0x400

RIOTBOOT_HDR_LEN=0x800 BOARD=pba-d-01-kw2x make -C tests/riotboot clean riotboot/flash-slot1 test
2019-06-06 12:30:46,332 - INFO # slot 0: metadata: 0x1000 image: 0x00001200
2019-06-06 12:30:46,336 - INFO # slot 1: metadata: 0x20800 image: 0x00021000 # 0x800

RIOTBOOT_HDR_LEN=0x1000 BOARD=pba-d-01-kw2x make -C tests/riotboot clean riotboot/flash-slot0 test
2019-06-06 12:31:53,536 - INFO # slot 0: metadata: 0x1000 image: 0x00002000 # 0x1000
2019-06-06 12:31:53,540 - INFO # slot 1: metadata: 0x20800 image: 0x00021000

@fjmolinas
Copy link
Contributor Author

+FEATURES_PROVIDED += riotboot

This isn't actually needed, if riotboot is not provided you get an "expect errors message" put the application will still compile (and in this case work).

So it is not required to always put the highest possible value as it is really board+firmware specific. Having it by default to this value could still be a sane default.

Indeed, it could also be defined for the specific boards/cpu (as done in #11642 and #11643). The good thing about this is that since by default it won't work, it will force the developer to look more carefully into RIOTBOOT_HDR_LEN value and set the minimum value accordingly for that board.

The thing is that if we are setting a default value, I think the default value should be sow that it works for most cases

Would it be possible to assert this requirement in the code too

This could be done by the bootloader, prevent a jump if the it is not aligned.

@cladmi
Copy link
Contributor

cladmi commented Jun 6, 2019

+FEATURES_PROVIDED += riotboot

This isn't actually needed, if riotboot is not provided you get an "expect errors message" but the application will still compile (and in this case work).

Indeed, I forgot that it is put in FEATURES_USED even if not PROVIDED. It will just be listed as missing.

For reference, without the FEATURES_PROVIDED you get

FEATURES_REQUIRED+=riotboot BOARD=mulle make -C tests/xtimer_usleep/ info-build  | grep -C 1 FEATURES

FEATURES_REQUIRED (excl. optional features):
         periph_spi periph_timer periph_uart riotboot
FEATURES_OPTIONAL (strictly "nice to have"):
         periph_gpio periph_pm
FEATURES_PROVIDED (by the board or USEMODULE'd drivers):
         cpp cpu_check_address periph_adc periph_cpuid periph_dac periph_gpio periph_gpio_irq periph_hwrng periph_i2c periph_mcg periph_pm periph_pwm periph_rtc periph_rtt periph_spi periph_timer periph_uart
FEATURES_MISSING (incl. optional features):
         riotboot
FEATURES_MISSING (only non-optional features):
         riotboot

FEATURES_CONFLICT:     
FEATURES_CONFLICT_MSG: 

And the value of FEATURES_USED that is not listed there

FEATURES_REQUIRED+=riotboot BOARD=mulle make --no-print-directory -C tests/xtimer_usleep/ info-debug-variable-FEATURES_USED
periph_gpio periph_pm periph_spi periph_timer periph_uart riotboot

@cladmi
Copy link
Contributor

cladmi commented Jun 6, 2019

The thing is that if we are setting a default value, I think the default value should be sow that it works for most cases

Agreed, so a sane "too big" default is not bad and could still be overwritten in the board.
However maybe the default would then be better in cortexm.inc.mk.

Would it be possible to assert this requirement in the code too

This could be done by the bootloader, prevent a jump if the it is not aligned.

The bootloader does not know the required alignment, as it depends on the number of exceptions.

@fjmolinas
Copy link
Contributor Author

The bootloader does not know the required alignment, as it depends on the number of exceptions.

There is a CPU_IRQ_NUMOF variable, would translate to 16 + CPU_IRQ_NUMOF exceptions. If the slot start address in the header isn't aligned with respect to 16 + CPU_IRQ_NUMOF it could avoid jumping to that image.

@cladmi
Copy link
Contributor

cladmi commented Jun 7, 2019

@fjmolinas Ah, so it is not application specific? I mean could a specifically crafted application/configuration increase or reduce the number of interrupts ?

This information would also really be useful in #11597

@fjmolinas
Copy link
Contributor Author

@fjmolinas Ah, so it is not application specific? I mean could a specifically crafted application/configuration increase or reduce the number of interrupts ?

Yes and No, you could but that would mean meddling with the vectors.c files. e.g.:

RIOT/cpu/stm32f4/vectors.c

Lines 141 to 147 in 7a264b2

/* CPU specific interrupt vector table */
ISR_VECTOR(1) const isr_t vector_cpu[CPU_IRQ_NUMOF] = {
/* shared vectors for all family members */
[ 0] = isr_wwdg, /* [ 0] Window WatchDog Interrupt */
[ 1] = isr_pvd, /* [ 1] PVD through EXTI Line detection Interrupt */
[ 2] = isr_tamp_stamp, /* [ 2] Tamper and TimeStamp interrupts through the EXTI line */
[ 3] = isr_rtc_wkup, /* [ 3] RTC Wakeup interrupt through the EXTI line */

When the cpu was ported a specific amount of interrupts where defined. If another new peripheral is added that could mean adding a new interrupt, that maybe wasn't added before. But as I understand by looking at the code, even if not used the vector is defined and therefor included in the vector table.

So for me it is not application specific, but CPU specific.

@kYc0o
Copy link
Contributor

kYc0o commented Jun 11, 2019

I can confirm is CPU specific and actually it MUST be 256B aligned according to the Cortex-M user manual. For this architecture I think there must be something similar, but I'd say to align it at 256B systematically so we don't risk too much.

For now, most of supported CPUs have less than 256 IRQ (mostly Cortex-M0+ and M3), then the M4 and M7 I think they have more, so they need at least a 512B for that.

Copy link
Contributor

@cladmi cladmi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some wording remarks, plus would like to have the link to the datasheet.
It would allow updating it later for new architecture and have all the context for justifying the values.

As it is CPU specific, its good to put the maximum possible required value by default.

# the Cortex-M0+/3/4/7 architecture
RIOTBOOT_HDR_LEN ?= 0x100
# Indicate the reserved space for a header.
# Notice that it must be at least 256B aligned. This is restricted by
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you update to remove the previous Notice that it must be at least 256 aligned and include this part in the following part. Currently it has two different informations mixed.

# Notice that it must be at least 256B aligned. This is restricted by
# the Cortex-M0+/3/4/7 architecture. "The Vector table must be naturally
# aligned to a power of two whose alignment value is greater than or equal
# to number of Exceptions supported x 4"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be good if you have a link for this information, it would be useful for porting future boards and justifying the values.

# the Cortex-M0+/3/4/7 architecture. "The Vector table must be naturally
# aligned to a power of two whose alignment value is greater than or equal
# to number of Exceptions supported x 4"
# For ARMv7-M/ARMv7E-M (M4, M3, M7). Maximum of 256 exceptions (256*4 bytes == 0x400).
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can put it as markdown style items with # * lalala

@fjmolinas
Copy link
Contributor Author

@cladmi Addressed your comments, let me know what you think.

@cladmi
Copy link
Contributor

cladmi commented Jun 18, 2019

The text is good for me, I could find the information in the datasheet, so any further modifications have everything needed.

I however just realized this is set in sys/riotboot/Makefile.include.
Do you want to keep it here or move it to cpu/cortexm_common/Makefile.include?

Question for further steps too.

Is this supposed to remove the need for the RIOTBOOT_HDR_LEN in kinetis and stm32l4 ? or should we keep them as they are smaller ?

With this pull request alone, I get

FEATURES_REQUIRED+=riotboot BOARD=pba-d-01-kw2x make --no-print-directory -C tests/xtimer_usleep/ info-debug-variable-RIOTBOOT_HDR_LEN
0x400

When rebased on master I get the kinetis configured value

FEATURES_REQUIRED+=riotboot BOARD=pba-d-01-kw2x make --no-print-directory -C tests/xtimer_usleep/ info-debug-variable-RIOTBOOT_HDR_LEN
0x200

@fjmolinas
Copy link
Contributor Author

I however just realized this is set in sys/riotboot/Makefile.include.
Do you want to keep it here or move it to cpu/cortexm_common/Makefile.include?

Good question, I was actually wandering the same thing and was going to point it out, I decided against it since for now riotboot is only really supported for cortex-m. I also though that having it here documents for some stuff a developer has to watch out when implementing riotboot. But re-thinking about it now this should be don in #11597.

If we move it I think a small comment should still be present mentioning generic alignment and maybe poiting out to cpu/cortexm_common/Makefile.include as an example.

Is this supposed to remove the need for the RIOTBOOT_HDR_LEN in kinetis and stm32l4 ? or should we keep them as they are smaller ?

I think we should keep it, every byte can count and if possible this should be optimized. Maybe we can add a comment that states this.

@cladmi
Copy link
Contributor

cladmi commented Jun 18, 2019

Good question, I was actually wandering the same thing and was going to point it out,

If we move it I think a small comment should still be present mentioning generic alignment and maybe poiting out to cpu/cortexm_common/Makefile.include as an example.

I like this

Is this supposed to remove the need for the RIOTBOOT_HDR_LEN in kinetis and stm32l4 ? or should we keep them as they are smaller ?

I think we should keep it, every byte can count and if possible this should be optimized. Maybe we can add a comment that states this.

Somehow saying in the definition file "this is the theoretical maximum, you may have a smaller one for your specific cpu/board"

- Since the Vector table must be naturally aligned to the next power
  of two of the amount of supported ISR, and the table will be
  placed after riotboot_hdr, we must ensure RIOTBOOT_HRD_LEN has the
  same alignment.
@fjmolinas
Copy link
Contributor Author

@cladmi I split the commit into two: one adding the cortex-m configuration and another adapting the comment on the generic sys/riotboo/Makefile.include.

I get the following outputs for different cpu's:

FEATURES_REQUIRED+=riotboot BOARD=pba-d-01-kw2x make --no-print-directory -C tests/xtimer_usleep/ info-debug-variable-RIOTBOOT_HDR_LEN
0x200
FEATURES_REQUIRED+=riotboot BOARD=cc2650stk make --no-print-directory -C tests/xtimer_usleep/ info-debug-variable-RIOTBOOT_HDR_LEN
0x400
FEATURES_REQUIRED+=riotboot BOARD=arduino-uno make --no-print-directory -C tests/xtimer_usleep/ info-debug-variable-RIOTBOOT_HDR_LEN
/bin/sh: 1: arithmetic expression: expecting primary: " + "
/bin/sh: 1: arithmetic expression: expecting primary: " + "
/bin/sh: 1: arithmetic expression: expecting primary: " + "
/bin/sh: 1: arithmetic expression: expecting primary: " + "
0x100

Which matches the expected behavior. What do you think?

@cladmi cladmi added the CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR label Jun 18, 2019
Copy link
Contributor

@cladmi cladmi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ACK good for me. The detailed explanation gives the required context to find the reason and future changes.

I get the same output for the tests as the last comment.

@cladmi
Copy link
Contributor

cladmi commented Jun 18, 2019

Please merge when CI is green, I will be afk in the next days.

@fjmolinas
Copy link
Contributor Author

Merging since @cladmi would be ACK, GO!

@fjmolinas fjmolinas merged commit 6db5aa0 into RIOT-OS:master Jun 18, 2019
@fjmolinas fjmolinas deleted the pr_riotboot_m4 branch August 7, 2019 15:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Area: OTA Area: Over-the-air updates CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR Discussion: RFC The issue/PR is used as a discussion starting point about the item of the issue/PR Platform: ARM Platform: This PR/issue effects ARM-based platforms

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants