AT91SAM7S256 WinARM port almost working

Hello, I have been creating an AT91SAM7S256 port using WinARM (GCC) and I have it running to the point where it gets to vPortISRStartFirstTask() in portISR.c which executes the macro portRESTORE_CONTEXT(). However, once it gets to this point I don’t know where it goes. It doesn’t appear to be executing any of the tasks that have been created (basically the IAR SAM7S demo application). I haven’t seen it get to any of the tasks (I have been using the LEDs to show me where it is since I don’t know how to use the debugger yet). I’ve tested the WinARM Hello example source within this port and that works fine (LEDs flash, timers run, UART0 works). I figure that this must be close to working, but maybe it is jumping to a wrong address? I tried disabling all tasks except the IDLE task that gets created in vTaskStartScheduler() in tasks.c, but it still won’t jump to prvIdleTask(). Any suggestions? Any ideas on how to use a SAM-ICE/J-LINK (Segger) with the AT91SAM7S-EK board to debug? Once I’ve got this code working I will submit it back to FreeRTOS and WinARM for assimilation. Thanks, Darrik

AT91SAM7S256 WinARM port almost working

IDLE tasks will work if you compile tasks.c in thumb mode – I had the problem (please look the archive some days ago) You have to remember about startup.s and swi handler – you can use .weak function to link the handler with vportYieldProcessor. J-LINK is cooperate with IAR environment but with other tool there is very poor support. GDB insight works with jlinkserver but it crashes very often :/ For Keil support you need RMI licence form Segger. Rowley is not special. I tried it but I was not happy. JLINK is good to debug using command line of jlink but it is not convenient… I had a lot of problems because I use GCC with SAM-BA boot loader cooperation (sometimes you are in ARM mode, sometimes in Thumb – dual reset etc.). Janusz

AT91SAM7S256 WinARM port almost working

>I tried disabling all tasks except the IDLE task that gets created in vTaskStartScheduler() in tasks.c, but it still won’t jump to prvIdleTask(). If you do not create any own task the scheduler will not run! Then it will return to continue your main function… Please look tasks.c source wheere idle task is created.

AT91SAM7S256 WinARM port almost working

Also – REMEBER TO CALL MAIN() FROM SUPERVISOR MODE!  Otherwise starting the first task will not work.

AT91SAM7S256 WinARM port almost working

I’m finally getting back to this source code… I’ve been compiling with -DTHUMB_INTERWORK per one of Janusz’s threads (because I also had the problem where the linker gave all kinds of errors). So, tasks.c is being compiled in thumb mode. Even with "user" tasks created, nothing happens. It gets to vPortISRStartFirstTask() and then I don’t know what happens. Since I am a newbie to ARM, I am using example code to determine how others got their stuff to work, but of course many are using IAR and not GCC. From what I can tell in the startup_SAM7S.S assembly, the processor is getting set to SVC mode. If some other C function is later setting the mode otherwise, then I haven’t figured that out yet. I will try to determine via JLink commander where this code might be sitting. If anyone has a GCC example startup file for the AT91SAM7S256, then that would be helpful to me… Thanks, Darrik

AT91SAM7S256 WinARM port almost working

Can you not use the SAM7X256 GCC startup file that is already in the zip file.  I don’t think there would be anything different between the S and X as far as this file goes. I think you are right, stepping into the start first task code will show you right away what the problem is.

AT91SAM7S256 WinARM port almost working

From what I have found so far, the code (when running with only the vErrorCheck() and prvIdleTask() tasks) sits/loops in vTaskSwitchContext(). When I have the demo tasks enabled, then it gets to address 0x00200044 which appears to be within the interrupt vector area: .data           0x00200000      0x140 load address 0x00104244                 0x00200000                _data = . *(.vectram) .vectram       0x00200000       0x58 startup_SAM7S.o *(.data) .data          0x00200058        0x0 startup_SAM7S.o I will need to wait for over a week before I get back to this, but it appears that maybe not jumping to an interrupt is what is holding me up. If anyone has a page number in some ARM manual I can look at so that I know how the vector memory is mapped out, then that would be helpful. Thanks again, Darrik

AT91SAM7S256 WinARM port almost working

If you zip up your whole project and send it to me ( r _dot* barry AT_AT freertos.org ) I will take a look. Regards.

AT91SAM7S256 WinARM port almost working

