About porting FreeRTOS to general 80C51 MCU

Nice to meet you all! Recently I am trying to port the FreeRTOS on some gerneral 80C51 Core based MCU with 2K External memory. I made referenced to the Cygnal 8051 based port. However, I find that I fail to run even a single task. I found that it fails in the pvPortMalloc(). I found that the following statement always false: if( ( usNextFreeByte + usWantedSize ) < portTOTAL_HEAP_SIZE ) I am using the snapshot version of SDCC with the library for reenterant from FreeRTOS websites. I had modify the portSTACK_START according to the MEM files generated by the SDCC. I had also modify the variables in portmacro.h. Any idea for this problems? Thank you~

About porting FreeRTOS to general 80C51 MCU

To clarify, I also modify the port.c and using Timer 0 as the schedular. Thank you~

About porting FreeRTOS to general 80C51 MCU

2K is not much to play with. What is portTOTAL_HEAP_SIZE set to?  Is there a memroy bank set up large enough to hold the entire array?  Are there any warnings at link time?

About porting FreeRTOS to general 80C51 MCU

The portTOTAL_HEAP_SIZE was set to 1500. The memory bank was set to 0 (so that except the R0-R7,all the others 256 bytes was used for SP, right?) There is no link warnings. I had tried to implement some simple timer program to change the GPIO port(to flash LED)(without RTOS), everythings seems to be alright. The timer should be working fine.

About porting FreeRTOS to general 80C51 MCU

Anyway thanks for your help. In fact 2KBytes external memory , is that enough for 1x – 20 tasks for FreeRTOS? I am running the chip @ 40Mhz (12 Clocks for 1 intruction cycle).

About porting FreeRTOS to general 80C51 MCU

>Is there a memroy bank set up large enough to hold the entire array? I think you may be getting PIC and 8051 confused here.  The PIC port has the .lkr file in which the banking requires adjustment.  That is not relevant here. With the 8051 port the external RAM size is set in the makefile, using the –xram-size option.  In the download this is set to 8448, and for 2K external RAM should be adjusted to 2048.

About porting FreeRTOS to general 80C51 MCU

Hi, If you look in the map file you should be able to see if the heap is allocated correctly.  The variable you are looking for is xHeap. For example, the map file for the cygnal build had the following section: Area                               Addr   Size   Decimal Bytes (Attributes) -——————————-   —-   —-   ——- —– ———— XSEG                               0000   18B9 =   6329. bytes (REL,CON,XDATA)       Value  Global    ——–  ——————————–   0D:0000    Ftasks$pxReadyTasksLists$0$0   0D:0058    Ftasks$xDelayedTaskList1$0$0   0D:006E    Ftasks$xDelayedTaskList2$0$0   0D:0084    Ftasks$pxDelayedTaskList$0$0   0D:0087    Ftasks$pxOverflowDelayedTaskList$0$0   0D:008A    Ftasks$xPendingReadyList$0$0   0D:00A0    LsTaskCreate$ucTaskNumber$1$1   0D:00A1    Fheap_1$xHeap$0$0   0D:18A5    Fprint$xPrintQueue$0$0   0D:18A8    LvStartPolledQueueTasks$xPolledQueue$1$1   0D:18AB    Fserial$xRxedChars$0$0   0D:18AE    Fserial$xCharsForTx$0$0   0D:18B1    LsAreSemaphoreTasksStillRunning$sLastCheckVariables$1$1 [this will probably look a mess when pasted here as the spacing will be all wrong] If you see the entry Fheap_1$xHeap$0$0 you can see that it starts at A1 and ends at 18A5, so is approx 6K big.  What do you see for these figures in your map file? Also note my comments regarding the –xram-size setting within the makefile made in a different post.

About porting FreeRTOS to general 80C51 MCU

Thanks a lot for your help, the following would be my Mem location for XHeap function: Area                               Addr   Size   Decimal Bytes (Attributes) -——————————-   —-   —-   ——- —– ———— XSEG                               0000   07BB =   1979. bytes (REL,CON,XDATA)       Value  Global    ——–  ——————————–   0D:0000    F______Source_tasks$pxReadyTasksLists$0$0   0D:0058    F______Source_tasks$xDelayedTaskList1$0$0   0D:006E    F______Source_tasks$xDelayedTaskList2$0$0   0D:0084    F______Source_tasks$pxDelayedTaskList$0$0   0D:0087    F______Source_tasks$pxOverflowDelayedTaskList$0$0   0D:008A    F______Source_tasks$xPendingReadyList$0$0   0D:00A0    LsTaskCreate$ucTaskNumber$1$1   0D:00A1    F______Source_portable_MemMang_heap_1$xHeap$0$0   0D:07AD    F___Common_Full_print$xPrintQueue$0$0   0D:07B0    LvStartPolledQueueTasks$xPolledQueue$1$1   0D:07B3    LsAreSemaphoreTasksStillRunning$sLastCheckVariables$1$1

