FreeRTOS+UDP demo and LPCOpen

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

FreeRTOS+UDP demo and LPCOpen

1,518 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by tvink on Mon Jan 19 12:44:33 MST 2015
Hi,

I have built and can debug the freertos_tcpecho code in LPCOpen.  It pings as expected and seems to be working properly.


Now I am looking at the  FreeRTOS+UDP demo on the freeRTOS page and they discus the USB console and the CLI interface using a terminal program. 

Should I get a console port with the freertos_tcpecho thingie in LPCOpen?  I do not see any COM ports in device manager when running the code.  Is this only available with the app on the freeRTOS page.  ( I was hoping that the  console port was available any time you run an RTOS project? )   Maybe it is just disabled in the LPCOpen code?

Thanks
Labels (1)
0 Kudos
23 Replies

1,206 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by www.FreeRTOS.org on Fri Feb 06 12:58:00 MST 2015
...I think it is probably a problem with the USB driver - we have commented on two work arounds already in this thread to make it behave.  First the one that has the "_RB_ workaround" comment next to it, and the second being the one tick delay that was already inserted in the code but, according to your experimentation, was not sufficient.

[EDIT]I should point out it is *not* the LPCOpen driver, which I have used in later examples, and found to be reliable[EDIT]

0 Kudos

1,206 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by tvink on Fri Feb 06 11:57:43 MST 2015
Below is the main console task in CDCCommandConsole.c with some "vTaskDelay( 1 )" added.

I played around with this proceedure a lot commenting stuff out and back in, looking for memcpy() that may have run away, etc.  Everything looked good except it started feeling like timing somehow. Even with the main command processing commented out it would fail after I pressed CR on the CLI with only a few tries.  It never failed with just holding an alpha key down on the CLI.

I noticed a 1 tick delay after one of the USB_WriteEP() calls.
So I put a similar delay after each USB_WriteEP() call in this procedure.

I have not seen a failure since.  200+ runs of task-stats and 200+ runs of ip-config.  These would fail after only a few.

What do you think?

















static void prvCDCCommandConsoleTask( void *pvParameters )
{
char cRxedChar;
uint8_t ucInputIndex = 0;
char *pcOutputString;
static char cInputString[ cmdMAX_INPUT_SIZE ], cLastInputString[ cmdMAX_INPUT_SIZE ];
BaseType_t xReturned;

( void ) pvParameters;

/* Obtain the address of the output buffer.  Note there is no mutual
exclusion on this buffer as it is assumed only one command console
interface will be used at any one time. */
pcOutputString = FreeRTOS_CLIGetOutputBuffer();

/* Initialise the virtual com port (CDC) interface. */
prvSetupUSBDrivers();

/* Send the welcome message.  This probably won't be seen as the console
will not have been connected yet. */
USB_WriteEP( CDC_DEP_IN, ( uint8_t * ) pcWelcomeMessage, strlen( pcWelcomeMessage ) );
vTaskDelay( 1 ); // 777
for( ;; )
{
/* No characters received yet for the current input string. */
cRxedChar = 0;

/* Only interested in reading one character at a time. */
cRxedChar = cGetCDCChar();

if( xSemaphoreTake( xCDCMutex, cmdMAX_MUTEX_WAIT ) == pdPASS )
{
/* Echo the character back. */
USB_WriteEP( CDC_DEP_IN, ( uint8_t * ) &cRxedChar, sizeof( uint8_t ) );
vTaskDelay( 1 ); // 777
/* Was it the end of the line? */
if( cRxedChar == '\n' || cRxedChar == '\r' )
{
/* Just to space the output from the input. */
USB_WriteEP( CDC_DEP_IN, ( uint8_t * ) pcNewLine, strlen( pcNewLine ) );
vTaskDelay( 1 ); // 777
/* See if the command is empty, indicating that the last command is
to be executed again. */
if( ucInputIndex == 0 )
{
/* Copy the last command back into the input string. */
strcpy( cInputString, cLastInputString );
}

/* Pass the received command to the command interpreter.  The
command interpreter is called repeatedly until it returns pdFALSE
(indicating there is no more output) as it might generate more than
one string. */
do
{
/* Get the next output string from the command interpreter. */
xReturned = FreeRTOS_CLIProcessCommand( cInputString, pcOutputString, configCOMMAND_INT_MAX_OUTPUT_SIZE );

/* Write the generated string to the CDC. */
USB_WriteEP( CDC_DEP_IN, ( uint8_t * ) pcOutputString, strlen( pcOutputString ) );
vTaskDelay( 1 ); // 777 was 1

} while( xReturned != pdFALSE );

/* All the strings generated by the input command have been sent.
Clear the inputstring ready to receive the next command.  Remember
the command that was just processed first in case it is to be
processed again. */
strcpy( cLastInputString, cInputString );
ucInputIndex = 0;
memset( cInputString, 0x00, cmdMAX_INPUT_SIZE );
USB_WriteEP( CDC_DEP_IN, ( uint8_t * ) pcEndOfOutputMessage, strlen( pcEndOfOutputMessage ) );
vTaskDelay( 1 ); // 777 put a delay here too
}
else
{
if( cRxedChar == '\r' )
{
/* Ignore the character. */
}
else if( cRxedChar == '\b' )
{
/* Backspace was pressed.  Erase the last character in the
string - if any. */
if( ucInputIndex > 0 )
{
ucInputIndex--;
cInputString[ ucInputIndex ] = '\0';
}
}
else
{
/* A character was entered.  Add it to the string
entered so far.  When a \n is entered the complete
string will be passed to the command interpreter. */
if( ( cRxedChar >= ' ' ) && ( cRxedChar <= '~' ) )
{
if( ucInputIndex < cmdMAX_INPUT_SIZE )
{
cInputString[ ucInputIndex ] = cRxedChar;
ucInputIndex++;
}
}
}
}

/* Must ensure to give the mutex back. */
xSemaphoreGive( xCDCMutex );
}
}
}
0 Kudos