I can’t understand why, but trouble is here: #define portRESTORE_CONTEXT()      …   … /* Restore all system mode registers for the task. */                "LDMFD    LR, {R0-R14}^                                        nt"    when compiled with IAR this insruction will leave LR unchanged, but in case of gas lr is changed to 0xaaaaaaaa I tried to restore registers without LR (R14), but my task is failed in taskYIELD i don’t know why, but it will go into IRQ handler, which isn’t defined because configUSE_PREEMPTION is 0

AT91SAM7S256 WinARM port almost working

This instruction should be called in Supervisor mode, and set the System mode LR to 0xaaaaaaaa. This instruction will NOT work in the IAR simulator due to a bug in the simulator – but will work using IAR on the target hardware – PROVIDED the CPU is in Supervisor mode when it is executed.

AT91SAM7S256 WinARM port almost working

What is your compiler flag for optimalization? I have problem with GCC and -O0. Then I have not stable platform which crash because of stack for example. Janusz

AT91SAM7S256 WinARM port almost working

Are you still using WinARM?  Try GNUARM using the preconfigured projects.  It works nicely ;-)

AT91SAM7S256 WinARM port almost working

yes, I am using. Is it really better?

AT91SAM7S256 WinARM port almost working

I have checked with GNUARM, all my problems are the same :/ with WINARM -O0 crashes after 102 OS ticks and with GNUARM after 7 :/ Janusz

AT91SAM7S256 WinARM port almost working

From what I can tell so far, when the code taskYIELD() (a macro for portYIELD() which is a macro for "SWI") from vTaskDelay() in tasks.c, the code never returns. This seems to be consistent with what I am seeing–the code seems to be stuck at some interrupt (I guess in this case it would be "SWI"). What SWI handler is being used? in the startup code it initializes SWI_Handler but it appears to just branch to itself. In Janusz’s example code (which works) it does the same thing, so what should I be looking into to make my version work? Thanks, Darrik

AT91SAM7S256 WinARM port almost working

swi_handler is a weak symbol.  It should be overwritten to jump to vPortYieldProcessor.  Look at the lwIP SAM7X port demo application, in FreeRTOSConfig.h you will see the line: #define vPortYieldProcessor swi_handler

AT91SAM7S256 WinARM port almost working

yes, the line in FreeRTOSConfig.h is responsible and .weak SWI_Handler line in startup.S Janusz

AT91SAM7S256 WinARM port almost working

I added both of these lines (and changed SWI_HandlerR to SWI_Handler in startup like Janusz’s example), but it still won’t return from taskYIELD(). I see that it is going through the vPortYieldProcessor() routine, but I don’t know what happens to it after that. I assume it should have switched tasks and started running in that task until it yielded again.

AT91SAM7S256 WinARM port almost working

have you add the .weak in startup? It is very important to add that. Then the linker removed the old symbol and linking with new from C. If you write the device enter into vPortYiledProcessor so it is ok. Now it is something other. Check all your port files especially assembler fragments. My advice is to add LED blinking to OS interrupt. It is very useful. Janusz

AT91SAM7S256 WinARM port almost working

Janusz, Yes, I had already added the .weak statement. It appears that all of the tasks run once. If there is some special circumstance, then sometimes the prvIdleTask() will keep running (resumes every 1 microsecond). However, if I disconnect power to the board, then each task will run only once and then everything is dead. The "special circumstance" seems to be after flash updating the code (via JTAG interface) then if I press the reset button prvIdleTask() will keep running (no other tasks run more than once). Again, unplugging power will then put the board in a state where it will run the tasks only once. Does this give anyone any clues? Thanks again, Darrik

AT91SAM7S256 WinARM port almost working

Sounds like the tick interrupt is not running.  Try getting the timer interrupt working by itself to prove to your self that it is working before attempting to add tasks.  If they only run once then they are probably blocked on a time that never occurs as the tick is not incrementing.

AT91SAM7S256 WinARM port almost working

It appears that the PIT is not running. I had tested the code without the OS a few weeks ago and the PIT was working (a WinARM serial "Hello" example), but now that code also is not working. The PIT is being configured and enabled, but it is like the main interrupt register (? is there one and what is it?) is being blocked. USART0 interrupts work and IRQ0 interrupts work, but the PIT is blocked… Darrik

AT91SAM7S256 WinARM port almost working

So far it appears that all interrupts are disabled. In startup_SAM7.S the processor gets put in SVC mode with IRQ and FIQ disabled. When I enable IRQ and FIQ for SVC then the interrupts work (as long as I don’t allow the RTOS to start!!!). Now I need to find out why the RTOS isn’t enabling the interrupts. As a note, Janusz’s hello3_2dmini2 code keeps SVC IRQ and FIQ interrupts disabled and yet that code works just fine. Is there a function that is being called that enables the SVC interrupts that I am missing??? Darrik

