IAR AVR Port

ChibiOS public support forum for topics related to the Atmel AVR family of micro-controllers.

Moderator: tfAteba

alexblack
Posts: 277
Joined: Mon Sep 24, 2012 3:52 pm
Been thanked: 33 times

Re: IAR AVR Port

Post by alexblack »

Hi.
It seems I found the problem. XMEGA more complex device then old AVRs and has 'Interrupts and Programmable Multilevel Interrupt Controller'.
This is 'XMEGA A MANUAL' from Atmel:
The PMIC status register contains state information that ensures that the PMIC returns to the correct interrupt level when the RETI (interrupt return) instruction is executed at the end of an interrupt handler. Returning from an interrupt will return the PMIC to the state it had before entering the interrupt. The status register (SREG) is not saved automatically upon an interrupt request.
The RET (subroutine return) instruction cannot be used when returning from the interrupt handler routine, as this will not return the PMIC to its correct state.

Since port_switch always uses RET instruction to switch to another thread even in the ISR (when preemption occurred) instead of RETI, then the PMIC is blocked!
Can somehow divide the switching procedure in this case: one used RET, and the second RETI?
Now I will try to use global flag in IRQ_PROLOGUE and port_switch to make sure that the problem in this.
Also global interrupts not disabled in ISR - may be this is the second problem.
alexblack
Posts: 277
Joined: Mon Sep 24, 2012 3:52 pm
Been thanked: 33 times

Re: IAR AVR Port

Post by alexblack »

YES!!! It works!

Code: Select all

 file: chcoreasm.s90
...
     // if (XMEGA_ISR_FLAG != TRUE)
                    tst     R0                   
                    brne    RETI_RET
     // ret
                    ret
     // else { XMEGA_ISR_FLAG = FALSE; REETI }
RETI_RET:           clr     R0
                    st      Z, R0
                    reti


Code: Select all

 file: chcore.h
...
/**
 * @brief   IRQ prologue code.
 * @details This macro must be inserted at the start of all IRQ handlers
 *          enabled to invoke system APIs.
 * @note    This code tricks the compiler to save all the specified registers
 *          by "touching" them.
 */
#define PORT_IRQ_PROLOGUE() { \
  dbg_check_lock();                                                         \
  XMEGA_ISR_FLAG = TRUE;                                                    \
  }

/**
 * @brief   IRQ epilogue code.
 * @details This macro must be inserted at the end of all IRQ handlers
 *          enabled to invoke system APIs.
 */
#define PORT_IRQ_EPILOGUE() {                                               \
  /*dbg_check_lock();*/                                                         \
  if (chSchIsPreemptionRequired())                                          \
    chSchDoReschedule();                                                    \
  XMEGA_ISR_FLAG = FALSE;                                                   \
  dbg_check_unlock();                                                       \
}


Results of TEST:

Code: Select all

MAIN: > *** ROBOT-X V.1.00 14/03/2013***
MAIN: > CPU is AVR atXMega128A1, XTAL = 32MHz
MAIN: > Compiled Mar 16 2013 14:59:53

MAIN: > ChibiOS Version: 2.5.2

*** ChibiOS/RT test suite
***
*** Kernel:       2.5.2unstable
*** Compiled:     Mar 16 2013 - 14:45:38
*** Compiler:     IAR C/C++ Compiler V6.11.1.50453 for Atmel AVR
*** Architecture: AVR
*** Core Variant: xMegaAVR
*** Port Info:    IAR XMEGA by ALEX BLACK
*** Platform:     XMEGA
*** Test Board:   PHOTOROBOT-X