1,206 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by www.FreeRTOS.org on Fri Feb 06 01:41:51 MST 2015
Are you talking about in CDCCommandConsole.c?  If so I can see three calls to take the mutex and three calls to give the mutex - one pair in three separate functions.  Just search the file for xCDCMutex to see where it is used.
0 Kudos

1,206 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by tvink on Thu Feb 05 15:19:11 MST 2015
I was thinking you might be RB...

I dont think the problem is actually failing to get the mutex.  I think that that is a consequence of an earlier failure.  The last time I pressed run at the return point of the procedure, I was expecting the CLI to update with another pass of ip-config. Instead all that displayed was the cursor moving to beginning of the current line.  So the fail has already happened by this point.  When the procedure is again called, then the code is already doomed and ets stuck blocked in the RX semaphore.  I think.

Another thing.... In the RX part of the function, the xSemaphoreTake() does not have a xSemaphoreGive() following it... like the TX one does.  Should there be a Give here too?  ( I tried adding one but it did not seem to fix the problem )

Tony
0 Kudos

1,208 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by tvink on Thu Feb 05 15:19:10 MST 2015
I was thinking you might be RB...

I dont think the problem is actually failing to get the mutex.  I think that that is a consequence of an earlier failure.  The last time I pressed run at the return point of the procedure, I was expecting the CLI to update with another pass of ip-config. Instead all that displayed was the cursor moving to beginning of the current line.  So the fail has already happened by this point.  When the procedure is again called, then the code is already doomed and ets stuck blocked in the RX semaphore.  I think.

Another thing.... In the RX part of the function, the xSemaphoreTake() does not have a xSemaphoreGive() following it... like the TX one does.  Should there be a Give here too?  ( I tried adding one but it did not seem to fix the problem )

Tony
0 Kudos

1,208 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by www.FreeRTOS.org on Thu Feb 05 14:12:00 MST 2015
>I saw in some of the documentation that stack protection only works on non-segmented memory and since the LPC1837 has four segments

The comment about segmented memory refers to base/offset architectures such as the 8086 family.  Although the LPC1837 has more than one bank of RAM, they are all in the same flat 32-bit memory space, so in this case considered to be in the same segment.  In other words - the stack overflow checking should be working fine, but it doesn't sound like that is your problem anyway.

However, what I have just realised (remembered!) is the CLI is not using a UDP port for its input and output, but a USB CDC.  So it is not the UDP stack that is not responding, but the USB port.  I can't remember where the USB stack came from, I seem to recall NGX, but it has a Keil copyright notice in the files.  We have some other demos somewhere that use the USB CDC driver that is actually in the ROM of the chip, but that doesn't help here.

From your description it sounds like it is attempting to obtain the mutex, but failing, is that correct.  The block time is 200m, so if it does not obtain the mutex within that time it should just give up and return to wait for more characters.  There isn't a path through that code that would result in the mutex not being returned.

If it is not the mutex that is causing what you are seeing maybe it is in the USB driver.  I have just looked at the function USB_WriteEP() which has a comment in it saying:

EDIT:  I can't get the code to post correctly, I think because it has "less than" characters in it, which the forum is taking as a URL tag, even when I escape it.  This is just the comment on the line I was referring to, you will see all the code if you look at the function:  /*_RB_ Fix for hang here. */

