Category Archives: Firmware

COFILOS SD Card Driver

SD Card Driver Development on COFILOS

Last year I completed a major milestone for COFILOS and the Perseus board. I completed a fully TDD written SD Card Driver.

You may check the following video: COFILOS SD Card

I was a big pain to write it, even though I had guide code from the internet and enough relevant information. The outcome is a very readable and organized code.

The initialization phase is very complex (and took the lion’s share of time to implement) is shown here:



/*!
* \brief Device Start (Stub)
* @param pstDriver_ : Pointer to Device structure
* @return 0 (SUCCESS), 1: Fail (Could not open SPI driver)
*/
BOOL f_DriverSD_Start(void *pstDriver_ )
{
type_stDRIVERSD *pst_SD;
INT8U v_error;
INT8U v_PhysDevID;
BOOL v_retval;

pst_SD = (type_stDRIVERSD *) pstDriver_;

if (pst_SD->stDriver.eState != DRIVER_CLOSE) return 1;
if (pst_SD->f_HAL_HookCardPresent == NULL) return 1;
if (pst_SD->f_HAL_HookCardPresent() == 0) return 255;

v_retval = 1; /* default is failure */

f_DriverSDHelper_InitSPI(pst_SD);

f_DriverCoFILOS_Open((PINT8) "SPI.Driver", 0xFF, (DRIVER_STRUCT *) &pst_SD->st_SPI);

Driver_Start((DRIVER_STRUCT *) &pst_SD->st_SPI);

/* Acquire Mutex, we need uninterrupted SPI access */
Driver_Control((DRIVER_STRUCT *) &pst_SD->st_SPI, CMD_SET_SPIMUTEX_ON, NULL);

f_DriverSDHelper_ResetSD(pst_SD);

/* set default value for Unknown Card Type */
/* Assuming initially that all is good */
v_PhysDevID = pst_SD->v_PhyVolumeID;
st_SDPhysical[v_PhysDevID].v_UnknownCard = eSDUn_None;
pst_SD->v_CardType = eSDCardUnknown;

/* set CS, clocked */
f_DriverSDHelper_SelectDevice(pst_SD);

v_error = f_DriverSDHelper_SendCMD0(pst_SD);
if (v_error == 0xFE)
{
  /* Unknown Card */
  /* TODO: Unknown Card */
  f_DriverSDHelper_UnknownDevice(pst_SD->v_PhyVolumeID, eSDUn_CMD0);
}
else
{
  v_error = f_DriverSDHelper_SendCMD8(pst_SD);

  if (v_error == 0) /* SDV2 Byte or Block */
  {
    v_error = f_DriverSDHelper_SendACMD41(pst_SD, 0x40000000);
    v_error = f_DriverSDHelper_SendCMD58(pst_SD);

    if (pst_SD->v_CardType == eSDCardSDv2Byte)
    {
      v_error = f_DriverSDHelper_SendCMD16(pst_SD);
      st_SDPhysical[v_PhysDevID].v_CardType = eSDCardSDv2Byte;
    }
    else
    {
      st_SDPhysical[v_PhysDevID].v_CardType = eSDCardSDv2Block;
    }
  }
  else if (v_error == 0xFE) /* SDv1 or MMCv3 or Unknown ? */
 {
   st_SDPhysical[v_PhysDevID].v_CardType = eSDCardSDv1;
   v_error = f_DriverSDHelper_SendACMD41(pst_SD, 0x00000000);
   if (v_error != 0)
   {
     /* MMCv3 ? */
     v_error = f_DriverSDHelper_SendCMD1(pst_SD);
     if (v_error == 0)
    {
      st_SDPhysical[v_PhysDevID].v_CardType = eSDCardMMCv3;
    }
    else
    {
      f_DriverSDHelper_UnknownDevice(pst_SD->v_PhyVolumeID, eSDUn_CMD1);
    }
   }

   if (v_error == 0)
   {
     v_error = f_DriverSDHelper_SendCMD16(pst_SD);
   }
  }
  else
  {
    /* Unknown card */
    f_DriverSDHelper_UnknownDevice(pst_SD->v_PhyVolumeID, eSDUn_CMD8);
  }
}

/* if Card is SDv1 or better then acquire CSD/CID */
switch(st_SDPhysical[v_PhysDevID].v_CardType)
{
   case eSDCardSDv1:
   case eSDCardSDv2Block:
   case eSDCardSDv2Byte:
     f_DriverSDHelper_SendCMD9(pst_SD);
     f_DriverSDHelper_SendCMD10(pst_SD);
     break;
  default:;
}

/* Deassert CS, clocked */
f_DriverSDHelper_DeSelectDevice(pst_SD);

/* Release Mutex, finished exclusive SPI access */
Driver_Control((DRIVER_STRUCT *) &pst_SD->st_SPI, CMD_SET_SPIMUTEX_OFF, NULL);

if (st_SDPhysical[v_PhysDevID].v_CardType == eSDCardUnknown)
{
  v_retval = 1;
}
else
{
  st_SDPhysical[v_PhysDevID].v_DriverState = eSD_Started;
  v_retval = 0;
  pst_SD->st_SPI.v_ConfigReg = 0xA002; /* increase clock to 24MHz */
}
st_SDPhysical[v_PhysDevID].v_OpenCnt = 0;

return v_retval;

}

