Quality RTOS & Embedded Software

 Real time embedded FreeRTOS RSS feed 
Real time embedded FreeRTOS mailing list 
Quick Start Supported MCUs PDF Books Trace Tools Ecosystem TCP & FAT Training




Loading

Microblaze Demo on ML405

Posted by Erik Andresen on May 8, 2008
Hello,

I tried to run the FreeRTOS v5.0 Microblaze Demo on my Xilinx ML405 board, however it did not work as expected - no blinking LEDs. In my serial terminal I get once the string "ABCDEFGHIJKLMNOP" - and nothing more.

Since the ML405 is a bit different to the ML403, so I had to edit the system.ucf and change the FPGA type for the project.

I'm using EDK & ISE 9.1

Any ideas what does went wrong here?

RE: Microblaze Demo on ML405

Posted by Erik Andresen on May 15, 2008
Could the problem be, that the compiler is removing the "or r0, r0, r0" from portasm.s?

RE: Microblaze Demo on ML405

Posted by Richard on May 20, 2008
The Microblaze port was developed using version 8.x of the EDK. Although we now have version 10.x we have not yet updated the demo application configuration.

When you open the project in your 9.x tools it should attempt to update the project to that standard, and update the used IP to the 9.x versions. It might be that the problem is occurring during this process.

Alternatively, as I recall the Microblaze port requires the timer interrupt vector to be setup manually rather than using the vector table setup by the EDK. It is quite likely that the timer interrupt (RTOS tick) is not executing. If this is the case each task will only execute up to the point that it blocks, and then never unblock. Can you verify that the RTOS tick interrupt is executing? Also, can you run the application in the debugger to see where it ends?

Regards.

RE: Microblaze Demo on ML405

Posted by Erik Andresen on May 22, 2008
First, thanks for your answer.

Yes, the 9.x Version did attempt to update the project without throwing an error.
Still the might me an undetected error...

The problem actually seems to be really odd:

First of all, I reduced the main() to
prvSetupHardware();
vStartLEDFlashTasks( mainLED_TASK_PRIORITY );
vTaskStartScheduler();

Next I added a
xil_printf("start\r\n");
at the very top of the file.

Executing this, I ended up with the demo application constantly printing "start" on the serial, again and again.
So it looks to me, that the whole thing is crashing sowewhere.

About debugging:
I'm loosing the program somewhere in
vStartFirstTask();
Unfortunately, the insight debugger seems unable to step into this function, since it is not written in C.

However, stepping in XMD seems to help.
The last comment I see exeuted before it starts back into the main is
brlid r15, -10164, which is the call for xTaskGetTickCount() in flash.c, portTASK_FUNCTION(vLEDFlashTask, pvParameters).

One additional information:
The system doesn't seem to crash when I remove the call to prvSetupTimerInterrupt() in port.c, xPortStartScheduler().

So the conclusion I jump to is, that the system does crash, as soon as the Interrupt gets called.
Unfortunately I have no idea why.

RE: Microblaze Demo on ML405

Posted by Richard on May 22, 2008
You should be able to debug the asm code from within Insight. I have been doing this recently on the PPC port, also using Insight.

In the Insight interface there are three drop down lists. The left list contains all the files, the middle list the functions contained within the file. In the left drop down list you should be able to select portasm.s, then once selected in the middle drop down list you should be able to select __FreeRTOS_interrupt_handler to take you to the start of the ISR handler function. You can then put a break point on the entry to the ISR. As this is an asm file you should be able to leave the right drop down list on Source.

This is complicated somewhat by the fact that the ISR starts with a macro, the first instruction after this is ori r31, r31, 2, that might be the best point to place the break point to see if it gets hit. If it never gets that far then something in the portSAVE_CONTEXT macro must be amiss.

Regards.

RE: Microblaze Demo on ML405

Posted by Erik Andresen on May 22, 2008
Btw, are you sure you developed the Microblaze Port under 8.x?
The system.xmp says 7.1.

