Skip to content

Stack unification and test #7238

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 13 commits into from
Closed

Conversation

mprse
Copy link
Contributor

@mprse mprse commented Jun 18, 2018

Description

This PR provides test which verifies stack sizes:

  • ISR stack: exactly 1 kB,
  • Main thread stack: exactly 4 kB,
  • Default thread stack: exactly 4 kB,
  • RTOS-less thread stack: at least 4 kB - skipped for now since it looks like it is impossible to check RTOS-less thread (tests are built with RTOS).

Additionally PR provides fixes in linker scripts for some example targets. Can someone who has more experience with linker scripts check if these changes are correct? I could then proceed with the further targets.

Pull request type

[X] Fix
[ ] Refactor
[ ] New target
[ ] Feature
[ ] Breaking change

@mprse mprse force-pushed the stack_unification branch from dea671e to 9ccd700 Compare June 18, 2018 11:44
@0xc0170 0xc0170 requested review from a team June 18, 2018 11:49
bulislaw
bulislaw previously approved these changes Jun 19, 2018
@bulislaw
Copy link
Member

@SeppoTakalo fyi

SeppoTakalo
SeppoTakalo previously approved these changes Jun 19, 2018
Copy link
Contributor

@SeppoTakalo SeppoTakalo left a comment

Choose a reason for hiding this comment

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

Looks good.

@SeppoTakalo
Copy link
Contributor

Can you also add checks for the boot time stack?

I believe those are the same as RTOS-less builds. For example IAR seems to define it as define symbol __ICFEDIT_size_cstack__ = 0x400;
and it is not the same as main thread stack, as main thread stack is allocated here: https://github.com/ARMmbed/mbed-os/blob/master/rtos/TARGET_CORTEX/mbed_boot.c#L189

So if we set stack size in linker file to 4kB it is used in boot, before RTX starts, and then we allocate another 4kB for main thread and kick the kernel to run.

However, RTX seems to suggest that 300 bytes should be enough: https://www.keil.com/pack/doc/CMSIS/RTOS/html/theory.html

@SeppoTakalo
Copy link
Contributor

SeppoTakalo commented Jun 19, 2018

Or here: http://www.keil.com/support/man/docs/rlarm/rlarm_ar_technical_data.htm
it tells that 300 + 128 bytes for kernel.
which to me suggest, that within a linker file 428 should be the stack size we use. Not 4 kB

@mprse
Copy link
Contributor Author

mprse commented Jun 20, 2018

@SeppoTakalo In the test I am checking mbed_stack_isr_size which is defined based on CSTACK, ISR_STACK_SIZE symbols:

#if defined(__ICCARM__)
#pragma section="CSTACK"
#pragma section="HEAP"
#define HEAP_START ((unsigned char*)__section_begin("HEAP"))
#define HEAP_SIZE ((uint32_t)__section_size("HEAP"))
#define ISR_STACK_START ((unsigned char*)__section_begin("CSTACK"))
#define ISR_STACK_SIZE ((uint32_t)__section_size("CSTACK"))
#endif

#ifdef ISR_STACK_START
/* Interrupt stack explicitly specified */
mbed_stack_isr_size = ISR_STACK_SIZE;
mbed_stack_isr_start = ISR_STACK_START;
#else
/* Interrupt stack - reserve space at the end of the free block */
mbed_stack_isr_size = ISR_STACK_SIZE < free_size ? ISR_STACK_SIZE : free_size;
mbed_stack_isr_start = free_start + free_size - mbed_stack_isr_size;
free_size -= mbed_stack_isr_size;
#endif

For example STM boards defines ISR_STACK_SIZE as follows (GCC_ARM):

#define ISR_STACK_SIZE ((uint32_t)((uint32_t)__StackTop - (uint32_t)__StackLimit))

Now for specific TARGET_STM32L476xG family we have the following definitions:
IAR

define symbol __size_cstack__ = 0x7e00;
define symbol __size_heap__ = 0x10000;
define block CSTACK with alignment = 8, size = __size_cstack__ { };
define block HEAP with alignment = 8, size = __size_heap__ { };