After completing the TDD phase on my host (PC) I needed to run my tests on the actual target (ColdFire) microcontroller.

In the next picture you may see the hardware setup along with my programmer. I used a micro-SD of 8GB from Kingston for test.

sd_board

I had already captured the sectors (and image) of the SD card and saved them on my hard-drive. I wanted to be able to compare what the microcontroller would read with the actual data stored.

After having my target run the code, I opened a PuTTY terminal to connect with my virtual COM on my target. Then through the CLI (Command Line Interpreter) I mounted the SD card. I issued the SDInfo command and the data provided the SD card “geometry”.

sd_cli_init

I then read sector zero (or MBR for FAT file system). I compared the data with the image capture to confirm reading of the same piece of information.

sd_cli_rdsec0000

 

The first FAT sector (0x2000) was also read and verified. I had to check it as I needed to run a FAT File System Handler to read the SD Card at a later stage (not very later, though).

sd_cli_rdsec2000

Then the write tests started. My write command in CLI supports a single 32-bit value write currently. This is sufficient at the moment to verify a sector write operation. So I used sector 1 which is unused to write the value 0x1234567

sd_cli_wrsec0001

Next a read on sector 1 is performed to check that the sector was written. And voila! Notice the Big-Endian write (0x78 at byte 0, instead of 0x12).

sd_cli_wrsec0001b

 

At the same time during debugging I used my Tektronix TDS3012B Digital Oscilloscope and a Python script to capture and decode the SD SPI data.

spi_capture

The script outputs also a VCD format file suitable for use with GTKWave. Thus I could see and analyse the data, both analog and digital.

spi_sd

Due to the TDD methods used the debugging phase on the target was very fast. With a few iterations and the help of the scope and the Python scripting tool the SD card driver worked well.

 

 

 

 

 

 

To RTOS or not to RTOS?

To RTOS or not? (to RTOS)

 

Summary

Often in the embedded world the question of using a Real-Time Operating System (RTOS) or not, is the big question amongst engineers. The answers found on-line are usually biased opinions without metrics or scientific support of the argument. They usually state the advantages or disadvantages over the classic round-robin systems. The truth is that engineers prefer and like evidence instead of heuristics. I will try to answer this, as I did for myself. I believe this small guide will help decide if an RTOS is worth the effort or not. 

Task Schedule
Example of Task Schedule in Pre-Emptive System

 

Many times the same question has been asked by embedded systems engineers, regarding whether they should use an RTOS or not.

 

Requirements of Embedded Systems

