scmRTOS - small RTOS for mbed

04 Oct 2010

Oh right ok thats grand so. I have everything I need to get my program up and running. Thanks a million for all the help.

13 Oct 2010 . Edited: 14 Oct 2010

I moved the post that was here to its own thread for clarity

21 Oct 2010

Igor - thanks for this port of scmRTOS (and to the author of course!). I was about to embark on trying to develop a simple RTOS - but this does the job, and is more complete than I could manage!

The thread above has got complicated, but I understand there seem to be issues with printf on Serial. For what its worth...

I tried to write a simple read/write application, and originally found that printf failed to give the correct value - but it would print '0.0' instead. I had been using stack sizes of 300 byte (cut & paste from code exeample I think). When I up'd the stack size of the task doing printf to 1024bytes it started working correctly.

HTH

Ian Hunter

21 Oct 2010

Ah, that could explain it. Indeed, printf uses a temporary buffer for the string to be printed.

21 Oct 2010 . Edited: 21 Oct 2010
user Ian Hunter wrote:
When I up'd the stack size of the task doing printf to 1024bytes it started working correctly.

Hi Ian

Can you try running the test program I referenced in the post here, and see if changing the stack sizes fixes the problem on your mbed? Because I went to 2048 stack size for each process (excessive) and printf still didn't work. I'm using scmRTOS happily, but I've written my own code for printing floats/doubles and long long (64 bit integer). There doesn't seem to be a problem with printing strings or 32 bit integers.

You can't see it with my test program, but with my real application, changing the stack sizes moved the printf problem around ie. some processes would print ok and some wouldn't, depending on the relative stack sizes. So that's why I went to my own code for printing some numbers, to make sure that it would work reliably in all processes and not have to guess at the right stack size etc.

Regards
Daniel

PS Until proven otherwise, I wouldn't want anybody reading this thread to think that the printf problem goes away simply by increasing stack size. That has definitely not been my (painful) experience.

21 Oct 2010

Hi Daniel,

I've run it and I think I get the same result as you.

I'm fiddling with it now, and just want to clarify what the aim is...

1. I assume a timed task updates a variable.
2. Two other tasks print out the variable, each should see the same(ish) value.
3. Is it necessary to be long long?

I wapped up the stack size and I get...

[1] 1031788583452674
[2] 240252
[1] 1040464417390594
[2] 242272
[1] 1049140251328514
[2] 244292
[1] 1057816085266434
[2] 246312

Still fiddling...

Ian Hunter

21 Oct 2010

Hi Ian

Yes, you should see the same value. It's necessary to be a long long (64 bit integer) because the printf has problems with them especially as well as floats/doubles. It doesn't seem to have problems with int (32 bit), which is ok as long as you only want to print ints ;-)

Thanks for checking.

Regards
Daniel

 

21 Oct 2010

OK

FYI: In addition, I extended the code to print different int types, and extended to 4 tasks. The output I get is a bit wierd....

Notice how even tasks (2 *& 4) print a reasonable value for the 64 bit, but (1 & 3) dont. Curious.

[2] Byte= 141 Short=1903 Int=1903 Long=1903 LongLong=           1903
[3] Byte= 211 Short=1973 Int=1973 Long=1973 LongLong=  8478264918015
[4] Byte=  25 Short=  42 Int=  42 Long=  42 LongLong=             42
[1] Byte=  91 Short=1900 Int=1900 Long=1900 LongLong=  8164732305407
[2] Byte= 161 Short=1970 Int=1970 Long=1970 LongLong=           1970
[3] Byte= 231 Short=  39 Int=  39 Long=  39 LongLong=   171798167551
[4] Byte=  45 Short= 109 Int= 109 Long= 109 LongLong=            109
[1] Byte= 111 Short=1967 Int=1967 Long=1967 LongLong=  8452495114239
[2] Byte= 181 Short=  36 Int=  36 Long=  36 LongLong=             36
[3] Byte= 251 Short= 106 Int= 106 Long= 106 LongLong=   459560976383
[4] Byte=  65 Short= 176 Int= 176 Long= 176 LongLong=            176
[1] Byte= 131 Short=  33 Int=  33 Long=  33 LongLong=   146028363775
[2] Byte= 201 Short= 103 Int= 103 Long= 103 LongLong=            103
[3] Byte=  15 Short= 173 Int= 173 Long= 173 LongLong=   747323785215
[4] Byte=  85 Short= 243 Int= 243 Long= 243 LongLong=            243
[1] Byte= 151 Short= 100 Int= 100 Long= 100 LongLong=   433791172607
[2] Byte= 221 Short= 170 Int= 170 Long= 170 LongLong=            170
[3] Byte=  35 Short= 240 Int= 240 Long= 240 LongLong=  1035086594047
[4] Byte= 105 Short= 310 Int= 310 Long= 310 LongLong=            310
[1] Byte= 171 Short= 167 Int= 167 Long= 167 LongLong=   721553981439
[2] Byte= 241 Short= 237 Int= 237 Long= 237 LongLong=            237
[3] Byte=  55 Short= 307 Int= 307 Long= 307 LongLong=  1322849402879

