ChibiOS/RT RTOS for Teensy 4.0.

Bill Greiman

Well-known member
I have updated the ChRt library to release 19.1.3 of ChibiOS and added support for Teensy 4.0.

Release 19.1.3 is about two years newer than the version I used in the last update of ChRt. There are many new features and improvements.

Giovanni Di Sirio is the author of ChibiOS. Giovanni has excellent understanding of RTOS theory and algorithms. He also has more than 25 years of practical experience working with RTOS applications.

Teensy 4.0 does a context switch in about 200 ns with this version of ChibiOS.

Teensy 4.0 is supported in both periodic and tick-less mode. Tick-less mode is great since there is little interrupt overhead. ChibiOS has a true tick-less mode. Other RTOSs like FreeRTOS only have a tick-less idle mode when no tasks are run-able.

See this article about ChibiOS tick-less mode.

I have run the system timer as fast as one MHz and it works with no extra overhead. chThdSleepUntil() then has a resolution of one microsecond.

Teensy 4.0 is a great match for ChibiOS. The GPT timer exactly fits the ChibiOS requirement. Most functions are a single line of code. Here are the low level timer functions for ChibiOS.

Code:
/**
 * @brief   Returns the time counter value.
 *
 * @return              The counter value.
 *
 * @notapi
 */
static inline systime_t st_lld_get_counter(void) {
  return (systime_t)GPT2_CNT;
}

/**
 * @brief   Starts the alarm.
 * @note    Makes sure that no spurious alarms are triggered after
 *          this call.
 *
 * @param[in] time      the time to be set for the first alarm
 *
 * @notapi
 */
static inline void st_lld_start_alarm(systime_t time) {
  GPT2_OCR1 = (uint32_t)time;
  GPT2_SR |= GPT_SR_OF1; 
  GPT2_IR = GPT_IR_OF1IE;
}

/**
 * @brief   Stops the alarm interrupt.
 *
 * @notapi
 */
static inline void st_lld_stop_alarm(void) {
  GPT2_IR = 0;
}

/**
 * @brief   Sets the alarm time.
 *
 * @param[in] time      the time to be set for the next alarm
 *
 * @notapi
 */
static inline void st_lld_set_alarm(systime_t time) {
  GPT2_OCR1 = (uint32_t)time;
}

/**
 * @brief   Returns the current alarm time.
 *
 * @return              The currently set alarm time.
 *
 * @notapi
 */
static inline systime_t st_lld_get_alarm(void) {
  return (systime_t)GPT2_OCR1;
}

/**
 * @brief   Determines if the alarm is active.
 *
 * @return              The alarm status.
 * @retval false        if the alarm is not active.
 * @retval true         is the alarm is active
 *
 * @notapi
 */
static inline bool st_lld_is_alarm_active(void) {
  return (GPT2_IR & GPT_SR_OF1) != 0;
}
 
@Bill G
Fantastic that you got this working. I was beginning to look at the Amazon RTOS that the NXP SDK uses but put that on the side for now since it would be a learning curve for me to get working.

Tickless mode will come in handy when you put the T4 to extreme sleep.

Thanks
Mike
 
@Bill G

Starting looking at giving this is a try now and start playing with it. Think I get the basics. There is one question though - if I want to use one of the Teensy or Arduino libraries can I do that the same way I would normally do it within a sketch or is there something else I have to do?
 
@Bill G

Starting looking at giving this is a try now and start playing with it. Think I get the basics. There is one question though - if I want to use one of the Teensy or Arduino libraries can I do that the same way I would normally do it within a sketch or is there something else I have to do?

Generally you can use libraries in the usual way. There can be problems since libraries were not written for a multi-threaded environment.

Here are some of the problems I have seen.

You must protect access to shared devices with a mutex or semaphore. calling print from several thread results in scrambled data.

For most Arduino systems use of dynamic memory is a problem. malloc()/free() are not re-entrant so use in two threads can scramble the heap. The String class is a key offender.

malloc() on most Arduino systems assumes the stack is above the heap and fails for threads. Teensy 4.0 has a separate heap so this may not be a problem.

ChibiOS has a heap allocator but that won't fix libraries.

Another problem is that libraries sometimes call delay() or delayMicroseconds(). This will block lower priority threads.

You must use the volatile qualifier for any shared variables and protect shared access with a mutex or semaphore.

There are the standard problems of writing multi-thread systems like priority inversion.

The ChibiOS site has excellent documentation and articles:

http://chibios.org/dokuwiki/doku.php?id=chibios:documentation:start

http://chibios.org/dokuwiki/doku.php?id=chibios:articles:start
 
Last edited:
@Bill G

Thanks for the info some of the multi-thread problems I recognize from using TeensyThreads.

Primarily the libraries I am talking about are things like PWMServo, NewPing, MPU-9250 etc. Sensor libs primarily. Unfortunately probably most of them use delay which I would have to address.
 
Hi Bill,

I'm using a Teensy version 3.5 and the ChRt library (current release). In my project, I also use the SDFat library (SdFat-beta). I have noticed that in this last library the millis() and delay() function are used:

Code:
/** \return the time in milliseconds. */
inline SdMillis_t SysCall::curTimeMS() {
  return millis();
}

Code:
DBG_TRACE Serial.print("TRACE."); Serial.println(__LINE__); delay(200);

They are not invoked in my code. I would like to ask you if both libraries are compatible and if you have had problems using ChibiOS with the libraries: Snooze and TimeAlarms

Thanks.
 
Last edited:
Back
Top