The embedded systems are often called Real-Time Systems and the terms are used interchangeably although this may not always be the case. Ie. There are embedded systems that may not be real-time. Think for example of a thermometer. There is an embedded processor, but failing to measure the temperature in time does not have an impact. 

One misconception is that Real-Time means very fast. This is a misleading interpretation. Real-Time means deterministic. For example if an event happens, our system needs to respond within a time limit. Depending on the application this time-limit will vary. In addition if multiple events are processed and all have the requirement of real-time then every event should be processed according to its own deadline.

As you may see we stress the property of time. Embedded systems may have other restrictions as well like memory footprint etc. but because here the resource we need to analyze and RTOSes handle it, is time.

 

Round-Robin

Round-Robin systems may come in two varieties. Fixed execution, or scheduled.

Round Robin AVRILOS
Example of Round Robin System

Fixed execution is the system which is hard coded. The main loop calls a list of functions (tasks) which each one process their own events.


Void Main(void)
{
   SystemInit();
   For(;;)
   {
     SerialPort();
     ProcessData();
     SetIO();
     SysTick();
   }
}

Obviously the tasks should not block on waiting, but they should rather return. This might add some complexity but in general this is probably the easiest method to build the system.

 

Scheduler

In this case each function is executed on demand. There is a top scheduler which observes which task has an event to process. Each task has also its deadline. Then the scheduler executes the best possible sequence of the previous tasks, according to their priority. This adds more complexity for the advantage of improving schedulability. Each time a task finishes the scheduler runs and decides which will the next task be.

This simple approach has a problem. What if, one of the tasks needs much processing time that upon returning to the main loop or scheduler, another task may have lost its deadline? Maximum response time in this case is the worst execution (till CPU release) of the set of all tasks. On average you may get better response time than Round-Robin systems but the average value cannot be used for real-time systems.

 

What is RTOS?

RTOS tries to solve the schedulability problem by pre-empting the tasks. This means that each task thinks that runs alone into the system without interruption. The scheduler will pre-empt each task according to some rules and will return back at the same point to continue when all the higher priority events have been processed. Although it might seem too complex, it is not so difficult to be done. Looking at the code of some RTOSes you will understand the logic behind it. Beware thought that many RTOSes are not code friendly. Ie. The code is not well written in respect to reading. For me this is what I consider one of the parameters of choosing an RTOS. Even if the RTOS is not perfect, if you have the source and it is readable you can fix or improve things. If the code is unreadable, then it is far more difficult to change it.

In fact even Round-Robin systems do pre-emptions! Can you guess it? The interrupts. The interrupts do exactly the same; However these are considered hardware priority (which is true) and limited in capacity or numbers. Thus actually RTOSes add one more layer of software pre-emption.

 

Comparison

So why not everyone use an RTOS? There are many reasons.

Example of RTOS Driver
RTOS COFILOS

 

First there is complexity. Using an RTOS may require additional code (like protection mutexes, semaphores, messages etc), that were not needed before.

Second the question of which RTOS to choose is not simple. Some are free, some need licenses and are expensive; others have a large footprint, or no do not provide source code.

Third are resources. What if your memory requirements need a very low footprint system or time constrains prohibit such systems? Maybe an RTOS cannot fit?

And the list goes on.

 

Solution?

And that’s how the question described in the beginning starts. Seems that there is no specific engineering parameter that would pin-point if we really need an RTOS or not. But let’s go back to the principles of decision. What all systems try to do? Share the CPU time resource. Is RTOS better in schedulability in respect to the other non pre-emptive systems?

Actually there is a very good principle that helps us in general with schedulability. This is called Rate-Monotonic Approach (RMA). This method analyzes a system to check if it is possible to schedule its tasks. The inputs are various parameters like period of events, sporadic events, deadlines, etc that help derive mathematically if the system is schedulable. This approach works with fixed-priority schemes and with either pre-emptive or non pre-emptive systems.