GCC_ARM
/* Set stack top to end of RAM, and stack limit move down by
* size of stack_dummy section */
__StackTop = ORIGIN(SRAM2) + LENGTH(SRAM2);
_estack = __StackTop;
__StackLimit = __StackTop - SIZEOF(.stack_dummy);
PROVIDE(__stack = __StackTop);
/* Check if stack exceeds RAM2 limit */
ASSERT((ORIGIN(SRAM2)+LENGTH(SRAM2)) >= __StackLimit, "SRAM2 overflow")

ARM
Not defined

According to the requirements I'm going to modify ISR stack for all targets to 1 kB. At least for GCC and IAR. I can't see how ISR stack size is defined for ARM compiler.
As far as I understand you suggest to set ISR stack size to ~0,5 kB?

@deepikabhavnani
Copy link

According to the requirements I'm going to modify ISR stack for all targets to 1 kB

Why set it to 1KB only? Some devices might need higher ISR stack can we have some good range instead?

@deepikabhavnani
Copy link

ARM Not defined

Below files show where ISR stack is set for ARM. Look for what is set in ISR_STACK_START for all targets. Many of them use same define "ARM_LIB_STACK" in scatter files

#define ISR_STACK_START ((unsigned char*)Image$$ARM_LIB_STACK$$ZI$$Base)

@SeppoTakalo
Copy link
Contributor

@mprse

As far as I understand you suggest to set ISR stack size to ~0,5 kB?

No, this was based on my original understanding that boot time stack/main stack and ISR stacks are different.

But according to Cortex-M3 User Guide Reference Material: 2.1.2. Stacks
In Thread mode, the CONTROL register controls whether the processor uses the main stack or the process stack, see CONTROL register. In Handler mode, the processor always uses the main stack.

So clearly "boot" stack and ISR stacks are the same. And I tried to find, where we set that pointer, but it seems to be the first vector, so its the linker file + startup_*.S

According the Cortex-M3 Devices Generic User Guide: Stack Pointer

The Stack Pointer (SP) is register R13. In Thread mode, bit[1] of the CONTROL register indicates the stack pointer to use:
0 = Main Stack Pointer (MSP). This is the reset value.
1 = Process Stack Pointer (PSP).
On reset, the processor loads the MSP with the value from address 0x00000000.

So I was wrong assuming that checking ISR stack would not be enough, but those are the same.

Should we actually change the name, because my understanding is now that both RTX kernel and ISR both use this "main stack" where MSP register points, and each thread have their own stack where PSP points?

And @deepikabhavnani why would some devices need 4kB of ISR stack? Sound like a lot compared to RTX kernel requiring only 400 bytes. Do you know some examples?

At least within Mbed OS it is very limited what you can do in ISR, so the call path would be usually very short.

@@ -40,7 +40,7 @@ export symbol __ICFEDIT_region_RAM_end__;

/*-Sizes-*/
/*Heap 1/4 of ram and stack 1/8*/
define symbol __ICFEDIT_size_cstack__ = 0x800;
Copy link
Member

Choose a reason for hiding this comment

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

That would break BLE.

@@ -11,8 +11,8 @@ define symbol __ICFEDIT_region_RAM_end__ = 0x20007FFF;
export symbol __ICFEDIT_region_RAM_start__;
export symbol __ICFEDIT_region_RAM_end__;
/*-Sizes-*/
/*Heap 1/4 of ram and stack 1/8*/
define symbol __ICFEDIT_size_cstack__ = 0x800;
Copy link
Member

Choose a reason for hiding this comment

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

That would break BLE.

Copy link
Member

@pan- pan- left a comment

Choose a reason for hiding this comment

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

IRQ Stack must be at least 2K large on Nordic targets. This is not an option to change it.

@deepikabhavnani
Copy link

And @deepikabhavnani why would some devices need 4kB of ISR stack

I never meant 4KB stack size as requirement. I would suggest to have a range based on analysis / input from target devices instead of hard-code 1KB.

@mprse
Copy link
Contributor Author

mprse commented Jun 21, 2018

Thanks for all your comments. They are really helpful!

Should we actually change the name, because my understanding is now that both RTX kernel and ISR both use this "main stack" where MSP register points, and each thread have their own stack where PSP points?

I agree that the name ("Interrupt stack") is misleading and it would be better to be consistent with the documentation and use names "main stack" (interrupt and boot time stack) and "process stack" (threads).

I never meant 4KB stack size as requirement. I would suggest to have a range based on analysis / input from target devices instead of hard-code 1KB.

