Microblaze Demo on ML405

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?

Microblaze Demo on ML405

Could the problem be, that the compiler is removing the "or r0, r0, r0" from portasm.s?

Microblaze Demo on ML405

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.

Microblaze Demo on ML405

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("startrn"); 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.

Microblaze Demo on ML405

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.

Microblaze Demo on ML405

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.

Microblaze Demo on ML405

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.

Microblaze Demo on ML405

I think I found the root of all evil: http://www.xilinx.com/support/answers/24988.htm Might be the point.

Microblaze Demo on ML405

Thats a good find.  I would appreciate a copy of any changes you make to fix this. Regards.

Microblaze Demo on ML405

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.

Microblaze Demo on ML405

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.

Microblaze Demo on ML405

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.

Microblaze Demo on ML405

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(); }

Microblaze Demo on ML405

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.

Microblaze Demo on ML405

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.

Microblaze Demo on ML405

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.

Microblaze Demo on ML405

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) {}

Microblaze Demo on ML405

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.

Microblaze Demo on ML405

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.

Microblaze Demo on ML405

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.

Microblaze Demo on ML405

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?

Microblaze Demo on ML405

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

Microblaze Demo on ML405

I stepped through the whole ISR with the debugger. The registers are not saved, only the MSR.

Microblaze Demo on ML405

…for some reasons I’m too dumb to get the save/restore assembler right.

Microblaze Demo on ML405

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,

Microblaze Demo on ML405

See my answer in the other thread.

Microblaze Demo on ML405

…worst thing is: I seem to get different results when I use the debugger and where I place my breakpoints.

Microblaze Demo on ML405

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.

Microblaze Demo on ML405

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

Microblaze Demo on ML405

…I mean, the context switch should still be done over port.c, vPortYield() – right?

Microblaze Demo on ML405

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.

Microblaze Demo on ML405

hmm ok, but the flash tasks for example do call vTaskDelayUntil() and vTaskDelayUntil() will cause a context switch, right?

Microblaze Demo on ML405

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

Microblaze Demo on ML405

Richard, any idea when you get time to fix the Microblaze port?

Microblaze Demo on ML405

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.

Microblaze Demo on ML405

hah wait. I think I finally found the right document with the proper text in it.

Microblaze Demo on ML405

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

Microblaze Demo on ML405

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.

Microblaze Demo on ML405

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.

Microblaze Demo on ML405

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.

Microblaze Demo on ML405

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.