Thus the methodology would be to estimate each tasks worst execution time, gather all the deadlines, fill in the matrices and get a result if the specific system is schedulable. Analyzing the round-robin systems first you get the idea if this will work or you stress the system.

RMA proves that a pre-emptive system is better. Thus if you round-robin systems fails to be schedulable, you should try the RTOS. Of course you have to add the context switching time and any other overheads. If the system is schedulable (with a safe margin), then using an RTOS is the solution with the given hardware. It might be the case that neither solution works. In this case you need probably to upgrade the hardware.

Fixed priority is not the best scheduling method, but it is predictable. Earliest Dead Line (EDL) priorities are better, but RMA cannot define how much better. Thus an EDL system will work if the fixed scheduled system is also schedulable.

 Of course there other parameters to consider in this case like costs, memory footprints etc, but the fact is that if you need an RTOS, the question moves from “To RTOS or not to RTOS?” to “Which RTOS?”  which is a whole new story.

 

Examples and Experience

During my carrier I rarely needed an RTOS. Classic round-robin systems would fit the bill very well. And that’s how AVRILOS came along over the years started from 8051 in the ‘90s and then ported in assembly to AVR in 2000. Then after a couple of years AVRILOS was re-written in C for AVR.

 

A case I should have used an RTOS

Looking back, I could see a project where an RTOS was necessary and I failed to see that at that point. The project was a cash register machine. I wrote the OS, which performed dynamic scheduling with Earliest Dead Line first priority but without pre-emption. The main application which we wrote with my colleague had to be split in sub-states and return to the main loop at the 2mS slot interval allocated for every task. This got us a tedious development. The funny thing was that we had implemented a one task pre-emption in case a task was missing its deadline. This was of course a safeguard and was not really used. But the pre-emption mechanism was there. Things got worse when I had to do the 10.4 digits BCD division which itself was longer than 2mS on our Z80 core. The full system could work skipping all these states/substates coding part from our side, if we had chosen to use an RTOS (or build our own). Although we had memory limitations, the extra code to support the splitting of the main application probably would be covered by the RTOS itself with a cleaner implementation.

 

A case that an RTOS would not fit

In another instance we were building the MAC layer of 802.11abg with smart antennas. Our core was an ARM9 with tightly coupled memory (TCM) running at 80MHz. The external bus was running at half the frequency as the connected logic (FPGA) could not go faster. At that point I was wondering if using an RTOS would be beneficial. The system had to respond in 2uS from an event, which means it had to process the received packet and prepare a response. Utilizing some system pipelining we could extend to 4-6uS. When I tried an RTOS to see the overheads, I realized that the penalty was about 2uS. The time cost was way too much, so I used the classic round robin approach which was matching the system needs pretty well.

So you may see from the above examples that the decision to use or not an RTOS was irrelevant of the system complexity or the execution speed, but rather a matter of schedulability.

 

Conclusion

The question to place an RTOS or not can be greatly answered depending on schedulability. If the system can be scheduled without an RTOS safely then you do not need an RTOS. If not, then RTOS is the way to go. Of course there can be other reasons for the decision, like future expansion, ready stacks to use etc. but these goes beyond the basic principles of decision. You may use the RMA method to provide the criteria for your decision.

 

References

[1] Meeting Deadlines in Hard Real-Time Systems

The Rate Monotonic Approach, by Loic P. Briand and Daniel M. Roy, ISBN 0-8186-7406-7,

IEEE Computer Society

 

[2] AVRILOS

AVRILOS: A simple OS for AVR microcontrollers

https://www.codeproject.com/articles/127095/avrilos-a-simple-os-for-avr-microcontrollers

 

FunkOS Driver with Mutex

 

I am currently working on the SD/MMC driver for CoFILOS.
During this time I figured out that there are some issues with the Mutex system, whih I will describe here.

FunkOS uses a driver structure that contains everything needed from the driver level. It mainly contains the standard FunkOS Driver entry point functions (Function Pointer to Init/Read/Write etc), a mutex entry and then custom data which are defined per each driver.