About porting FreeRTOS to general 80C51 MCU

Your print out shows that 1.75 KBytes have been allocated to the heap, which is good.  It is odd then that the line: if( ( usNextFreeByte + usWantedSize ) < portTOTAL_HEAP_SIZE ) would return false. usNextFreeByte should be initialsed to 0 – this is an initialised file scope variable which should be set to 0 before main() gets called. usWantedSize is the parameter you pass in, which is presumably quite a small number (?). And portTOTAL_HEAP_SIZE is your constant. So how can this line fail?  Can you step through the code to this point and look at the values of usWantedSize and usNextFreeByte.  The only thing I can think of is that usNextFreeByte is not being initialised properly or it is getting clobbered before you get to the function call. Regards.

About porting FreeRTOS to general 80C51 MCU

Thank you. Richard. I will have another trial tonight. Another question, is that for my case, the following definition needed to be change: #define portMINIMAL_STACK_SIZE        ( ( unsigned portSHORT ) 200 – ( unsigned portSHORT ) portSTACK_START ) if not, the size for those idle task would be quite large and 2K external memory seems cannot hold much tasks at the same time…thank you~

About porting FreeRTOS to general 80C51 MCU

Yes, I had already edit the makefile for –xram-size to 2048. Thanks a lot~

About porting FreeRTOS to general 80C51 MCU

I have tried to add the following function call to the main in main.c vPortInitialiseBlocks(); and I change the following #define portMINIMAL_STACK_SIZE        ( ( unsigned portSHORT ) 100 – ( unsigned portSHORT ) portSTACK_START ) This makes the sTaskCreate 0x00 in return However, I still fail to run a single task, the task as follow: static void prvToggleOnBoardLED2( void ) {     /* If the on board LED is on, turn it off and visa versa. */     if( P1 & 0x20 )     {         P1 &= ~0x20;     }     else     {         P1 |= 0x20;     } } /*———————————————————–*/ static void vToggleLED( void *pvParameters ) {             (void)pvParameters;     P1_4=0;     for(;;)     {         prvToggleOnBoardLED2();         vTaskDelay(0xff);     } }        

About porting FreeRTOS to general 80C51 MCU

Sorry for disturbing all of you again. I found that some static variables are not being initialised. Is that the lastest snapshot version of SDCC imcomplatible with the reenterant library? If that is the fact, I may try to implement the freeRTOS by using Keil C. Thank you~

About porting FreeRTOS to general 80C51 MCU

1 more question: When main() try to call sPortStartScheduler() if I have just one single task made, the pxCurrentTCB should be points to the TCB of that task or not? and the value stored inside the *pxCurrentTCB should be the stack size (17 in this case?)

About porting FreeRTOS to general 80C51 MCU

Is this the case when you try compiling a simple "hello world" type program?  Maybe the variables are getting initialised, but then corrupted. Can you look at the startup asm code to see where the initialisation should occur? If you find that you get the same problem with a simple "hello world" program then try sending the program (it must be small and compile ‘out of the box’) to the sdcc support mail list.  http://sdcc.sourceforge.net has the list information.

About porting FreeRTOS to general 80C51 MCU

You will actually have two tasks – because the idle task is created automatically – but the pxCurrentTCB should point to your task as you say. *pxCurrentTCB will not however be the stack size – but a pointer to the top of the task stack. I suspect you may be getting some corruption somewhere. I don’t know what your debug system is like.  If you can stop the program where main() is called then take a look at the static variable values.  If they are correct then you can step through until you see it change to the incorrect value. Regards.

About porting FreeRTOS to general 80C51 MCU

Thank you Richard, it is a pity for me to have just a 89C51SND1 , it is a 8051 based core chip running @ 20Mhz (X2 mode just need 6 clock period per instruction, thus act as a 8051 @ 40MHz)…. I do not have any debug system except 2 leds…..

About porting FreeRTOS to general 80C51 MCU

Hi, void main( void ) { -—// First check if the variable starts with the -—// expected value. -—if( variable == expected value ) -——-Led1 = on; -—else -——-Led2 = on; -—// The rest of your code here } The old fashioned way :-)

About porting FreeRTOS to general 80C51 MCU

"*pxCurrentTCB will not however be the stack size – but a pointer to the top of the task stack. " Yup, thank you for correcting my mistake :) and *(*pxCurrentTCB) would be the stack size right?.. I should expected with default setting, I should get the value 17? thank you~

About porting FreeRTOS to general 80C51 MCU