31 Oct 2010

Hey again guys,

I am having a problem with reading and writing to the serial port.

I am still using the ScmRTOS and am now using 7 processes. One process handles all the output data to the serial port and any other process that wants to output data puts it into an output channel which the output process uses to output the data character by character. I have input data being put into a channel with a simple serial interrupt handler. When serial data is being input constantly or output constantly the program runs just fine but the program freezes when I start doing both together. As per previous discussions on the serial port, I have the serial port protected with a mutex so only input or output can be done at any one time. Additionally, I am not using printf to to output or scanf to input, I am dealing with the data character by character.

 

Does anyone have any other suggestions as to why this is happening?

The serial interrupt handler code:

 void USB_serial() //signal RTOS event that RXinterrupt has been asserted
{
    //char count = 0;
    //led3 = !led3;
    char temp = 0;    
    OS::TISRW ISRW;
    if(!Serial_Mutex.IsLocked())
    {
        Serial_Mutex.Lock();
        while(USB.readable())
        {
            temp = USB.getc(); 

            if(RX_channel.get_free_size() >0 ) //only push a character onto the channel if there is free space
            {    
                //OUT = &USB;              
                if(temp != '\n')
                {                    
                    RX_channel.push(temp);
                                        
                }
                else if(temp == '\n')
                {                     
                    RX_channel.push('\0');
                }
            }
            else USB.getc(); //start discarding characters!
            
        }   
       Serial_Mutex.Unlock();
     }
     
     else USB.getc(); //start discarding characters!
   
}

The serial output process:

template<> OS_PROCESS void Serial_Out::Exec() //Output stream handling process
{


     char temp1 = 0;
     led3 = 0;
     for(;;)
     {
               
        TX_channel.pop(temp1);               
        led3 = !led3; 
        Serial_Mutex.Lock();
        USB.putc(temp1);
        Serial_Mutex.Unlock();   
     }
}

 
 #endif

 
 
I realise that the freezing may be occurring elsewhere but I have tried to isolate it to this problem, for example, I tried not outputting any characters in the output process and left to work away for over an hour and with no freezes.

Any suggestions/thoughts welcome!

 

Regards,

Greg

31 Oct 2010

I have also tried to rule out the likes of stack overflow causing issues by deliberately including large delays in the output process.

I have two processes outputting data to the output channel every 60 to 80 ms and I am sending a character sting to the mbed every 60 ms or so. With the output process not outputting anything, there is no problem at all.

My output process looks like this with the delays:

template<> OS_PROCESS void Serial_Out::Exec() //Output stream handling process
{


     char temp1 = 0;
     led3 = 0;
     for(;;)
     {
               
        TX_channel.pop(temp1); 
        wait_ms(200); //simulate delays and context switches
        Sleep(100);     
        led3 = !led3; 
        Serial_Mutex.Lock();
        USB.putc(temp1);
        Serial_Mutex.Unlock();   
     }
}

 
 #endif

01 Nov 2010 . Edited: 01 Nov 2010

Ok so I have narrowed down the problem by outputting a unique combination of lights on the LEDs at different sections of my code. The mbed is freezing at a certain repeatable spot every time. In the serial interrupt code shown above (the first block of code I posted relating to this problem), the leds are all turned just before the Serial_Mutex is unlocked and this is how I know where the mbed is freezing. Does anyone have any suggestions on the significance of this and/or what I can do about it?

 