The Driver level is actually a wrapper of the actual driver functions that are called. There the common functionality required by the driver system is implemented. Then the function pointers call the actual work routines of the driver.

FunkOS Driver and Mutex Architecture
What FunkOS Driver does

The mutex function is checked on the Driver level. Now as the mutex is stored on the driver structure, the mutex will work for two tasks if both tasks share the same driver structure. For example accessing the serial port with two tasks that share the serial port (not a very common scenario) means that both tasks should share the same structure. This might be fine for such applications with the drawback that both tasks share the driver structure. Who in this case does the initialization? There are some issues to be solved by the application.

However I do not believe this would be the common case of the drivers. Normally a single task access each device, so this is not a big problem.

Let’s see another example. The SPI interface supports multiple physical devices that may be accessed. The SPI bus itself is a common shared resource. Each SPI device may use different clock speeds and phase settings to work. I would expect in this case that each SPI device has its own Driver structure. Actually this is how the SPI driver is built in CoFILOS.

CoFILOS Driver Requirements
How CoFILOS requires to work

Now the common mutex scheme employed by FunkOS would not work, as the mutexes are inside each structure; This means a mutex lock will lock the specific driver’s mutex. Another task will still access the SPI as the mutex of this driver is not locked. This leads to the probably obvious  solution to keep a driver internal common mutex to properly support mutlitasking.

SPI driver example with internal mutex
CoFILOS SPI Driver Implementation

The new implementation supports two different configuration of access. The first mode is the interleaved mode. There each task may access the SPI interface per transaction (read/write). So two tasks can execute transactions to two different devices. Each transaction though is locked, so we do not scramble the SPI input/output data.

However there are cases where we need to lock a complete transaction sequence. In this case the SPI driver through the Control function supports locking of sequences. In this case CS of this device should be manipulated by the task level itself. This could be modified to be done on the driver as well, but I have not decided if there is a need for handling CS from the task level. This scheme is used for the SD/MMC interfaces where the there is a requirement of series of actions, especially during the initialization phase.

Timeline of two tasks accessing the Driver

TDD cannot completely cover the full testing of this sequence easily, I just created a primitive test to check critical sections and mutex claims, without actually checking the internal sequence. This is a risk I will take in order to reduce the development time, as my main task is the SD/MMC driver interface implementation.

CLI On Target (Perseus-ColdFire)

Before  a couple of weeks the CLI code compiled and downloaded to the target. It took a few hours to do any necessary code porting due to compiler differences (mostly some defines).

I also had to fix some project settings on my Processor Expert (PE) configuration to work correctly on Internal RAM or Internal Flash configurations for the Perseus board.  Now everything is smooth. I prefer to test on Internal RAM (as a program memory) as at this phase I will need to do many iterations (and thus save my flash memory for later). The code is not very big at the moment so It can fit on the 64KB of my MCU.

The first hickup was that my terminal was receiving 2 bytes as a response (ie. 0x30, 0xFF) from my target. I was afraid that my FTDI which was in a QFN package may not be correctly soldered. I already had difficulty to solder it. I used a QFN part by mistake, as I try to avoid them for prototypes which require manual soldering. I had to probe with my Oscilloscope to the Rx/Tx lines. I soon discovered that the stop bit seem to have double width (and thus re-initiating a Start sequence for the UART). I could not control this through Processor Expert (the Parity was grayed out). I then discovered that I used a wrong PE component. I used AsyncroMaster instead of AsyncroSerial. Using the correct component I was ready to go.

I had tested everything on TDD, so I was keen to find out if this would work well the first time. Nahh. Merphy’s law. A few things worked or worked partially a few other did not work at all.

Well it is about specifications. I did test with TDD and I assumed how VT100 would work, but did not test the behavior beforehand. Well assumption is mother of failure, right?

The first problem was <CR> or <LF>. Initially my code could handle either one as an end of line character, but did not work well on PuTTY which sent always <CR>. Thus I modified the code to be robust on this matter and do not care about <CR> or <LF> (or select between the two correctly at compile time).