I finally found a 7.1 here and installed it. It didn't want to compile the project - too big for target.
Only after installing the updates I was to able to compile _and_ finally get FreeRTOS to run as expected.
My Leds do finally blink - yeah :)
Xilinxs tools seem to be really funny.

Anyway, would be good if we could get the whole thing working on a recent EDK.

RE: Microblaze Demo on ML405

Posted by Erik Andresen on May 22, 2008
Back to EDK 9.1:
I'm afraid portasm.s is not in the list of files I can select.

I was unable to see ori r31, r31, 2 executed in XMD. It seems to directly jump from the vLEDFlashTask() back to main().

I also tried to set a breakpoint to __FreeRTOS_interrupt_handler in XMD, but was able to get a hit.

RE: Microblaze Demo on ML405

Posted by Erik Andresen on May 22, 2008
I think I found the root of all evil: http://www.xilinx.com/support/answers/24988.htm

Might be the point.

RE: Microblaze Demo on ML405

Posted by Richard on May 22, 2008
Thats a good find. I would appreciate a copy of any changes you make to fix this.

Regards.

RE: Microblaze Demo on ML405

Posted by Erik Andresen on May 26, 2008
If I can fix this, you will get the patch, of course.

However right now I'm still trying to understand the original idea.
For the Microblaze port you use two interrupt routines? -I found port.c vTickISR() and portasm.s __FreeRTOS_interrupt_handler() and I can't really explain why there are two.

I looked through your other FreeRTOS ports, especially the Atmel AVR one and it uses only one interrupt routine.

RE: Microblaze Demo on ML405

Posted by Richard on May 26, 2008
I was looking at this a bit yesterday. I have the same thing as you, after allowing the project to update to V10.1 of the EDK I can compile and download but the code does not run correctly. What I found is that the code does actually run, and switch between tasks, but as soon as a timer tick interrupt comes in the system resets.

It looks like (as per your previous email) the way interrupts are setup has completely changed between versions of the EDK - what a pain.

It might be that the PPC405 port can offer some clues as this was generated in V10.1 of the EDK - this has a function vPortInitiliazeInterruptController() in its port.c file. The problem being that the library functions differ somewhat between the Microblaze and the PPC405.

Also, looking through the peripheral test code automatically generated by the EDK with a new project, it looks like there are more setup functions require to be called before the interrupt controller is in a state whereby it can be used successfully. I have just stepped through the interrupt controller self test code to find these, I have not actually looked up exactly what they do.

__FreeRTOS_interrupt_Handler is the interrupt handler. From memory it replaces the interrupt handler installed by the crt0 code. Its job is to save the task context, determine which peripheral caused the interrupt, then just to the correct handler for that peripheral. vTickISR() is one of the functions it jumps to so vTickISR() is not the entry point for an interrupt.

Regards.

RE: Microblaze Demo on ML405

Posted by Erik Andresen on May 26, 2008
Getting the interrupt to occure is easy. The example code in this document http://www.xilinx.com/support/documentation/application_notes/xapp778.pdf (last page) is close to what we need.

What I'm stuck is what exactly todo in the isr.

I mean the basics are clear.
Something like...

portSAVE_CONTEXT()
vTaskIncrementTick()
clear_timer_interrupt()
#if configUSE_PREEMPTION == 1
vTaskSwitchContext()
#endif
portRESTORE_CONTEXT()

...just have to get it right.

RE: Microblaze Demo on ML405

Posted by Erik Andresen on May 26, 2008
btw right now I'm using this code to setup the interrupt. I hope this board keeps the source in a readable format...

