Yes - that is the approach I would have taken too. Assuming the port is
known to be working, and malloc() is never failing, then I cannot think
of any reason why doing that would cause an issue. Even if the software
timer could not be created it should not crash or prevent you from
stepping into the code. Something is fundamentally wrong somewhere -
maybe you are ending up in a fault interrupt, or something like that.
One thing you could do is try switching to assembly mode and try
stepping into the function in assembly code to see what happens, or at
least how far into the function you get before the debugger lets go.
resetEntry
b _c_int00
undefEntry
b undefEntry
b vPortSWI
prefetchEntry
b prefetchEntry
b _dabort
b phantomInterrupt
ldr pc,[pc,#-0x1b0]
ldr pc,[pc,#-0x1b0]
I set a breakpoint at the call to xTimerCreate in prvIPTask() and disassembled into assembly instructions. I see the following, and when I step through these instructions on the branch to xTimerCreate (EBFFD8F8 BL xTimerCreate) the processor jumps to sys_intvecs.asm as I described in the previous post.
You can see the parameters being loaded onto the stack: R12 has the timer name, R1 (10000) is the timer period, R2 (1) is autoreload, R3 (2) is eARPTimerEvent. I assume R0 is the address of the callback function. I’m not sure of the contents of R12.
I guess I’ll have to contact TI as I can’t find a way to disable the MPU from HALCoGen. The HALCoGen GUI provides a tab for configuring the MPU and it appears as if it can be disabled, but the generated code doesn’t reflect disabling the MPU.
I spent a little time today reading up on the ARM MPU and how HALCoGen configures it. I consulted the TI RM46x TRM, the ARM TRM, and the FreeRTOS documentation on the subject. After all that, I OR’d portPRIVILEGE_BIT with ipconfigUDP_TASK_PRIORITY in the source file FreeRTOS_UDP_IP.c on line #127 where the “prvIPTask” is created. This allowed me to get past creating the timer in prvTask without a prefetch error. I still don’t have the network stack working correctly yet, but I’ve gotten past a significant issue. Can you think of any other issues I should be on the lookout for?
Hi Ray - good call with the portPRIVILEGE_BIT, the stack has probably
never been used with an MPU port before (very few FreeRTOS applications
will use the MPU, whereas very few SafeRTOS applications will not use
the MPU). I take it the code is no longer ending up in the abort
handler, but still you have no communications.
I would suggest the first thing to do would be to ensure the MAC driver
is receiving network data. If you put a break point in the MAC driver’s
interrupt, then send a ping to the board, does the interrupt ever
execute? [sending a ping to an unknown IP address should generate an
ARP message, which should be received by the hardware even if the IP
address is not assigned to the hardware].
I generated the port I’m using with HALCoGen v04.03.00. That version of HALCoGen uses FreeRTOS v8.2.0 - it doesn’t offer a choice about using the MPU.
I’ve just started the debugging process to figure out why the stack isn’t working. One of the things I’m trying to track down is how FreeRTOS handles the IP and MAC addresses. It appears the MAC address is handled correctly but the IP address is reversed somewhere, but I’m not 100% positive about anything yet.
I’m not sure the debugger allows breakpoints in an ISR, but I’ll figure out how to track data flow through the stack. I do have a question about the routine that I had to write: “xNetworkInterfaceInitialise”. It appears this routine can be called more than once - during initialization and whenever the network is determined to be “down”. I made sure the creation of “prvEMACDeferredInterruptHandlerTask” can only be called once, but initializing the hardware can be called more than once.
After looking at the source code HALCoGen generates for the EMAC device driver, I call “EMACHWInit” every time “xNetworkInterfaceInitialise” is called. Is this the correct way to handle that?
I’m not familiar with the code generated by HALCoGen, but if
xNetworkInterfaceInitialise() is only called when the network is down it
will be ok to call EMACHWInit() each time. Assuming EMACHWInit()
initialises the DMA descriptors any packets already held in the
descriptors would be lost of course. Also, if EMACHWInit() enables the
MAC interrupt it would be a good idea to disable the interrupt manually
before EMACHWInit() is called - if it does not do it itself inside the
function.
I’ve got the UDP/IP stack running but I’m having problems. I have the stack configured to use DHCP for now. Using Wireshark I can see a DHCP Discover message go out from the RM46 and an offer comes back from the server. Next I see a DHCP Request go out from the RM46 and an ACK comes back from the server. After that I don’t see any more responses from the RM46.
Eventually the RM46 stops and the debugger reports that the ARM had an exception again. I assume I probably need to review the settings in FreeRTOS_UDP_IP.h. Originally FREERTOS_BIG_ENDIAN was defined to one and I was having very unstable behavior. I changed it to “0” and Set FREERTOS_LITTLE_ENDIAN to one. That seemed to help, but the stack is still very unstable. Do you have a recommended set of settings for configuration compatible with the RM46/48?
I want to use the UDP/IP stack in the simplest way - I just want to stream data on the network. When I’m not doing that I want the stack to not use unnecessary CPU cycles.
OK, I tweaked some of the stack and buffer configuration settings and I was able to get the RM46 to accept a DHCP IP address from the server. I enabled outgoing pings and was able to get the assigned IP address using Wireshark. When I ping the IP address from my host computer I got responses as expected. After that I did an “arp /a” from the host and verified the RM46 showed up with the right IP and Ethernet address.
The RM46 runs a little longer after I tweaked the buffer and and stack configuration settings, but it still dies after just a few minutes. I assume this means I may have a memory leak somewhere (or a stack growth issue). I’m not using dynamic memory allocation to get data from the stack - I use statically allocated buffers and I verified I’m handling the indexing properly. Are you aware of anything in the stack that might be using memory if I didn’t configure it or set it up properly? If not, do you have any suggestions on how I can track down the leak (or stack growth) using TI’s CCS? I have no CLI or other way of seeing into the code.
I would suggest first determining if it really is a memory leak by first defining a malloc failed
hook, and then (if you are using one of heap_1.c, heap_2.c, heap_4.c
or heap_5.c) periodically calling xPortGetFreeHeapSize() to see how much
free space is available.
Also, which memory allocator are you using? If you not using heap_4
then it might be an idea (as an experiment at least) to switch to it as
it should prevent fragmentation of the heap as far as is viable.
OK. It tok me 12 days, but I finally have the FreeRTOS+UDP working on an RM46x HDK using the MPU. I did not implement a “zero copy” version, so it is not very efficient, but it works cooperatively with other tasks and meets my needs.
The last issue I had was putting data on a queue at ISR level. I knew there was a special command to put data on a queue at ISR level, I just hadn’t gotten around to using it. The hooks for malloc and stack overflow were very useful in helping me troubleshoot. Thank you for all your help - I assume I’ll be back as I continue to use FreeRTOS.
Here is my project zipped up - according to my reading on http://interactive.freertos.org I’m supposed to post it on the forum. If I’ve violated a rule, please excuse me, I’m still new to the forum.
Project Parameters:
Target - TI RM46L852ZWT Hercules microcontroller HDK,
Code generation - HALCoGen v0.4.03,
IDE - Code Composer Studio version 6.1.0.00104,
Compiler - TI v5.2.3
When I generated code with HALCoGen, I deleted their “os_heap.c” file and replaced it with FreeRTOS+UDP “heap_4.c”
This is a simple implementation - it is not a zero copy implementation.
I did not “tune” or otherwise optimize the task stack sizes or heap size.
The purpose of the LED blinky tasks is to convince myself that I could run multiple tasks cooperating with each other while running the UDP/IP stack simultaneously
The biggest issue I ran into was that I had to ‘OR’ in the “portPRIVILEGE_BIT” with the task priorities to get everything working correctly with the ARM MPU