The majority of the minor issues where easily solved. First I tested the behavior in PuTTY and then replicate that on my TDD testbed. The most difficult part was the <DEL> button.  Actually the key <DEL> sends the backspace character! Well there is a very good explaination here why.

CLI Basic Tests
CLI Basic Tests

In anycase everything sort out very fast, and I apprecieated that my TDD testbed helped do lot’s of functional tests before going to the target. As long as the protocol was understood, it was easy to test all the functionality and make sure nothing was broken in the change process.

CLI Test Example
Running various commands

After the basic line editing worked, I started testing the history function. Ohh, that was easy, worked from the begining… thanks TDD.

The help function had some issues but it was also a quick fix. The help function has to access the top level command table and then get the relevant help strings. Because it has multiple lines to output, the CLI service shall wait the serial port to complete the previous line outputs. Thus a state machine inside the CLI core and the relevant command (in this case Help) to output multiple lines. This is to avoid using extra RAM buffers simply for text outputs.

CLI Help Command Example
CLI Help Command

Did I finish? No I had to test the Flash Read/Write functions, RAM Read and Write, CPU and Version. Everything was set within a few hours.

SPI was another beast, as it did incorporate the newly built driver. This time TDD did its work! Hehe, everything went smooth. I checked the data with the my Osciloscope and tried to access my on-board   Serial Flash. Great, I can see it!

It took me about 40 hours for CLI, another 30 Hours for the SPI drivers, and around 10 hours for debugging these modules. I hope the next sprint would go faster. It seems that before doing anything you need to plan (yeah, I already knew that). The most difficult part is to figure out the architecture. It helped me a lot, to get up to speed when I did the SPI driver.

Conclusion

Another sprint finished. I was so happy, but at the same time I knew I had a long way to reach my first milestone. I still have to access my SD card and add a FatFS module.

 

Funk OS Port for Coldfire on SourceForge

I just uploaded my port of FunkOS for Coldfire microcontroller devices. The code is an Eclipse project with PE, that runs an example I created to test it. The port is not cleaned by commented code, as my time is limited. This is the reason I did not post it earlier. I thought that I need to clean it up from unused content. So time passed and I decided to get along and post it as is.

It uses a modified version of FunkOS R3. The modifications included code fixes that my MISRA checks were complaining on the original FunkOS code, mostly on external packages (like graphics).

The test code included three tasks (Idle, LedAlive, Test), that were going to sleep for a while, did something (LED toggle) and then waited to synchronize by a semaphore with an other task. That created a nice LED blinking with two LEDs.

You may find the project at COFILOS page here.

My post on FUNKOS PORT TO COLDFIRE V2 was based on this code.

I hope someone finds it useful.

 

 

Completed CLI for COFILOS

During the last weeks I finished a long task that I had…

My COFILOS CLI is ready and tested with TDD in my host.
Still I have to test it on my target.

To be honest the main skeleton is ready. Currently only internal commands (ie. compiled) are available. In the future after the addition of the FAT-FS on my SD card I plan to support commands that exists on my SD. This is much more work and is not needed at the moment.

Of course it has some neat things for an embedded system, like line editing and command history.

It took me about a week’s time to implemented it (still the majority of my efford was the design of a scaleable architecture and modularity). However this week time seemd to me too long (1-2 months..), as I work on it when I have time.

I computed myself the memory footprint and it takes about 500-600 bytes of RAM. It seems a lot but this reminded me that strings DO take space. Lots of space in terms of small embedded systems. Fortunetely my Coldfire has 64KB of RAM so this would no be a problem; Even with 32KB I believe it should be fine.

It is very modular. Actually the CLI is a handler not doing any real I/O to UART or Network. It just handles strings, characters and VT100 commands. A thin top layer is used to transfer between the external world and the handler all the required data. In case of COFILOS this is the CLI Service task.