(I'm RB, by the way) which makes me think I had an issue at some time too.

Regards.
0 Kudos

1,208 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by tvink on Thu Feb 05 13:40:13 MST 2015
Hi again,

I had stack overflow protection turned ON.  ( It is ON as your demo ships )
However I never hit the break point that I placed on the handler so I dont think it is stack overflow.  At least not a detected one.


I saw in some of the documentation that stack protection only works on non-segmented memory and since the LPC1837 has four segments, I thought I would turn the feature OFF. 
It made no difference.


I set breaks points before and after the semaphores in the cGetCDCChar() procedure in CDCCommandConsole.c and watched the code execute.
For this I typed "ip-config" and pressed ENTER to repeat the command in the CLI window.
When it finally failed, the cGetCDCChar() procedure returned normally but the CLI window did not update as it had done on the successful passes.
Then pressing ENTER in the CLI did take me back into the 1st break point in cGetCDCChar() but when I stepped over the RX semaphore it stayed blocked.  No more response from the CLI input.
So It seemed to go wrong on the last TX to the CLI but then blocked permanently on the next RX.

I am getting valuable experience with lpcExpresso and the RTOS with this experience but I think I need to get this working reliably.
Would you be able to take a look at my project?  It is essentially the UDP+CLI demo with the changes discussed above.

Thanks, Tony





0 Kudos

1,208 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by www.FreeRTOS.org on Tue Feb 03 08:41:51 MST 2015
For the few times task-stats does run does it show any of the stack high water marks getting close to 0?  The lower the number the closer it is to overflowing the stack.  Do you have stack overflow protection turned on? http://www.freertos.org/Stacks-and-stack-overflow-checking.html

You could also try placing a break point in the CLI task to see if it is receiving the data.  If it is, and is generating a reply, you can step through the code to see where it goes wrong.

The task-stats commands it a bit brutal and keeps interrupts disabled for quite a long time, so it not really intended for production code, just as a debugging aid.

Please ensure to post your project to the FreeRTOS interactive site: http://interactive.freertos.org

0 Kudos

1,208 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by tvink on Tue Feb 03 08:26:49 MST 2015
Hi,

I have my FreeRTOS+UDP up and running on my LPC1837 board.  Yay!

I set the memory size of the 1st segment as you suggested. 
I have: #define configTOTAL_HEAP_SIZE ( ( size_t ) ( 14336 ) ) 
which is a few bytes less than where I get compile errors for bss segment fitting.

I also set up that last segment of SRAM in the table handed to vPortDefineHeapRegions();

I am using TeraTerm to look at the CLI.  I get an IP addres from the command ip-config.  I can ping the LPC1837 board from my PC which is on the same network and it  never fails to respond.

However, I am experiencing some incorrect behavior which I am wondering if it has to do where I am calling vPortDefineHeapRegions( xHeapRegions_LPC1830 ), or where I placed const HeapRegion_t xHeapRegions_LPC1830[] =.

The CLI seems to hang rather frequently.  For example if I issue the command "stat-tasks" repetitively.  ( slowly, once a second ) After a few tries ( less than 10 ) the CLI hangs up.  I can not get it to communicate except for power cycling the board.  This happens with other commands too.  So I am wondering if the CLI is overflowing  a stack?  When the CLI hangs, the board continues to respond to pings. 

I kept the debugger up during one of these and it did not show anything bad...  but I am not sure where to look.  It did not emit any messages in the console, etc.

I tried putty selecting the serial port and it behaves the same way.

The blue light keeps flashing.  ( although I think it did stop one time )

Any insight as to where to look?

Thanks


P.S. I am using Comm Echo to echo the UDP messages but am not seeing anything happen.  This may be my setup issue, but thought I would mention it.  I have Comm Echo allowed in my firewall.  Am just now installing Wireshark so I can see if I am receiving the UDP frames.  My PC is running 64 bit Win 7.
0 Kudos

1,208 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by tvink on Fri Jan 30 11:04:42 MST 2015
Thanks, it does make sense.

The LPC1837 does have an additional 16kB up at 0x2000C000. I was planning on asking about that after I got everything working.

Thanks

Oh and concerning the malloc()...  I noticed that printf-stdarg.c is already part of the project.
0 Kudos

1,208 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by www.FreeRTOS.org on Thu Jan 29 14:53:18 MST 2015
The linker script will tell the linker which memory region to place the .data and .bss sections.  That will take up some room in one of the RAM blocks, but you don't know how much room until your build your application.  As you don't know how much room it will take, you don't know how much of that RAM block you can give to the FreeRTOS heap by including it in the HeapRegion_t structure.  Therefore I did not explicitly allocate any RAM in the first RAM block (which is the RAM block the linker script placed the .data and .bss) in the HeapRegion_t.  Instead I declared a variable:

ucHeapBlock1[ configTOTAL_HEAP_SIZE ];

The linker will place the RAM allocated to that variable in the .bss section, which in turn it will place in the first block of RAM.

Now I find out how much RAM I can use from that block by playing with the size of configTOTAL_HEAP_SIZE.  If it is set too big the application will not link because it will run out of RAM in the .bss block.  When it fails to link it will tell you how much more memory it would have required in order to link.  Adjust configTOTAL_HEAP_SIZE down by that amount, and the application will link.

By doing that the heap regions, as defined in the structure, will have *all* of the RAM from the blocks that are not used by the linker, and as much as possible from the first block of RAM, which is used by the linker.  The memory from the first block is the memory in the ucHeapBlock1 array - so that appears in the structure.  The memory in the other blocks is just hard coded to grab all the RAM in that block.

I think in fact the LPC1830 has yet another block of RAM higher up the memory that is not in the xHeapRegions_t structure I posted.

Does that make sense?

----

Compiling in printf-stdarg.c will not direct malloc calls to pvPortMalloc() - although there are linker command line options you can use to achieve that if you want to.  What it does do is direct any calls to sprintf() type functions to the version in printf.starg.c, preventing any such function coming in from the C library.  The versions in the C library will call malloc in unexpected places, so preventing the ones from the library being linked into your project prevents malloc being called when you don't expect it to.  In fact one of the libraries in LPCXpresso (can't remember if it is Newlib nano or Redlib) will cause malloc to be called *before* you even reach main().

