About porting FreeRTOS to general 80C51 MCU

nobody wrote on Thursday, March 10, 2005:

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~

nobody wrote on Thursday, March 10, 2005:

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

nobody wrote on Thursday, March 10, 2005:

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?

nobody wrote on Friday, March 11, 2005:

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.

nobody wrote on Friday, March 11, 2005:

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).

rtel wrote on Friday, March 11, 2005:

>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.

nobody wrote on Friday, March 11, 2005:

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.

nobody wrote on Sunday, March 13, 2005:

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

rtel wrote on Sunday, March 13, 2005:

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.

nobody wrote on Sunday, March 13, 2005:

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~

nobody wrote on Sunday, March 13, 2005:

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

nobody wrote on Sunday, March 13, 2005:

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(;:wink:
    {
        prvToggleOnBoardLED2();
        vTaskDelay(0xff);
    }
}
       

nobody wrote on Tuesday, March 15, 2005:

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~

nobody wrote on Tuesday, March 15, 2005:

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?)

nobody wrote on Tuesday, March 15, 2005:

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.

rtel wrote on Tuesday, March 15, 2005:

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.

nobody wrote on Tuesday, March 15, 2005:

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…

nobody wrote on Tuesday, March 15, 2005:

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 :slight_smile:

nobody wrote on Tuesday, March 15, 2005:

"*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 :slight_smile:

and *(*pxCurrentTCB) would be the stack size right?.. I should expected with default setting, I should get the value 17? thank you~

nobody wrote on Tuesday, March 15, 2005:

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 :frowning: . Some parts I would use some debug marco to swap out the whole byte for checking…