Thanks,

Greg

 

EDIT: I thought it was related to the Mutex but this is not the case as I tried removing the mutex as well.

The serial interrupt handler now looks like this:

 void USB_serial() //signal RTOS event that RXinterrupt has been asserted
{
    OS::TISRW ISRW;
    leds = 0x7;
    //char count = 0;
    //led3 = !led3;
    char temp = 0;    
    
    //leds = 0xa;
    if(true)//!Serial_Mutex.IsLocked())
    {
        //leds = 0xb;
        //Serial_Mutex.Lock();
        leds = 0xc;
        if(USB.readable())
        {
            temp = USB.getc(); 
            leds = 0xd;

            if(RX_channel.get_free_size() >0 ) //only push a character onto the channel if there is free space
            {    
                //OUT = &USB;              
                if(temp != '\n')
                {                    
                    RX_channel.push(temp);
                    leds = 0xe;                    
                }
                else if(temp == '\n')
                {                     
                    RX_channel.push('\0');                    
                }
            }
            else USB.getc(); //start discarding characters!*/
         leds = 0xf;
         leds = 0xa;            
        }   
        leds = 0xb;
       //Serial_Mutex.Unlock();
       //Serial_Mutex.Lock();
       //if(USB.writeable())
        //USB.putc(temp);
           //Serial_Mutex.Unlock();
       leds = 0x1;
     }
     else USB.getc(); //start discarding characters!
        
   leds = 0x9;
}
The program is freezing when the leds are left all on, i.e. just after the line: leds = 0xf;

01 Nov 2010

Apologies in advance if this is useless information but the simularities seemed close enough to comment. I'm not using scmRTOS but faced a problem a few moments ago that looked identical. Some background first. I have an application, written in pure C that works just fine. I'm converting it to C++ to make it's construction more intuative. And here's where the fun starts when dealing with interrupts.

With the C version the ISR can callback into the correct places without an issue. Even before the power is switched on, the Flash "knows" where ISR callbacks are going to go, they are resolved by the linker at compile time. However, when moving to C++ these get somewhat messier. This is because the callbacks are now methods within classes and these "function pointers" can't be done at compile time. In step the C++ "functor". Now, the Mbed libraries have methods called ".attach()" that allow ISR callbacks to methods. Looking at FunctionPointer.h you seel that .attach() uses these functors to make the callback. I don't actually use Mbed's FunctionPointer, I use my own version of functors but the principles are the same. So where is the problem?

In my conversion, I had a bug whereby I managed to do NVIC_EnableIRQ(UART1_ISRn) before I had made the attachment callback. Simply put, the C ISR merely looked for an attachment and make the call. What it didn't do was read the ->IIR register which clears the interrupt. So, if a serial IRQ fired before I had completed the attachment, when the ISR returned it interrupted immediately, and again, and again, infinite loop and the Mbed locks up. Obviously my bug was to make sure I either complete the attachment before enabling the interrupt or make sure the C portion of the ISR always read the ->IIR register regardless to dismiss the interrupt.

This maybe off topic for your problem but since you added LEDs to debug your problem, if you have the ability to see if the ->IIR register is being read in the ISR then this mybe a clue to the "lockup". Remember, just reading the ->IIR register is enough to dismiss the interrupt.

01 Nov 2010 . Edited: 01 Nov 2010

Hi Andy, thanks for the detailed information. To my surprise, I understood every word of what you said!

Ok so I must confess using the Mbed is my first dabble with an ARM and I have little knowledge of how it is programmed on the lower levels. (That, unfortunately we only learn next semester!)

So in relation to your suggestion, I am most certainly willing to give it a shot if it will help. Would you be able to furnish me with a statement that I can use to do such? It will save me a lot of time scouring the LPC1768's user manual!

Thanks!

Greg

 

P.S. thinking about what you said, if this problem was the case, and it was in an infinite loop just after returning, wouldnt the last instruction in the function still have completed? For example, the last instruction in my my function sets the leds to 0x9 wheras the leds are being continually set to 0xf which is a few instructions before the function returns.

01 Nov 2010

Can you publish your program so I can take a look at the whole thing rather than a tiny portion on a forum?

01 Nov 2010 . Edited: 01 Nov 2010

No problem at all. Please excuse the presentation of the program!