0 Kudos

1,208 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by tvink on Thu Jan 29 13:32:39 MST 2015
Your reply above was very helpful but unfortunately I do not have enough trained neurons to connect all the dots by myself!

I placed the heap descriptors in main.c above the function calls and put the vPortDefineHeapRegions() as the first call in main().
My region descriptors look like this:

const HeapRegion_t xHeapRegions_LPC1830[] =
{
{ ( uint8_t * ) 0x10000000,   ( 32UL * 1024UL ) },
{ ( uint8_t * ) 0x10080000,   ( 40UL * 1024UL ) },
{ ( uint8_t * ) 0x20000000,   ( 32UL * 1024UL ) },
{ ( uint8_t * ) 0x20008000,   ( 16UL * 1024UL ) },
{ NULL, 0 }  /* Terminates the array. */
};

I am confused about the start address and size for the 1st descriptor.  In your example you used a variable to locate the start of the 1st region.  The lpc1837 first SRAM starts at 0x10000000 so I just used that.  Is that OK?  Is there something that I need to be aware of that would move the start address up from the actual SRAM start? 

I understand that I need to set the size of the 1st region as small as I can.  How do I know how small that is.  Would I use the smallest value that does not produce compiler errors?  Do I set it to some test value and then run something to see if it crashes? 

I think I understand what you are saying about compiling in the printf-stdarg.c file.  If it is linked into the project all malloc() calls will be intercepted and sent to pvPortMalloc(), yes?

Last question.  You mention the linker script.  Being new to lpcXpresso I could be completely wrong but would you be referring to the  build properties, MCU settings, where the memory details are defined.  ( the items that I was incorrectly modifying several posts ago )   Would I set the size of the SRAM blocks in there?  I would set the first block to the same small value that would be used in the 1st descriptor.  I would set the other ones to ZERO.  Is that correct?

Thanks










0 Kudos

1,208 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by tvink on Tue Jan 27 14:55:04 MST 2015
Thanks!
0 Kudos

1,208 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by www.FreeRTOS.org on Mon Jan 26 14:08:39 MST 2015
The biggest thing in the bss will be the FreeRTOS heap.

The way I get around this on the LPC is to use heap_5.c (see the link above) and set the heap in the linker script to as close to 0 as you can get it.  You may however find that the compiler libraries call malloc(), and that will break things if the heap in the linker is near zero - to prevent that also build in the printf-stdarg.c file you will find multiple copies of in the FreeRTOS/Demo sub-directories of the main FreeRTOS download.

When using heap_5.c you can define each memory region separately, then create have the FreeRTOS heap span across all the regions.  It is just like heap_4.c but the memory it uses does not have to be in a contiguous block.  That way you can access all the RAM for the task heaps and network buffers without them appearing in the linker script.