Next step is to implement the drivers for SPI and TWI (I2C), before going forward with FAT-FS….

By then I would complete the RAM Rd/WR, Flash Rd/Wr/Erase, SPI and TWI access functions for the CLI.

FunkOS Port to Coldfire V2

Recently I started working on selecting an RTOS for using in my projects. Given that there are many candidate solutions it was not straight forward to find an applicable RTOS.

I needed a free to use RTOS. I cannot afford to pay anything yet 🙂 If I had to pay I would go for uC/OS-III. I have the book for uC/OS-II and I consider the code, functionality and extensions pretty good.

So I started looking around. I tried FreeRTOS where I know more people are using it. I also looked at picoOS, uexecFemptoOS, XMKrtos . Looking at these I liked picoOS and XMKrtos. Both seemed to be lacking further development.

picoOS was officially declared frozen, given that there was not much contribution by the community. I can understand this as this is an issue with open source in general. You may need to have a significant traction in order for people to contribute back modules or enchancements. I liked its thorough documentation, but the fact that the code was concentrated on a big file(s) that was not easy to follow the structure was something that bothered me.

uexec and FemptoOS had the same philosophy of large files containing the full RTOS and for me the code was again not easily readable (not necessarily from the code structure, but comments or spaces seperation etc). For me it is important to look at the code immediately be able to navigate; It should be a joy to look at the code. When you have a problem it is there were you would look for! This is the spirit of open source… usually you do not expect much support, but you contribute back your improvements. In theory at least.

XMKrtos seemed pretty attractive, but I never actually tried it.

A combination of initial targets architectures (8-bit processors), licensing, code readability and other factors moved me on.

I was not pleased too much with FreeRTOS at the time although I believe it is a good implementation. Then I went through FunkOS.

Normally because of its name, I would not trust such a system for RTOS. Certainly you don’t want to have a funky RTOS, right? Well I started digging into the code and I was shocked. The way it was written was very close to my programming attitude. It was very easy to read and follow. It had also a C++ verion of it as well. And it had also a small manual. Documentation (doxygen) is not as good as picoOS, but I this can be fixed. I plan to add missing parts over time.

So jumped on FunkOS. E, hmmm. Wait a minute I did not have a port for my controller. I use the coldfire V2 family, usually MCF5225x or MCF52233 (I have a demo board), but there are not many ports in general of these controllers. So I started working on my port. Delving on the issue, I discovered that FreeRTOS has better and safer handling on some points (FunkOS was based on FreeRTOS according to its author).

Yesterday I saw another interesting project the ChibiOS/RT. As I have started working with FunkOS, I did not divert to check this one.

Now let’s see some benchmarks. I first run FunkOS on my Demo board with MCF52233. As it was my first attempt to evaluate the RTOS I had only 3 tasks:

  1. Idle Task (Priority 0, Lowest)
  2. LED Alive (Priority 1)
  3. Second LED flash, triggered by a LED Alive semaphore and a timer wait [sleep delay]; (Priority 1)
  4. One IRQ (Systick).
  •  Each task has 256 bytes stack.
  • The core (system) clock runs at 50MHz.
  • Simple stack check: FunkOS original routine. Safer but slow.
  • Fast stack check: Own faster routine. May not accuretely provide always correct information (depending on stack data). Did work well for its purpose on this example.
  • Stack usage: Idle task 68 bytes, other tasks 100 bytes.
  • Flash footprint: 9K
  • RAM footprint: 1K (includes stacks)
  • Systick execution time: 14uS without stack check, 110uS with simple stack check, 22uS with fast stack check.
 

Register Save-Restore
 

1.5uS
 

Task Switch
 

3.2uS
 

SysTick (inc. task switch) with no stack check
 

14uS
 

SysTick (inc. task switch) with simple stack check
 

45us
 

SysTick (inc. task switch) with fast stack check
 

22uS

 

Did the modifications and run the same kernel on my new Perseus development board on MCF52258. My LEDs are flashing…

Happy New Year 2015!!!