void setup_isr(void) {
/* Register External interrupt handler */
XIntc_RegisterHandler(XPAR_OPB_INTC_0_BASEADDR, XPAR_OPB_INTC_0_OPB_TIMER_1_INTERRUPT_INTR, timer_int_handler, (void *)XPAR_OPB_TIMER_1_BASEADDR);

/* Start the interrupt controller */
XIntc_mMasterEnable(XPAR_OPB_INTC_0_BASEADDR);

/* Set the number of cycles the timer counts before interrupting */
XTmrCtr_mSetLoadReg(XPAR_OPB_TIMER_1_BASEADDR, 0, configCPU_CLOCK_HZ / configTICK_RATE_HZ);

/* Reset the timers, and clear interrupts */
XTmrCtr_mSetControlStatusReg(XPAR_OPB_TIMER_1_BASEADDR, 0, XTC_CSR_ENABLE_TMR_MASK | XTC_CSR_ENABLE_INT_MASK | XTC_CSR_AUTO_RELOAD_MASK | XTC_CSR_DOWN_COUNT_MASK );

/* Enable timer and uart interrupts in the interrupt controller */
XIntc_mEnableIntr(XPAR_OPB_INTC_0_BASEADDR, XPAR_OPB_TIMER_1_INTERRUPT_MASK);

/* Enable MicroBlaze interrupts */
microblaze_enable_interrupts();
}

RE: Microblaze Demo on ML405

Posted by Richard on May 26, 2008
You probably know all this already, but just in case.

The previous version installed __FreeRTOS_interrupt_handler as the interrupt handler, with the following code:

__FreeRTOS_interrupt_handler:
portSAVE_CONTEXT
/* Entered via an interrupt so interrupts must be enabled in msr. */
ori r31, r31, 2
/* Stack msr. */
swi r31, r1, 8
/* Stack the return address. As we entered via an interrupt we do
not need to modify the return address prior to stacking. */
swi r14, r1, 76
/* Now switch to use the ISR stack. */
lwi r3, r0, pulISRStack
add r1, r3, r0
bralid r15, vTaskISRHandler
or r0, r0, r0
portRESTORE_CONTEXT

This is defined in portasm.s. vTaskISRHandler then found the source of the interrupt and ran the correct handler, in the case of the timer interrupt this was vTickISR(). When vTickISR() is called the context has already been saved by __FreeRTOS_interrupt_handler, so this does not need to happen again. vTickISR() is therefore (in port.c):

void vTickISR( void *pvBaseAddress )
{
unsigned portLONG ulCSR;

/* Increment the RTOS tick - this might cause a task to unblock. */
vTaskIncrementTick();

/* Clear the timer interrupt */
ulCSR = XTmrCtr_mGetControlStatusReg(XPAR_OPB_TIMER_1_BASEADDR, 0);
XTmrCtr_mSetControlStatusReg( XPAR_OPB_TIMER_1_BASEADDR, portCOUNTER_0, ulCSR );

/* If we are using the preemptive scheduler then we also need to determine
if this tick should cause a context switch. */
#if configUSE_PREEMPTION == 1
vTaskSwitchContext();
#endif
}


So provided the timer interrupt is installed correctly into the interrupt controller array of handlers, it should work.

Regards.

RE: Microblaze Demo on ML405

Posted by Erik Andresen on May 26, 2008
aah, so vTaskISRHandler() is the one that should call vTickISR().
So in theory - since I only have one interrupt source active right now - with __FreeRTOS_interrupt_handler as my ISR to replace all the contents of vTaskISRHandler() with a single call to vTickISR() and it should work, right?

void vTaskISRHandler( void )
{
vTickISR(NULL);
}

just for testing.

RE: Microblaze Demo on ML405

Posted by Richard on May 26, 2008
If this is the only interrupt then I think something close to that should work. Looking at the existing vTaskISRHandler() handler it also acks the interrupt controller, so you would have to add that too.

Regards.

RE: Microblaze Demo on ML405

Posted by Erik Andresen on May 26, 2008
hmm. This results in a _vector_sw_exception in insight.

The problem might be the stack since __FreeRTOS_interrupt_handler() doesn't have an argument, while it should have one
since the template for an isr is void ext_int_handler(void * baseaddr_p) {}

