Using Scheduler Library

The official STMicroelectronics Arduino core
Post Reply
User avatar
Rick Kimball
Posts: 1038
Joined: Tue Apr 28, 2015 1:26 am
Location: Eastern NC, US
Contact:

Using Scheduler Library

Post by Rick Kimball » Sat Jun 24, 2017 3:50 pm

The Scheduler Library by Arduino can be installed using the Library Manager. Its purpose is to allow multiple tasks to run at the same time without interrupting each other. The code is specific to the cortex-m0 and cortex-m3 chips. However, the code only checks to see if you are using the ATMEL sam or samd architecture. The sam is a cortex-m3 and the samd is a cortex-m0.

You can make this library work with the stm32f0 chips with a few simple changes. Below I explain the changes to the scheduler code to support the F030R8 and F091R8 boards. You need to change 2 files:

Code: Select all

$ pwd
~/Arduino/libraries/Scheduler
change Scheduler/library.properties and add the stm32 architecture:

Code: Select all

$ grep -i SAMD library.properties 
sentence=Allows multiple tasks to run at the same time, without interrupting each other. For Arduino sam and samd architectures only (Due, Zero...).
library.properties:architectures=sam,samd,stm32
change Scheduler/src/Scheduler.cpp and add a more generic way to check for the type of arm chip:
...

Code: Select all

$ grep -i SAMD src/Scheduler.cpp 
#if defined(ARDUINO_ARCH_SAMD) || (defined(__CORTEX_M) && __CORTEX_M == 0)
#if defined(ARDUINO_ARCH_SAMD) || (defined(__CORTEX_M) && __CORTEX_M == 0)
#if defined(ARDUINO_ARCH_SAMD) || (defined(__CORTEX_M) && __CORTEX_M == 0)
The gcc created define "__CORTEX_M" is controlled by the -mcpu command line argument. It will contain 0 for a cortex-m0 and 3 for a cortex-m3.

The scheduler is a co-operative multitasking scheduler. This approach relies on the user to give up control as opposed to more complex preemptive scheduling. The examples and Arduino web page explain it more detail. https://www.arduino.cc/en/Reference/Scheduler


Note: Once the STM Core supports the STM32F1 series, the Scheduler code will probably work without changes, The only thing you might want to change is the library.properties file to add the stm32 architecture.
Last edited by Rick Kimball on Sun Jun 25, 2017 12:18 pm, edited 4 times in total.
-rick

fpiSTM
Posts: 224
Joined: Fri Sep 16, 2016 12:33 pm
Location: Le Mans, France

Re: Using Scheduler Library

Post by fpiSTM » Sat Jun 24, 2017 5:30 pm

Thanks Rick,

I have planned to do this soon:)
probably adding ARDUINO_ARCH_STM32 should be sufficient.

User avatar
RogerClark
Posts: 7148
Joined: Mon Apr 27, 2015 10:36 am
Location: Melbourne, Australia
Contact:

Re: Using Scheduler Library

Post by RogerClark » Sat Jun 24, 2017 11:10 pm

I suppose we could download it and include it as part of LibMaple

I am not sure what Frederic wants to do, we could try to ask Arduino to change the properties to include STM32, but I dont have any leverage in this respect

fpiSTM
Posts: 224
Joined: Fri Sep 16, 2016 12:33 pm
Location: Le Mans, France

Re: Using Scheduler Library

Post by fpiSTM » Sun Jun 25, 2017 8:21 am

Right Roger,
As far as possible, I will make pull request to the Arduino libraries to add the support of STM32.
ARDUINO_ARCH_STM32 is enough generic to be compatible with several STM32 cores

stevestrong
Posts: 1744
Joined: Mon Oct 19, 2015 12:06 am
Location: Munich, Germany

Re: Using Scheduler Library

Post by stevestrong » Sun Jun 25, 2017 8:38 am

RogerClark wrote:
Sat Jun 24, 2017 11:10 pm
I suppose we could download it and include it as part of LibMaple
+1

danieleff
Posts: 336
Joined: Thu Sep 01, 2016 8:52 pm
Location: Hungary
Contact:

Re: Using Scheduler Library

Post by danieleff » Sun Jun 25, 2017 9:25 am

Scheduler already works with libmaple (and all STM32 cores) as is.

Rick's point is only for Cortex M0 chips that need different code path.

User avatar
RogerClark
Posts: 7148
Joined: Mon Apr 27, 2015 10:36 am
Location: Melbourne, Australia
Contact:

Re: Using Scheduler Library

Post by RogerClark » Sun Jun 25, 2017 10:22 am

danieleff wrote:
Sun Jun 25, 2017 9:25 am
Scheduler already works with libmaple (and all STM32 cores) as is.

Rick's point is only for Cortex M0 chips that need different code path.
Umm.

Rick wrote
You can make this library work with the stm32 chips with a few simple changes.
I did not check if it worked already, as it seemed Rick was saying some changes were needed (hence perhaps it would not work without changes)

User avatar
Rick Kimball
Posts: 1038
Joined: Tue Apr 28, 2015 1:26 am
Location: Eastern NC, US
Contact:

Re: Using Scheduler Library

Post by Rick Kimball » Sun Jun 25, 2017 11:54 am

Yes, for libmaple and the stm32 f1 chips you can get away without changing anything because the code is written for the cortex-m3. However, the Arduino IDE will still whine telling you the architecture is not supported, as it only names sam and samd as valid architectures.

The Scheduler library code assumes you are using a cortex-m3 and only makes accommodations for the ATMEL SAMD cortex-m0 chips. However, anywhere the SAMD is mentioned means it is also needed by the STM32F0 series.