The FreeRTOS+TCP demo does it like this.  The linker only knows about the lowest block of RAM on the LPC.  Then there is the following structure:

const HeapRegion_t xHeapRegions_LPC1830[] =
{
{               ucHeapBlock1,   configTOTAL_HEAP_SIZE }, /* See definition above. */
{ ( uint8_t * ) mainRAM_LOC_40,   ( 40UL * 1024UL ) },
{ ( uint8_t * ) mainRAM_AHB_32,   ( 32UL * 1024UL ) },
{ ( uint8_t * ) mainRAM_AHB_16,   ( 16UL * 1024UL ) },
{ NULL, 0 }  /* Terminates the array. */
};


which actually works on the LPC1830 and LPC1837 (? might have that number wrong).  ucHeapBlock1 is in the bottom block of RAM, the one the linker knows about, so configTOTAL_HEAP_SIZE just dimensions what comes from that lowest block.  The other three regions are not known to the linker so you can do with them as you will.  You must use this structure to initialise the heap before any FreeRTOS calls are made:

vPortDefineHeapRegions( xHeapRegions_LPC1830 );


0 Kudos

1,208 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by tvink on Mon Jan 26 13:14:51 MST 2015
Hi again,

I have been away for a couple of days and now have had some time do devote to this...


I see where I went wrong with the LPC1837.  I edited the MCP memory map which made the project build OK but since I was telling the tool that there was a 96kb segment at 0x10000000 of course it would fail when run.  There is only a 32kB segment at that location in the LPC1837.

Going back and making the MCU memory map correct for the LPC1837 hardware I get build errors indicating that the '.bss' section will not fit in the reagion RamLoc32.

So I need to tell whatever is making the bss section to only use 32kB.  ( or use the other SRAM region which is 40kB ).  I can track this down to a section in the file "FreeRTOS_UDP_Demo_Debug.ld" which is a generated file and should not be edited.  The auto comments in the file indicate that this is setup automatically by the linker.

So now I am snarled up in the internals of FreeRTOS_UDP and the LPCXpresso environment.  Not the place I want to be when just trying to learn the MPU, the tool, and the RTOS.

Please Help.  What do I need to do to get the demo to run on the LPC1837? 

Thanks


0 Kudos

1,208 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by www.FreeRTOS.org on Wed Jan 21 13:52:41 MST 2015
This question was asked on the FreeRTOS forum just yesterday - I assumed it was from you.  In any case, there is an answer here:
https://sourceforge.net/p/freertos/discussion/382005/thread/7e08dd08/

0 Kudos

1,208 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by tvink on Wed Jan 21 11:51:30 MST 2015
I am sorry.  I completely bollixed up this posting.   I started out right.  I am trying to build the FreeRTOS_UDP project.  Somewhere in the middle I started calling it FreeRTOS+CLI... brain fart.  I am only working on FreeRTOS+UDP.  This project has some CLI responses built in as shown in the video on the FreeRTOS site.

Here is the question I meant to ask a couple of postings ago...

- Will the FreeRTOS+UDP project work on an LPC1837?  ... by only changing the MPU choice and memory map?


Sorry about the confusion,
Tony
0 Kudos

1,208 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by www.FreeRTOS.org on Wed Jan 21 07:13:00 MST 2015
>  I thought it by default used the USB COM channel. Is that not the case.

Please read the FreeRTOS+CLI documentation - a link to which has already been posted.

> Didn't realize you guys were on line here too

The FreeRTOS support forum is the correct place to post questions about FreeRTOS.

The LPCWare support forum is the correct place to post questions about LPCOpen.

Sometimes there is a cross over.
0 Kudos

1,208 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by tvink on Wed Jan 21 07:05:10 MST 2015
Thanks,

I have to spend a couple of days on another project so I'll set this aside for now....  but one question about the CLI.  I thought it by default used the USB COM channel.  Is that not the case.


On a related issue, I posted the same "does it work on 1837" question on your sourceforge forum.  Did I do a bad by duplicating?   Didn't realize you guys were on line here too.

Thanks,
Tony
0 Kudos

1,208 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by www.FreeRTOS.org on Tue Jan 20 14:51:42 MST 2015
FreeRTOS+CLI itself has no hardware dependencies, and will run on any device.  You do however have to provide input and output for the CLI, and that naturally does have a hardware dependency.  We have examples that use a UART, a UDP port, a TCP port (in the lab) and USB CDC drivers for character input and output - I can recall which the demo you are talking about is using.

The FreeRTOS+TCP project we have running on both the LPC1830 and LPC1835 Xplorer boards from NGX, with the only changes being to the target MCU and associated memory map.
0 Kudos