westfw,
Almost nothing you say about modern preemptive kernels is true.
I know a lot about Cisco's IOS. I worked in the network research group at LBNL and we had a close relationship with Cisco. The head of our department, Van Jacobsen, became chief scientist at Cisco.
IOS has a run to completion scheduler, which means that the kernel does not pre-empt a running process — the process must make a kernel call before other processes get a chance to run. For Cisco products that required very high availability, such as the Cisco CRS-1, these limitations were not acceptable. In addition, competitive router operating systems that emerged 10–20 years after IOS, such as Juniper's JUNOS, were designed not to have these limitations.
Cisco's response was to develop a new version of Cisco IOS called IOS XR. It is based on 3rd party real-time operating system micro-kernel (QNX), and a large part of the current IOS code was re-written to take advantage of the features offered by the new kernel — a massive undertaking.
A company like Cisco can afford to spend a lot of resources to polish a product that will sell in large volume and high profit. The methods used by Cisco for communications don't necessarily translate to other applications.
For one-off hobby projects a RTOS can be a good tool to accomplish more with less code and time.
I agree that a ATmega 328 is small for use of an OS and it wasn't designed for quick context switches. Still FreeRTOS can do a context switch on a m328 in about 50 us.
ARM processors were designed to be run with a micro-kernel. A modern micro-kernel can do a context switch in as little as 2.2 us on a 72 MHz stm32 http://yagarto.de/projects/rtoscomp/index.html. ARM Arduino is where a RTOS could help hobbyists accomplish more sophisticated projects.
Here is the FreeRTOS test program I used with a scope to check the context switch time. The lower priority task switches an LED on, off, on, and then gives a semaphore to do a context switch to a higher priority task which turns the LED off.
#include <AvrFreeRTOS.h>
#define LED_PIN 3
xSemaphoreHandle xSemaphore;
static void ledOffTask(void *pvParameters) {
for (;;) {
xSemaphoreTake(xSemaphore, portMAX_DELAY);
digitalWrite(LED_PIN, LOW);
}
}
static void ledControl(void *pvParameters) {
for (;;) {
vTaskDelay(10);
digitalWrite(LED_PIN, HIGH);
digitalWrite(LED_PIN, LOW);
digitalWrite(LED_PIN, HIGH);
xSemaphoreGive(xSemaphore);
}
}
void setup() {
pinMode(LED_PIN, OUTPUT);
xTaskCreate(ledOffTask,
(signed portCHAR *)"Task1",
configMINIMAL_STACK_SIZE,
NULL,
tskIDLE_PRIORITY + 2,
NULL);
xTaskCreate(ledControl,
(signed portCHAR *)"Task2",
configMINIMAL_STACK_SIZE,
NULL,
tskIDLE_PRIORITY + 1,
NULL);
vSemaphoreCreateBinary(xSemaphore);
vTaskStartScheduler();
}
void loop() {
// Insert background code here
}