An example of that like this:

Code: Select all

...
static void __attribute__((naked)) __attribute__((noinline)) coopTaskStart(void) {
    asm (
        "mov   r0, r5;"
        "blx   r4;"
        /* schedule. */
        "mov   r0, #1;"      /* returned from task func: task done */
        "bl    coopSchedule;"
        /* r0 holds address of next task context */
#if defined(ARDUINO_ARCH_SAMD) || (defined(__CORTEX_M) && __CORTEX_M == 0)
        "mov   r8, r1;"      /* ...and move them into high registers... */
        "mov   r9, r2;"
        "mov   r10, r3;"
        "mov   r11, r4;"
        "mov   r12, r5;"
        "mov   lr, r6;"
        /* load low registers */
        "sub   r0, r0, #40;" /* back to begin of context */
        "ldmia r0, {r4-r7};"
#else
        "ldmia r0, {r4-r12, lr};"
#endif
        /* restore task stack */
        "mov   sp, r12;"
        /* resume task */
        "bx    lr;"
    );
}

...
In the code above, cortex-m0 chips have to deal with the upper registers differently than the lower ones. Because of the subset of supported instructions available in the ARMv6-M architecture.

I'm not sure if the code as written is enough to support a cortex-m4 chip that has hardware floating point enabled. You might have to push and pop those registers too. I haven't dug in as I don't have any stm32 f4 supported boards. This is why I didn't make a blanket statement about the changes supporting all the STM chips. The real point of my posting is show the minor things you have to change to make it work with the STM32F0 boards and the STM32 Core.
-rick

User avatar
Rick Kimball
Posts: 1038
Joined: Tue Apr 28, 2015 1:26 am
Location: Eastern NC, US
Contact:

Re: Using Scheduler Library

Post by Rick Kimball » Sun Jun 25, 2017 12:15 pm

RogerClark wrote:
Sun Jun 25, 2017 10:22 am
Umm.

Rick wrote
You can make this library work with the stm32 chips with a few simple changes.
I did not check if it worked already, as it seemed Rick was saying some changes were needed (hence perhaps it would not work without changes)
I modified my first posting to make it more clear I'm only talking about the STM32F0 chips and the STM Core.
Last edited by Rick Kimball on Sun Jun 25, 2017 1:27 pm, edited 1 time in total.
-rick

User avatar
Rick Kimball
Posts: 1038
Joined: Tue Apr 28, 2015 1:26 am
Location: Eastern NC, US
Contact:

Re: Using Scheduler Library

Post by Rick Kimball » Sun Jun 25, 2017 1:01 pm

Rick Kimball wrote:
Sun Jun 25, 2017 11:54 am
...
I'm not sure if the code as written is enough to support a cortex-m4 chip that has hardware floating point enabled. You might have to push and pop those registers too. I haven't dug in as I don't have any stm32 f4 supported boards.
...
Looking at some FreeRTOS code it seems to make provisions for the cortex-m4. From here:
https://mcuoneclipse.com/2016/08/28/arm ... os-part-3/

Code: Select all

__attribute__ ((naked)) void vPortSVCHandler(void) {
#if configCPU_FAMILY_IS_ARM_M4_M7(configCPU_FAMILY)  /* Cortex M4 or M7 */
__asm volatile (
    " ldr r3, pxCurrentTCBConst2 \n" /* Restore the context. */
    " ldr r1, [r3]               \n" /* Use pxCurrentTCBConst to get the pxCurrentTCB address. */
    " ldr r0, [r1]               \n" /* The first item in pxCurrentTCB is the task top of stack. */
    /* pop the core registers */
#if configCPU_FAMILY_IS_ARM_FPU(configCPU_FAMILY)
    " ldmia r0!, {r4-r11, r14}   \n"
#else
    " ldmia r0!, {r4-r11}        \n"
#endif
    " msr psp, r0                \n"
    " mov r0, #0                 \n"
    " msr basepri, r0            \n"
#if configCPU_FAMILY_IS_ARM_FPU(configCPU_FAMILY)
#else
    " orr r14, r14, #13          \n"
#endif
    " bx r14                     \n"
    "                            \n"
    " .align 2                   \n"
    "pxCurrentTCBConst2: .word pxCurrentTCB \n"
  );
#elif configCPU_FAMILY_IS_ARM_M0(configCPU_FAMILY) /* Cortex M0+ */
  /* This function is no longer used, but retained for backward
  compatibility. */
#endif
Specifically check of the configCPU_FAMILY_IS_ARM_FPU(configCPU_FAMILY), they push and pop "r14" on the stack.

And more details here:
https://github.com/jameswalmsley/FreeRT ... ort.c#L459
they are using the LR (aka R14) to see if they need to push / pop the floating point registers {s16-s31}

Code: Select all

	__asm volatile
	(
	"	mrs r0, psp							\n"
	"	isb									\n"
	"										\n"
	"	ldr	r3, pxCurrentTCBConst			\n" /* Get the location of the current TCB. */
	"	ldr	r2, [r3]						\n"
	"										\n"
	"	tst r14, #0x10						\n" /* Is the task using the FPU context?  If so, push high vfp registers. */
	"	it eq								\n"
	"	vstmdbeq r0!, {s16-s31}				\n"
	"										\n"
	"	stmdb r0!, {r4-r11, r14}			\n" /* Save the core registers. */
	"										\n"
	"	str r0, [r2]						\n" /* Save the new top of stack into the first member of the TCB. */
So it seems likely you would have to make some other changes to the Scheduler library depending on the m4 configuration.
-rick

Post Reply