AT91SAM7S256 WinARM port almost working

Each task maintains its own interrupt status that is stored as part of the task context.  When the task context is initially set up (when the task is created) it is configured to have interrupts enabled.  It should therefore not matter if main() is called with interrupts enabled or disabled, as when a task starts executing it will have interrupts enabled. Place a break point at the start of the first task that executes – when the break point is hit check the interrupt bit in the status register – also check the uxCriticalNesting value (variable found in port.c), it should be 0 when the task starts. One or other must be going wrong. Regards.

AT91SAM7S256 WinARM port almost working

I’m at a loss as to why it is not working. This is my current output: main: starting task scheduler xPortStartScheduler: started timer vPreemptiveTick: AIC_ISR=1, AIC_IPR=2, AIC_IMR=42, ulCriticalNesting=0 The vPreemptiveTick output above is right after vTaskSwitchContext() in vPreemptiveTick(). I get 1 interrupt (tick) and then no more. I am going to modify some working code that is almost identical to mine to make it like my code until the working code stops working. Hopefully I’ll have an update on this tomorrow morning. The joys of the learning curve on new processors and new code… Darrik

AT91SAM7S256 WinARM port almost working

Do you send to AIC interrupt finished flag in portISR PIT interrupt service like AT91C_BASE_AIC->AIC_EOICR = AT91C_BASE_PITC->PITC_PIVR? Janusz

AT91SAM7S256 WinARM port almost working

Hi Janusz, Yes, I do:         /* End the interrupt in the AIC. */         AT91C_BASE_AIC->AIC_EOICR = AT91C_BASE_PITC->PITC_PIVR; portISR.c is almost identical to your hello3_2dmini2 code. I notice that you have a conditional statement around the interrupt code (between the portSAVE_CONTECT() and portRESTORE_CONTEXT() macros):         if (AT91C_BASE_PITC->PITC_PISR & AT91C_PITC_PITS) { Is there a reason for that? Darrik

AT91SAM7S256 WinARM port almost working

So far, converting Janusz’s hello3 code toward my implementation has not caused a failure in hello3. The PIT and OS are still running. The main differences left are in main.c and syscalls.c (which makes use of comm.c and commd.c whereas my code follows the serial.c and serialISR.c source from one of the FreeRTOS SAM7S examples). My code also (like the FreeRTOS SAM7S example) compiles and uses the following whereas hello3 does not: $(RTOS_APP_DIR)/Common/Minimal/integer.c $(RTOS_APP_DIR)/Common/Minimal/flash.c $(RTOS_APP_DIR)/Common/Minimal/PollQ.c $(RTOS_APP_DIR)/Common/Minimal/comtest.c $(RTOS_APP_DIR)/Common/Minimal/flop.c $(RTOS_APP_DIR)/Common/Minimal/semtest.c $(RTOS_APP_DIR)/Common/Minimal/dynamic.c $(RTOS_APP_DIR)/Common/Minimal/BlockQ.c Files that I have converted to be identical to mine include: * makefile * tasks.c * task.h * port.c * portISR.c * portmacro.h * FreeRTOSConfig.h * Board.h * startup_SAM7S.S Darrik

AT91SAM7S256 WinARM port almost working

I’ve converted most of main.c in hello3 (Janusz’s code) toward my code (which is basically one of the SAM7S FreeRTOS examples). When I add the following task in main(), then the board fails to continue running:     vAltStartComTestTasks( mainCOM_TEST_PRIORITY, mainCOM_TEST_BAUD_RATE, mainCOM_TEST_LED ); Since Janusz’s code uses some other comm code, then this is probably why hello3 has always worked. Darrik

AT91SAM7S256 WinARM port almost working

I have found the bug! The queue handles in serialISR.c were never initialized (but the serial.c versions of those same variables were initialized). Thus when the COM interrupt would happen it would attempt to do a memcpy() to the Tx queue handle but alas it was attempting to write to unknown memory and thus locked up. I added the following to xSerialPortInitMinimal() and all is mostly happy:     /* The queues are used in the serial ISR routine, so are created from     serialISR.c (which is always compiled to ARM mode. */     vSerialISRCreateQueues( uxQueueLength, &xRxedChars, &xCharsForTx ); Now the question is why there is an indication (via LED4) that there was a task check error (it is the serial task again causing a problem). Function xAreComTestTasksStillRunning() gets called and returns an error and thus the LED’s timing is adjusted to indicate an error.