RE: Microblaze Demo on ML405

Posted by Richard on May 26, 2008
I'm not sure that __FreeRTOS_interrupt_handler should have an argument, it is a replacement for the Xilinx provided _interrupt_handler, which is installed by crt0.s.

Handler functions called by __FreeRTOS_interrupt_handler (like vTickISR()) should have an argument.

Regards.

RE: Microblaze Demo on ML405

Posted by Erik Andresen on May 26, 2008
After having read the Xilinx appnote on Interrupts I found no mention off crt0.s in it. My guess is that this file is no longer used.
In fact I've created a new base project for freertos and crt0.s has not been created with it.
However the ISR itself is called.

So my guess is crt0.s is no longer used, same with most parts of vTaskISRHandler(), but can't say it for sure since I was unable to find documentation for the old style Interrupts.

The new way, using XIntc_RegisterHandler() expects a function to be ISR that has an argument.

RE: Microblaze Demo on ML405

Posted by Richard on May 26, 2008
Looking at the PowerPC port (which was created using EDK V10.1) I see that the Xilinx standard interrupt handler calls vPortISRHandler() which is where the interrupt source is located (equivalent to the Microblaze vTaskISRHandler()) and sure enough vPortISRHandler() has a parameter. The parameter is the interrupt controller that is being serviced. As in the PowerPC demo only one interrupt controller is included the parameter is ignored.

The crt0 file is included in the demo code itself, presumably it was copied there automatically when the V7.1 EDK generated the project structure. The PowerPC demo does not include a crt0 file. Startup code must exist somewhere however - I have just searcehd a new Xilxix created Microblaze project and cannot find it. Main() does exist in a library though, so maybe that is where they have put it. Looks like you are right in that new project are not explicity copying a crt0 file.