yup , I am now using this method… however, it must be the most troublesome way… as I cannot check for the stack pointer and the internal / external memory map. I could just guess for my expect value :( . Some parts I would use some debug marco to swap out the whole byte for checking…

About porting FreeRTOS to general 80C51 MCU

As the first task when the Schedular started should be loading the stack with the format the same as defined in the function *pxPortInitialiseStack(), I should expected that the pxCurrentTCB is pointing to the tcb of the task I created. and the first byte pointer stored inside the pxCurrentTCB, should be the top stack address of  the task stack. This pointer should contants : 17(20),(0x11,0x12,0x13),LSB of PC , MSB of PC , 0xaa… right? It seems to me that the pxCurrentTCB is not pointing to the TCB of the task I created (when schedular first started), any idea for such …. happend.. I believe that Cygnal 8051’s context switching is basically the same as the other 8051s right? Sorry for so many questions and trouble all a lot.

About porting FreeRTOS to general 80C51 MCU

This is getting confusing – pxCurrentTCB points to the TCB. The first pointer in the TCB points to the stack. Therefore – *pxCurrentTCB = TCB of your task. and ( portSTACK_TYPE * ) TCB = the address of the task stack. *(( portSTACK_TYPE * ) TCB) = the first item on the stack. Just to add more confusion, effectively: **( ( portSTACK_TYPE **) pxCurrentTCB ) is where the stack is at. This is simpler than it looks here.

About porting FreeRTOS to general 80C51 MCU

I have tried to enforce the pxCurrentTCB to point to the first task, it would run the task for 1 tick ( I guess). From the tasks.c , I found that the PC never loops the following code:     if( usCurrentNumberOfTasks == 1 )             {                 /* As this is the first task it must also be the current task. */                 pxCurrentTCB = ( volatile tskTCB * volatile ) pxNewTCB;                                P1_5=0;                 /* This is the first task to be created so do the preliminary                 initialisation required.  We will not recover if this call                 fails, but we will report the failure. */                 sReturn = prvInitialiseTaskLists();                             }

About porting FreeRTOS to general 80C51 MCU

I think you need to find the reason the static variables have the wrong values first – otherwise everything else will also be odd also. Are you using the –no-xinit-opt compiler option.  This would seem to be a possible cause of the symptoms you are finding?

About porting FreeRTOS to general 80C51 MCU

Thank you~ I also believe that there are some problems for my SDCC(maybe setting,maybe something else)… I tried to make a static unsigned char in the main.c and initialize it with a value, however, I checked inside the main() function but it fails too… I did not use such optimized options. I straightly follow the makefile.. with just the xram-size option changed. I am now wondoring if there are any other reasons which caused the error….

About porting FreeRTOS to general 80C51 MCU

Just have a trial, with no object files built with the main.c by SDCC with the same flags, the main.c will works fine(static variable initialization) .It seems that the linker is not working correctly with the makefile…. when the main.c links with the object files(rel), all static variables initialization failed.

About porting FreeRTOS to general 80C51 MCU

Thank you all for your kindly help. I had solved the problem by reinitialize all the static variable before creating first task.   0C:4FE3    Fmain$__xinit_sLatchedError$0$0   0C:4FE5    F______Source_tasks$__xinit_pxCurrentTCB$0$0   0C:4FE8    F______Source_tasks$__xinit_sUsingPreemption$0$0   0C:4FEA    F______Source_tasks$__xinit_usCurrentNumberOfTasks$0$0   0C:4FEC    F______Source_tasks$__xinit_xTickCount$0$0   0C:4FEE    F______Source_tasks$__xinit_ucTopUsedPriority$0$0   0C:4FEF    F______Source_tasks$__xinit_ucTopReadyPriority$0$0   0C:4FF0    F______Source_tasks$__xinit_cSchedulerRunning$0$0   0C:4FF1    F______Source_tasks$__xinit_ucSchedulerSuspended$0$0   0C:4FF2    F______Source_tasks$__xinit_ucMissedTicks$0$0   0C:4FF3    F______Source_portable_MemMang_heap_1$__xinit_usNextFreeByte$0$0   0C:4FF5    F___Common_Minimal_integer$__xinit_cTaskCheck$0$0   0C:4FF6    F___Common_Minimal_PollQ$__xinit_cPollingConsumerCount$0$0   0C:4FF7    F___Common_Minimal_PollQ$__xinit_cPollingProducerCount$0$0 And reduced the size of the following #define portMINIMAL_STACK_SIZE        ( ( unsigned portSHORT ) 100 – ( unsigned portSHORT ) portSTACK_START ) The RTOS is working fine on my Atmel 89C51SND1 @ 16Mhz X2 mode(32Mhz) @ 1000Hz timer tick running for 12task + 1 idle task Dunno why have such to happen, but anyway thanks to all~