I also agree that setting main stack/isr stack size to 1 KB for all boards might not be a good solution. For many cases it should be ok, but for sure there are cases when it is impossible (like BLE support on NRF boards pointed by @pan).

I found the following problematic cases:

  • Renesas targets are based on Cortex-A and stack is organised in the different way. We have different exception modes like Undefined instruction, Supervisor call, Abort, IRQ, FIQ and for each of them separate stack is used. Total stack size is defined as a sum of all these stacks which gives 92 KB.

ARM_LIB_STACK (__RAM_BASE + __NM_RAM_SIZE) EMPTY -__STACK_SIZE ; Stack region growing down

#define __UND_STACK_SIZE 0x00000100
#define __SVC_STACK_SIZE 0x00008000
#define __ABT_STACK_SIZE 0x00000100
#define __FIQ_STACK_SIZE 0x00000100
#define __IRQ_STACK_SIZE 0x0000F000
#define __STACK_SIZE (__UND_STACK_SIZE + __SVC_STACK_SIZE + __ABT_STACK_SIZE + __FIQ_STACK_SIZE + __IRQ_STACK_SIZE)

//Enter Undefined Instruction Mode and set its Stack Pointer
CPS #UND_MODE
MOV SP, R0
SUB R0, R0, #__UND_STACK_SIZE
// Enter Abort Mode and set its Stack Pointer
CPS #ABT_MODE
MOV SP, R0
SUB R0, R0, #__ABT_STACK_SIZE
// Enter FIQ Mode and set its Stack Pointer
CPS #FIQ_MODE
MOV SP, R0
SUB R0, R0, #__FIQ_STACK_SIZE
// Enter IRQ Mode and set its Stack Pointer
CPS #IRQ_MODE
MOV SP, R0
SUB R0, R0, #__IRQ_STACK_SIZE
// Enter Supervisor Mode and set its Stack Pointer
CPS #SVC_MODE
MOV SP, R0
SUB R0, R0, #__SVC_STACK_SIZE

  • On some boards with very small amount of RAM the main stack/isr stack size is currently less than 1 KB.
    TARGET_KL05Z: main stack/isr stack size is set to 512 B. This board has only 4 KB RAM.

/*Heap 1/4 of ram and stack 1/8*/
define symbol __ICFEDIT_size_cstack__ = 0x200;
define symbol __ICFEDIT_size_heap__ = 0x400;
/**** End of ICF editor section. ###ICF###*/

TARGET_NCS36510: main stack/isr stack size is set to 512 B. This board has 48 KB RAM.

/*-Sizes-*/
define symbol __ICFEDIT_size_cstack__ = 0x200;
define symbol __ICFEDIT_size_heap__ = 0x4000;

TARGET_LPC810: main stack/isr stack size is set to 256 B. This micro-controller has only 4 KB RAM.

/*-Sizes-*/
define symbol __ICFEDIT_size_cstack__ = 0x100;
define symbol __ICFEDIT_size_heap__ = 0x200;

I'm not sure if increasing main stack/isr stack size for boards which have only 4KB or 8KB RAM is possible.

@bulislaw I think we should consider changing the requirement. I still did not checked all targets, but it looks like I can not simply unify main stack/isr stack size to 1KB for all targets. At least some exceptions are needed.

@bulislaw
Copy link
Member

bulislaw commented Jun 21, 2018

Yeah that's fair, NRF is special case due to the SoftDevices. TARGET_LPC810 and TARGET_KL05Z is not supported in mbed 5. We may also make an exception for Cortex A platform, but we need to document it well (your comment above gives nice explanation).

@mprse mprse dismissed stale reviews from SeppoTakalo and bulislaw via 93a141b June 22, 2018 09:16
@mprse mprse force-pushed the stack_unification branch from 9ccd700 to 93a141b Compare June 22, 2018 09:16
@mprse mprse force-pushed the stack_unification branch 3 times, most recently from d9eba95 to a119085 Compare June 26, 2018 11:21
@mprse
Copy link
Contributor Author

mprse commented Jun 26, 2018

@pan Can you check if current form is acceptable for NORDIC target?

mprse added 3 commits August 28, 2018 09:16
Unify ISR stack size for targets which support MBED 5 (or MBED 2 and MBED 5).

 MBED 5 : 3 boards
----------------
TMPM3H6
TMPM46B
TMPM066
 MBED 2, 5 : 0 boards
