CMSIS-RTOS for Mecrisp-Cube
Intro

Why a Preemptive Real Time Operating System?

Forth systems traditionally make use of cooperative multitasking. It is very simple and clever. But it has its limits. If you write all your software by yourself, each software part can be cooperative. But if you want to benefit from middleware written by somebody else (and most probably not written in Forth), you can be sure that software is not cooperative (in the context of multitasking). Forth wants to rule your system. I would like to have a Forth system that is cooperative. It should extend the system, to make it interactive and easy to use. The Forth itself is only a thread and can be used as some sort of CLI for testing purposes or could be the main part of the application.

How to Create a Thread

A very simple thread could be like this one, a boring blinker:

: blink-thread  ( -- )
  begin 
    led1@ 0= led1!   \ toggle blue LED
    200 osDelay drop  \ wait 200 ms
    switch1? 
  until 
  0 led1! 
;

If you type the word blink-thread, the blue LED blinks, after push the button SW1, the blinking stops an the ok. apears. But if you try to start the thread with

' blink-thread 0 0 osThreadNew
Nothing happens and probably the Forth system hangs. Restart the Forth system with the Reset button SW4.

If you create a new RTOS Thread, CMSIS-RTOS (FreeRTOS) allocate some memory from the heap for the stack and the thread control block. But Forth thread needs another stack, the data stack. The blink-thread runs concurrent to the Forth interpreter and use the same data stack. This cannot work. Each thread must have its own data stack, the thread function can get one with osNewDataStack (see below for the assembler source).

: blink-thread  ( -- )
  osNewDataStack
  begin 
    led1@ 0= led1!   \ toggle blue LED
    200 osDelay drop  
    switch1? 
  until 
  0 led1! 
  osThreadExit
;

osThreadExit is needed to exit the thread, otherwise the Forth system hangs after leaving the thread. These threads are very similar to the control tasks described in Starting Forth, Leo Brodie. But without user variables. If a thread wants to use variables and share these variables with other threads, the variables have to be protected by a mutex or a semaphore. Anyway variables have to be created by the main Forth thread (terminal task) before.

Now you can interactively play with the words osThreadGetId, osThreadGetState, osThreadSuspend, and osThreadResume without the tedious edit-compile-download-run-abort.

// -----------------------------------------------------------------------------
		Wortbirne Flag_visible, "osNewDataStack"
		@ (  --  ) Creates an new data stack for a Forth thread.
// -----------------------------------------------------------------------------
rtos_osNewDataStack:
	push	{r0-r3, lr}
	ldr	r0, =256	// 64 levels should be more than enough
	bl	pvPortMalloc
	adds	r7, r0, #256	// stack grows down
	movs	tos, 42
	pop	{r0-r3, pc}

CMSIS-RTOS API

The C function prototype for osThreadNew looks like this:

osThreadId_t osThreadNew (osThreadFunc_t func, void *argument, const osThreadAttr_t *attr);

param[in]     func          thread function.
param[in]     argument      pointer that is passed to the thread function as start argument.
param[in]     attr          thread attributes; NULL: default values.

return        thread ID for reference by other functions or NULL in case of error.

The parameter order for the Forth Word is the same: a1 is func, a2 is argument, and a3 is attr.

osThreadNew  ( a1 a2 a3 -- u )   Create a thread and add it to Active Threads.

See also osThreadNew

RTOS Support Functions

  • osNewDataStack
  • xPortGetFreeHeapSize

Kernel Management Functions

Kernel Information and Control
  • osKernelGetTickCount
  • osKernelGetTickFreq
  • osKernelGetSysTimerCount
  • osKernelGetSysTimerFreq

Generic Wait Functions

Generic Wait Functions
  • osDelay
  • osDelayUntil

Thread Management

Thread Management
  • osThreadNew
  • osThreadGetId
  • osThreadGetState
  • osThreadSetPriority
  • osThreadGetPriority
  • osThreadYield
  • osThreadSuspend
  • osThreadResume
  • osThreadExit
  • osThreadTerminate
  • osThreadGetStackSpace
  • osThreadGetCount
  • osThreadEnumerate

Timer Management Functions

Timer Management
  • osTimerNew
  • osTimerGetName
  • osTimerStart
  • osTimerStop
  • osTimerIsRunning
  • osTimerDelete

Event Flags Management Functions

Event Flags
  • osEventFlagsNew
  • osEventFlagsSet
  • osEventFlagsClear
  • osEventFlagsGet
  • osEventFlagsWait
  • osEventFlagsDelete

Mutex Management Functions

Mutex Management
  • osMutexNew
  • osMutexAcquire
  • osMutexRelease
  • osMutexGetOwner
  • osMutexDelete

Semaphore Management Functions

Semaphores
  • osSemaphoreNew
  • osSemaphoreAcquire
  • osSemaphoreRelease
  • osSemaphoreGetCount
  • osSemaphoreDelete

Message Queue Management Functions

Message Queue
  • osMessageQueueNew
  • osMessageQueuePut
  • osMessageQueueGet
  • osMessageQueueGetCapacity
  • osMessageQueueGetMsgSize
  • osMessageQueueGetCount
  • osMessageQueueGetSpace
  • osMessageQueueReset
  • osMessageQueueDelete

A multi-tasking wordset for Standard Forth, Andrew Haley http://www.complang.tuwien.ac.at/anton/euroforth/ef17/papers/haley-slides.pdf

-- Peter Schmid - 2020-04-07

Comments

Edit | Attach | Watch | Print version | History: r60 | r8 < r7 < r6 < r5 | Backlinks | Raw View | Raw edit | More topic actions...
Topic revision: r6 - 2020-04-20 - PeterSchmid
 
  • Edit
  • Attach
This site is powered by the TWiki collaboration platform Powered by PerlCopyright © 2008-2024 by the contributing authors. All material on this collaboration platform is the property of the contributing authors.
Ideas, requests, problems regarding TWiki? Send feedback