----------------------------------------------------------------------------
--- Test Case 1.1 (Threads, enqueuing test #1)
--- Result: SUCCESS
----------------------------------------------------------------------------
--- Test Case 1.2 (Threads, enqueuing test #2)
--- Result: SUCCESS
----------------------------------------------------------------------------
--- Test Case 1.3 (Threads, priority change)
--- Result: SUCCESS
----------------------------------------------------------------------------
--- Test Case 1.4 (Threads, delays)
--- Result: SUCCESS
----------------------------------------------------------------------------
--- Test Case 2.1 (Semaphores, enqueuing)
--- Result: SUCCESS
----------------------------------------------------------------------------
--- Test Case 2.2 (Semaphores, timeout)
--- Result: SUCCESS
----------------------------------------------------------------------------
--- Test Case 2.3 (Semaphores, atomic signal-wait)
--- Result: SUCCESS
----------------------------------------------------------------------------
--- Test Case 2.4 (Binary Semaphores, functionality)
--- Result: SUCCESS
----------------------------------------------------------------------------
--- Test Case 3.1 (Mutexes, priority enqueuing test)
--- Result: SUCCESS
----------------------------------------------------------------------------
--- Test Case 3.2 (Mutexes, priority return)
--- Result: SUCCESS
----------------------------------------------------------------------------
--- Test Case 3.3 (Mutexes, status)
--- Result: SUCCESS
----------------------------------------------------------------------------
--- Test Case 3.4 (CondVar, signal test)
--- Result: SUCCESS
----------------------------------------------------------------------------
--- Test Case 3.5 (CondVar, broadcast test)
--- Result: SUCCESS
----------------------------------------------------------------------------
--- Test Case 3.6 (CondVar, boost test)
--- Result: SUCCESS
----------------------------------------------------------------------------
--- Test Case 4.1 (Messages, loop)
--- Result: SUCCESS
----------------------------------------------------------------------------
--- Test Case 5.1 (Mailboxes, queuing and timeouts)
--- Result: SUCCESS
----------------------------------------------------------------------------
--- Test Case 6.1 (Events, registration and dispatch)
--- Result: SUCCESS
----------------------------------------------------------------------------
--- Test Case 6.2 (Events, wait and broadcast)
--- Result: SUCCESS
----------------------------------------------------------------------------
--- Test Case 6.3 (Events, timeouts)
--- Result: SUCCESS
----------------------------------------------------------------------------
--- Test Case 10.1 (Queues, input queues)
--- Result: SUCCESS
----------------------------------------------------------------------------
--- Test Case 10.2 (Queues, output queues)
--- Result: SUCCESS
----------------------------------------------------------------------------
--- Test Case 11.1 (Benchmark, messages #1)
--- Score : 38581 msgs/S, 77162 ctxswc/S
--- Result: SUCCESS
----------------------------------------------------------------------------
--- Test Case 11.2 (Benchmark, messages #2)
--- Score : 32047 msgs/S, 64094 ctxswc/S
--- Result: SUCCESS
----------------------------------------------------------------------------
--- Test Case 11.3 (Benchmark, messages #3)
--- Score : 32047 msgs/S, 64094 ctxswc/S
--- Result: SUCCESS
----------------------------------------------------------------------------
--- Test Case 11.4 (Benchmark, context switch)
--- Score : 119744 ctxswc/S
--- Result: SUCCESS
----------------------------------------------------------------------------
--- Test Case 11.5 (Benchmark, threads, full cycle)
--- Score : 23359 threads/S
--- Result: SUCCESS
----------------------------------------------------------------------------
--- Test Case 11.6 (Benchmark, threads, create only)
--- Score : 29935 threads/S
--- Result: SUCCESS
----------------------------------------------------------------------------
--- Test Case 11.7 (Benchmark, mass reschedule, 5 threads)
--- Score : 9666 reschedules/S, 57996 ctxswc/S
--- Result: SUCCESS
----------------------------------------------------------------------------
--- Test Case 11.8 (Benchmark, round robin context switching)
--- Score : 69300 ctxswc/S
--- Result: SUCCESS
----------------------------------------------------------------------------
--- Test Case 11.9 (Benchmark, I/O Queues throughput)
--- Score : 130828 bytes/S
--- Result: SUCCESS
----------------------------------------------------------------------------
--- Test Case 11.10 (Benchmark, virtual timers set/reset)
--- Score : 105794 timers/S
--- Result: SUCCESS
----------------------------------------------------------------------------
--- Test Case 11.11 (Benchmark, semaphores wait/signal)
--- Score : 371820 wait+signal/S
--- Result: SUCCESS
----------------------------------------------------------------------------
--- Test Case 11.12 (Benchmark, mutexes lock/unlock)
--- Score : 145496 lock+unlock/S
--- Result: SUCCESS
----------------------------------------------------------------------------
--- Test Case 11.13 (Benchmark, RAM footprint)
--- System: 370 bytes
--- Thread: 47 bytes
--- Timer : 14 bytes
--- Semaph: 7 bytes
--- EventS: 3 bytes
--- EventL: 8 bytes
--- Mutex : 12 bytes
--- CondV.: 6 bytes
--- Queue : 26 bytes
--- MailB.: 26 bytes
--- Result: SUCCESS
----------------------------------------------------------------------------

Have a nice day.
User avatar
Giovanni
Site Admin
Posts: 14891
Joined: Wed May 27, 2009 8:48 am
Has thanked: 1202 times
Been thanked: 996 times

Re: IAR AVR Port

Post by Giovanni »

Good work.

If I understood the problem right then I would consider making the PMIC part of the intctx structure, this way you would not have to handle flags. Each thread would have its PMIC status as part of the context. The problem is that port_switch can return either in a thread or into an ISR.

Alternatively the switch could be performed after exiting from the ISR like the Cortex port does but this would be much more complex. In this scenario the switch is always thread-to-thread.

Giovanni
alexblack
Posts: 277
Joined: Mon Sep 24, 2012 3:52 pm
Been thanked: 33 times

Re: IAR AVR Port

Post by alexblack »

Hi.
I can't understand in ISR routines interrupts must be disabled?
Because in xMega AVR on enter of ISR routine interrupts do not disabled by hardware and I have mysterious errors.
If I disable interrupts in PORT_IRQ_PROLOGUE() then all works fine.
User avatar
Giovanni
Site Admin
Posts: 14891
Joined: Wed May 27, 2009 8:48 am
Has thanked: 1202 times
Been thanked: 996 times

Re: IAR AVR Port

Post by Giovanni »

I don't know that architecture enough to give an definite answer. It is possible it supports priority levels like the Cortex and in that case IRQs are enabled during ISRs. If this is true then the port is more complex, you should look at the Cortex code.

Giovanni
JetForMe
Posts: 99
Joined: Mon Jan 31, 2011 8:12 am

Re: IAR AVR Port

Post by JetForMe »

Giovanni,

XMEGA has a multi-level interrupt handler. Any interrupt can be assigned to any of four levels: disabled, low, medium, and high. Separately, low, medium and high interrupts can be enabled/disabled.

I'm trying to port ChibiOS as well (for GCC).

I set up one of the Timer/Counters to be the system interrupt timer, and gave it medium priority. I currently only enable medium priority interrupts. The handler is being called repeatedly, but very haphazardly. I have not yet addressed the RET/RETI issue raised earlier in this thread. But is storing the PMIC state per thread the right approach?
User avatar
Giovanni
Site Admin
Posts: 14891
Joined: Wed May 27, 2009 8:48 am
Has thanked: 1202 times
Been thanked: 996 times

Re: IAR AVR Port

Post by Giovanni »

Hi,

Your best example is the Cortex-M3 port, it also has priority levels for interrupts. You should not have to save the interrupt level on a per-thread basis because threads run when interrupts are enabled.

The CM3 saves the IRQ info internally to the NVIC and in the interrupt stack frame, I am no sure how this would map to the XMEGA because I don't know the architecture.

In general, when you enter an ISR only IRQs with higher priority should be able to preempt it, interrupts at equal or lower priority should be disabled.

chSysLockFromIsr() should temporarily lock ALL IRQs, chSysUnlockFromIsr() should return to the PREVIOUS situation (not enable all IRQs).

Giovanni
JetForMe
Posts: 99
Joined: Mon Jan 31, 2011 8:12 am

Re: IAR AVR Port

Post by JetForMe »

I'm still working on getting the XMEGA port (using GCC, by the way, perhaps I should start a new thread?) to work. I've disabled everything but PAL and the quantum scheduler. I changed port_switch() to use RETI instead of RET, so that interrupts are re-enabled.

Although XMEGA has a the multi-level interrupts, I don't think they're relevant at this particular juncture. The ONLY interrupt I'm currently using is the timer interrupt, to generate the scheduler ticks.

I have the main thread, idle thread (I think), and the sample thread (which in my case blinks an LED). Before I changed port_swithc() to use RETI, my main would run, the timer would start, it would interrupt 20 times (the quantum), and then try to switch contexts. But it would end up re-entering main, now with interrupts disabled, and the main loop would run.

I changed it to use RETI, and it started continuously re-entering main after 20 ticks. So I looked at port_switch(), and thought I saw that stack pointer address was wrong. I changed it from 0x3D/0x3E to 0x0D/0x0e, and suddenly my debugging was showing that it was scheduling between two threads, one of which was the LED blinker thread. BUT: it never entered the blinker thread, and the main thread loop kept running.

After closer examination of the XMEGA data sheet, I realized I was wrong about the stack pointer, and that it's the same as MEGA.

So, at this point I'm stuck. I can't get it to switch contexts. The AVR core is the same, as far as I can tell, as is interrupt handling. I'm not sure why the MEGA port works with RET, and XMEGA does not. I also can't figure out why I can't seem to actually switch to another thread.

Any suggestions?
JetForMe
Posts: 99
Joined: Mon Jan 31, 2011 8:12 am

Re: IAR AVR Port

Post by JetForMe »

By the way, Giovanni, I'm happy to buy you an Xplain board if it would speed an XMEGA port. But I really need to get this up and running in the next few days.
User avatar
Giovanni
Site Admin
Posts: 14891
Joined: Wed May 27, 2009 8:48 am
Has thanked: 1202 times
Been thanked: 996 times

Re: IAR AVR Port

Post by Giovanni »

Hi,

Please don't, I am so busy of late that I could not promise anything. Things keep cumulating and I still don't have a 2.6.0 release ready. Why don't for a group in order to support the AVR? it is currently not covered by any maintainer.

Giovanni
Post Reply