The link for it is:  http://mbed.org/users/jberry/programs/scmRTOS_test/lh77rv

 

Thanks a million for taking the time!

 

EDIT: Andy, I cause the lockup to happen when writing data repeatedly to the mbed and have it output data back to the pc. I am trying to cause it to happen now by simply sending data destined for the motor_control process and havent been able to get a lock up. I get a lockup by getting one of the other processes to continually output data as well. The way I have been able to get a lockup recently is by sending the mbed the following strings:

"PIC\n"

"ACR\n"

and then a string like:

MO2:0.000000:0.007812 every 100 ms.

The PIC and ACR command causes the mbed to send data data back at 80 and 70 ms intervals respectively. The serial port speed the USB serial port is running at is 921600 baud.

01 Nov 2010 . Edited: 01 Nov 2010

This is something of a hack, find this....

leds = 0xc;
if(USB.readable())
{
    temp = USB.getc(); 
    leds = 0xd;
 

 

and try doing this as a test:-

leds = 0xc;
uint32_t iir = (LPC_UART1->IIR >> 1) & 0x7;
if (iir == 0x2) 
{
    temp = USB.getc();
    leds = 0xd;

This does the same as USB.readable()  If it still locks up then the problem isn't the IRQ firing before teh system is ready. If it doesn't fix the problem It may at least rule out one potential issue.

 

01 Nov 2010

Ok Andy I have tried it and the program doesnt seem to like it one bit. The program works up intil I send something, at which point I am back to a lockup as before. (leds = 0xf)

02 Nov 2010

Ok so I am kicking myself! I reread a forum post on pretty much the same problem I was having and actually read it and it turned out that a suggestion by Simon Ford to use extra serial objects solved it! Happy days! 2.5 hours constantly reading and writing and no lockups!

 

Apologies for wasting your time Andy.

02 Nov 2010

Jason, no worries, glad you got it solved! :)

23 May 2011

Hello,

I start with mbed and I need to use an RTOS for my project but I have problems with basic functions. When I run my program the mbed blocks at the multitasking sequence. I saw on the forum that several problems have been addressed on scmRTOS and I increased the size of the stack but without result. Do you have any other ideas for me?

The program crashes with the basic functions that I show below but in the real program I want to call a function that will connect to an NTP server to retrieve the time, the problem is that the program does not end process and blocks other processes.

You can see the program here: http://mbed.org/users/etudiant12/programs/RTOS/lrlqq9

Thank you for your help Olivier

int main(){

wait(8);

run OS::Run(); }

--------------- template<> OS_PROCESS void TProc1::Exec() { for(;;) { Sleep(3000); pc.printf("Execution Process 1\n") } }

--------------- template<> OS_PROCESS void TProc2::Exec() { for(;;) { Sleep(5000); pc.printf("Execution Process 2\n"); } }

--------------- template<> OS_PROCESS void TProc3::Exec() { for (;;) { char c = pc.getc(); if(c == 'a') { pc.printf("On va afficher l'heure\n"); }

} }

03 Feb 2012

Hello,

I finally find what I need for my programming, however, I need abit of help from all of you. currently I am implementing an interrupt using keypad inside the RTOS, but I dont really know how should I implement it. If I am not wrong, we couldnt write in inside the process. I need some guidance on how can I use it. Thanks in advance!

Regard Daryl Tan Wei Guang

12 Feb 2012

Hi:

I have a problem with scmRTOS

#include <mbed.h>
#include <scmRTOS.h>

typedef OS::process<OS::pr0, 5000> TProc1;
TProc1 Proc1;
Ticker Update1;

void Update1ISR()
{
    printf("Calling from %s\n", __FUNCTION__);
}

template<> OS_PROCESS void TProc1::Exec() {
    Update1.attach(&Update1ISR, 2.0);
    printf("TProc1::Exec() called once\n"); 

    while (1) {
        printf("Before ... ");
        __WFI();
        printf("after\n");
    }
}

//---------------------------------------------------------------------------
long long count = 0;

int main() {
    printf("\nInitialising ...\n");
    OS::Run();
}

I expect that "after\n" is to be printed out after the process is interrupted. However, when the program runs, it seems that it did not "sleep" as it kept on printing "Before ... after\n"

Any idea?