----------------
 MBED 2 : 0 boards (skipped)
----------------
Unify ISR stack size for targets which support MBED 5 (or MBED 2 and MBED 5).

 MBED 5 : 0 boards
----------------

 MBED 2, 5 : 3 boards
----------------
WIZWIKI_W7500ECO
WIZWIKI_W7500P
WIZWIKI_W7500

 MBED 2 : 0 boards (skipped)
----------------
Unify ISR stack size for targets which support MBED 5 (or MBED 2 and MBED 5).
@mprse mprse force-pushed the stack_unification branch from 7cfa089 to 22399bb Compare August 28, 2018 07:18
@mprse
Copy link
Contributor Author

mprse commented Aug 28, 2018

Rebased.

The following Mbed 5 boards were processed:
NUCLEO_F091RC
NUCLEO_F070RB
NUCLEO_F072RB

NUCLEO_F103RB

NUCLEO_F207ZG

DISCO_F303VC
NUCLEO_F303ZE
NUCLEO_F303RE

--- only boards marked with "-" of NUCLEO_F3 family were processed
UBLOX_C030_U201
MTB_UBLOX_ODIN_W2
MTB_MXCHIP_EMW3166
MBED_CONNECT_ODIN
UBLOX_C030_N211
UBLOX_EVK_ODIN_W2
USI_WM_BN_BM_22
UBLOX_C030_R410M
NUCLEO_F411RE
NUCLEO_F413ZH
DISCO_F407VG
- NUCLEO_F401RE
NUCLEO_F429ZI
B96B_F446VE
DISCO_F413ZH
NUCLEO_F439ZI
DISCO_F429ZI
- MTS_DRAGONFLY_F411RE
NUCLEO_F446ZE
DISCO_F469NI
NUCLEO_F446RE
NUCLEO_F410RB
MTS_MDOT_F411RE
WIO_3G
STEVAL_3DP001V1
- MTB_MTS_DRAGONFLY
NUCLEO_F412ZG
@jeromecoutant
Copy link
Collaborator

Hi

Maybe we can push a little bit this PR as more and more PR on the same topic comes ?
#8225 #8252 #7909 #7289 ...

Thx

@jeromecoutant
Copy link
Collaborator

Maybe should we implement proposition from #8252:

if (!isdefinedsymbol(MBED_APP_HEAP_SIZE)) {
define symbol size_heap = ;
} else {
define symbol size_heap = MBED_APP_HEAP_SIZE;
}

@mprse
Copy link
Contributor Author

mprse commented Sep 26, 2018

I will have to mainly review all files again when framework for configuring boot stack size will go in (PR #8039).

deepikabhavnani pushed a commit to c1728p9/mbed-os that referenced this pull request Oct 5, 2018
Set the ISR stack to be 1KB. ARMmbed#7238
Set the heap size to 3KB(2KB + overhead + spare) so that atleast 2KB free ram is
available for testing.
With dynamic heap size, explicit size is not required. IAR 7.8 supports
static heap, hence the change is needed in IAR linker files.
@cmonr
Copy link
Contributor

cmonr commented Oct 18, 2018

@mprse Is this still in progress? #8039 has since been merged

adbridge pushed a commit that referenced this pull request Oct 19, 2018
Set the ISR stack to be 1KB. #7238
Set the heap size to 3KB(2KB + overhead + spare) so that atleast 2KB free ram is
available for testing.
With dynamic heap size, explicit size is not required. IAR 7.8 supports
static heap, hence the change is needed in IAR linker files.
@SeppoTakalo SeppoTakalo mentioned this pull request Oct 23, 2018
@0xc0170
Copy link
Contributor

0xc0170 commented Oct 25, 2018

@mprse Let us know the status. We shall close it and reopen with an update? Or is there expecting completion anytime soon?

@mprse
Copy link
Contributor Author

mprse commented Oct 25, 2018

@mprse Let us know the status. We shall close it and reopen with an update? Or is there expecting completion anytime soon?

I'm planning to continue this one when I'm done with SPI testing. Since we have new Framework added by @c1728p9 (PR #8039) I will have to go through all linker scripts again, so I think we should close this one and I'll open new one instead later.

@0xc0170
Copy link
Contributor

0xc0170 commented Oct 25, 2018

Sounds good to me (reference this previous work if needed any history). I'll close this one

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.