Unfortunately I have not got the space time to read through the app notes and try running a virgin project today :o(

Regards.

RE: Microblaze Demo on ML405

Posted by Erik Andresen on May 27, 2008
ok, the problem with the new interrupt setup code is, that xintc_l.c, XIntc_DeviceInterruptHandler() is the real new interrupt handler which will call the FreeRTOS one, so

XIntc_DeviceInterruptHandler()
1. will do some stuff
2. call __FreeRTOS_interrupt_handler()
3. will do some other stuff

So if I understand it correctly. Instead of jumping from portRESTORE_CONTEXT (rtid/rtsd) directly back to code, freertos would "only" have edit the stack...is that even possible?

RE: Microblaze Demo on ML405

Posted by Richard on May 27, 2008

> ok, the problem with the new interrupt setup code is, that xintc_l.c,
> XIntc_DeviceInterruptHandler() is the real new interrupt
> handler which will
> call the FreeRTOS one, so


So this is the function installed on the 0x10 vector. It might be possible to replace that prior to the libraries being built, so it calls the FreeRTOS.org handler directly.

> XIntc_DeviceInterruptHandler()
> 1. will do some stuff
> 2. call __FreeRTOS_interrupt_handler()
> 3. will do some other stuff

This sounds like the Microblaze is now more like the Xilinx/PowerPC code, which I suppose would make sense.

I would have to look at what the library code does. If it has the same functionality as the PowerPC interrupt entry code then it will save all the registers for you, which can make things easier. The FreeRTOS handler then just has to save the link register and save the stack pointer into the TCB - nothing else. When the task next runs it loads the stack pointer from the TCB and restores the link register before simply returning to the library code, which then pops off all the registers.

This would mean the portSAVE_CONTEXT and portRESTORE_CONTEXT macros would disappear.

Regards.

RE: Microblaze Demo on ML405

Posted by Erik Andresen on May 28, 2008
I stepped through the whole ISR with the debugger.
The registers are not saved, only the MSR.

RE: Microblaze Demo on ML405

Posted by Erik Andresen on May 28, 2008
...for some reasons I'm too dumb to get the save/restore assembler right.

RE: Microblaze Demo on ML405

Posted by threinbacher on May 29, 2008
Hi all,

I read this thread with special attention, cuz i ran into the same problems as you encountered. Have you found and solution so far to the FreeRTOS working under the newer IP Cores that came with edk 9.2?

greetings from vienna,

RE: Microblaze Demo on ML405

Posted by Erik Andresen on June 2, 2008
See my answer in the other thread.

RE: Microblaze Demo on ML405

Posted by Erik Andresen on June 2, 2008
...worst thing is: I seem to get different results when I use the debugger and where I place my breakpoints.

RE: Microblaze Demo on ML405

Posted by Erik Andresen on June 2, 2008
For some reasons it now ticks a few times (led on, led off...) but after after 5 times toggling a led, the return address after vTaskSwitchContext() in the ISR points back to the ISR itself.

RE: Microblaze Demo on ML405

Posted by Erik Andresen on June 3, 2008
Could somebody explain me why, under EDK 7.1, the demo application no longer works when I remove the call to vTaskSwitchContext() in port.c, vTickISR()?

RE: Microblaze Demo on ML405

Posted by Erik Andresen on June 3, 2008
...I mean, the context switch should still be done over port.c, vPortYield() - right?

RE: Microblaze Demo on ML405

Posted by Dave on June 3, 2008
vTaskSwitchContext is a badly named function. It does not switch any context but does select the next task to run. If you remove it from the tick interrupt then you are effectively running the system in cooperative mode. In cooperative mode a switch between tasks will only occur when taskYIELD is called or when an interrupt calls taskEND_SWITCHING_ISR (or whatever the macro is called in the Microblaze demo).

Setting configUSE_PREEMPTION to 0 should have the same effect.

RE: Microblaze Demo on ML405

Posted by Erik Andresen on June 3, 2008
hmm ok, but the flash tasks for example do call vTaskDelayUntil() and vTaskDelayUntil() will cause a context switch, right?

RE: Microblaze Demo on ML405

Posted by Richard on June 3, 2008
Correct - vTaskDelayUntil() will place the task in the Blocked state, then call yield to switch aware from the (now blocked) task.

The tick interrupt does two things.

+ First it increments the time. When the time has been incremented it checks the Blocked state tasks to see if the new time should cause any tasks to unblock. In the case of a task that was blocked using vTaskDelayUntil() if the time at which the task should unblock has been reached the task will be moved from the Blocked state to the Ready state. It will not be switched in though.

+ Second, if configUSE_PREEMPTION is set to 1, it looks at all the Ready state tasks and selects the highest priority one to enter the running state.

It is the second part that you are removing by deleting te call to vTaskSwitchContext(). Therefore the flash tasks will get unblocked when their delay period expires, but will not be moved from the Ready to the Running state until the currently running task either blocks itself, or calls yield.

If configUSE_PREEMPTION is set to 0 then the idle task will continuously call yield. If configUSE_PREEMPTION is set to 1, AND configIDLE_SHOULD_YIELD is set to 1, then the idle task will also yield if there is a higher priority task that is ready to run. So these two options provide a way for unblocked flash tasks to actually transition to the Running state when vTaskSwitchContext() is not called from the tick interrupt.

Regards

RE: Microblaze Demo on ML405

Posted by Erik Andresen on June 4, 2008
Richard, any idea when you get time to fix the Microblaze port?

RE: Microblaze Demo on ML405

Posted by Erik Andresen on June 4, 2008
I mean, I have a working configuration, but it doesn't involve the xintc (Interrupt Controller) module, so the timer is the only possible interrupt source.

As soon as I try to do the whole stuff with the xintc module, it fails for various reasons.

RE: Microblaze Demo on ML405

Posted by Erik Andresen on June 5, 2008
hah wait. I think I finally found the right document with the proper text in it.

RE: Microblaze Demo on ML405

Posted by Erik Andresen on June 5, 2008
Right. I finally got it working. The answer is soo damm simple. Problem is to find the right documentation.
Also found some documentation in my EDK Installation that disagree on each other. Xilinx will get a Mail from me on this.

Richard, do you prefer an unified patch file, or list of items what to change? (Its not that much).

RE: Microblaze Demo on ML405

Posted by Erik Andresen on June 5, 2008
Anyway, I have a patch file here (Will apply against FreeRTOS 5.0):
http://ares.mailus.de/~erik/freertos_microblaze_ise_9.1/FreeRTOS_Microblaze_ISE_9.1.patch

or the already patched files here:
http://ares.mailus.de/~erik/freertos_microblaze_ise_9.1/files/

I will check if it still works with EDK/ISE 10.1 tomorrow.

RE: Microblaze Demo on ML405

Posted by Richard on June 5, 2008
Nice work! I appreciate your perseverance and sorry not to have been of more assistance - I'm having extreme pressure on my time at the moment.

I have downloaded your files and look forward to trying them out.

Regards.

RE: Microblaze Demo on ML405

Posted by Erik Andresen on June 6, 2008
Thanks, but in my pleasure of seeing the LEDs blinking correctly, I have to admit that I completely forgot the RS232 interrupt.

I have updated the patch
https://ares.mailus.de/~erik/freertos_microblaze_ise_9.1/FreeRTOSV5.0.0_Microblaze_ISE_9.1.patch

and the files port.c and serial.c
http://ares.mailus.de/~erik/freertos_microblaze_ise_9.1/files/

so that the serial interrupt now also works again.

RE: Microblaze Demo on ML405

Posted by Erik Andresen on July 9, 2008
Little update: With my patches the MB port still works with the Xilinx tools 10.1.02i.
Just a small problem: With 10.i GCC will throw a little for the portENTER_CRITICAL/portEXIT_CRITICAL Macros.
Easy to fix: Add the volatile keyword to the uxCriticalNesting declaration in both Macros.


[ Back to the top ]    [ About FreeRTOS ]    [ Sitemap ]    [ ]




Copyright (C) 2004-2010 Richard Barry. Copyright (C) 2010-2016 Real Time Engineers Ltd.
Any and all data, files, source code, html content and documentation included in the FreeRTOSTM distribution or available on this site are the exclusive property of Real Time Engineers Ltd.. See the files license.txt (included in the distribution) and this copyright notice for more information. FreeRTOSTM and FreeRTOS.orgTM are trade marks of Real Time Engineers Ltd.

Latest News:

FreeRTOS V9.0.0 is now available for download.


Free TCP/IP and file system demos for the RTOS


Sponsored Links

⇓ Now With No Code Size Limit! ⇓
⇑ Free Download Without Registering ⇑


FreeRTOS Partners

ARM Connected RTOS partner for all ARM microcontroller cores

Renesas Electronics Gold Alliance RTOS Partner.jpg

Microchip Premier RTOS Partner

RTOS partner of NXP for all NXP ARM microcontrollers

Atmel RTOS partner supporting ARM Cortex-M3 and AVR32 microcontrollers

STMicro RTOS partner supporting ARM7, ARM Cortex-M3, ARM Cortex-M4 and ARM Cortex-M0

Xilinx Microblaze and Zynq partner

Silicon Labs low power RTOS partner

Altera RTOS partner for Nios II and Cortex-A9 SoC

Freescale Alliance RTOS Member supporting ARM and ColdFire microcontrollers

Infineon ARM Cortex-M microcontrollers

Texas Instruments MCU Developer Network RTOS partner for ARM and MSP430 microcontrollers

Cypress RTOS partner supporting ARM Cortex-M3

Fujitsu RTOS partner supporting ARM Cortex-M3 and FM3

Microsemi (previously Actel) RTOS partner supporting ARM Cortex-M3

Atollic Partner

IAR Partner

Keil ARM Partner

Embedded Artists