Porting to ATmega1284p

kd5uwl wrote on Saturday, October 03, 2009:

Hi, I have a couple of ATmega1284p engineering samples - this is similar to the 644 which I also have.

I’m new to FreeRTOS and trying to run it for the first time on the 1284p.  I can flash the LEDs using the mod to main.c (from the docs) that comments out everything and uses a crude timing loop (for loop) to flash them.  But I have not been able to use the scheduler yet.  I’m trying to use the vStartLEDFlashTasks and have added #include "flash.h" to main.c, and have added $(DEMO_DIR)/flash.c to the makefile.

Here is what I’ve changed so far to run on my 1284p:

- Switched to port A instead of B in ParTest.c (PORTA and DDRA)
- In port.c, changed lines like this:
- void SIG_OUTPUT_COMPARE1A( void ) __attribute__ ( ( signal, naked ) );
- to lines like this:
- void TIMER1_COMPA_vect( void ) __attribute__ ( ( signal, naked ) );
- and lines like this:
- TIMSK = ucLowByte;
- to:
- TIMSK1 = ucLowByte;
- Also updated interrupt handling in serial.c so lines like this:
- look like:
- ISR( USART0_UDRE_vect )

What I suspect is that the timer is not running.  Not sure how to check that … ?  Another thing possible is that the prescaler bit pattern is wrong (just thought of that one) - perhaps different between 323 and 1284p?  And of course I’m hoping no major changes like the number of registers being different between these two MCUs?

Any help making this port would be appreciated!  I’m using my usua AVR project setup of avr-gcc and avr-libc on linux.

Thank you,

kd5uwl wrote on Saturday, October 03, 2009:

Looks like this is going to be more difficult than I thought.  Looks like it’s not a simple matter of replacing instances of "TIMSK" with "TIMSK1" as those registers are different.  However, it does look like the prescaling bit patterns are the same, near as I can tell.  Does anyone know of any other differences to watch out for?

rtel wrote on Saturday, October 03, 2009:

I have some ATMega128 files if they are of any use.  I think there are a few around the WEB too.  Contact me directly on r (dot) barry _at_ freertos.org if you want a copy.


kafes wrote on Thursday, October 08, 2009:

Heya kd5uwl and other fellow engineers!
I’m working on a project myself ( a greenhouse automation device with a GSM modem) and i have the same problem . From my tests till now (trying to make it work for about 1-2 weeks) i have seen that the scheduler never interupts the running task and when I try the vTaskDelay it never returns to the task. Have you found the solution or do you have any other thoughts on where might be the problem?

kd5uwl wrote on Friday, October 09, 2009:

Kafes, the answer as Richard says is in the files for the 128 which you can find on here.  I had to travel today and took files with me right after I sent the message earlier so I could reply to you tonight.  But, I didn’t take the right ones :(  Richard did send me the pertinent files for a 128, and I was able to use that to get this running on my 1284p.  Contact me off the reflector – e - smith - mail (all one word without the dashes), and I use geemail (without the "ee"), and I’ll send those to you and point out the areas you need to look at.  I believe port.c is all you’ll need.

Note I still do NOT have the serial piece working, and had to comment out the section in main.c that starts the comtest task, and the check for it.  I’m looking at the serial port for the flshlight, and I’m (finally) (slowly) starting to understand it…

However, I am able to run all the other demo tasks, and write my own.

kafes wrote on Friday, October 09, 2009:

Thanks for the answer and the overall help help Eric.

kd5uwl wrote on Saturday, October 10, 2009:


Sorry, I found your direct emails in my spam folder.  I’ve now replied to you directly.

To anyone following along here, it was the Timer1 setup that needs attention, not Timer2 like I said before.

Here are the pertinent sections of port.c - this is what worked for my 1284p:

     * Implementation of functions defined in portable.h for the AVR port.
    /* Start tasks with interrupts enables. */
    #define portFLAGS_INT_ENABLED                                   ( ( portSTACK_TYPE ) 0x80 )
    /* Hardware constants for timer 1. */
    #define portCLEAR_COUNTER_ON_MATCH                              ( ( unsigned portCHAR ) 0x08 )
    #define portPRESCALE_64                                                 ( ( unsigned portCHAR ) 0x03 )
    #define portCLOCK_PRESCALER                                             ( ( unsigned portLONG ) 64 )
    #define portCOMPARE_MATCH_A_INTERRUPT_ENABLE    ( ( unsigned portCHAR ) 0x02 )  

And then further down, in the function called " prvSetupTimerInterrupt":

    static void prvSetupTimerInterrupt( void )
    unsigned portLONG ulCompareMatch;
    unsigned portCHAR ucHighByte, ucLowByte;

        /* Using 16bit timer 1 to generate the tick.  Correct fuses must be
        selected for the configCPU_CLOCK_HZ clock. */

        ulCompareMatch = configCPU_CLOCK_HZ / configTICK_RATE_HZ;

        /* We only have 16 bits so have to scale to get our required tick rate. */
        ulCompareMatch /= portCLOCK_PRESCALER;

        /* Adjust for correct value. */
        ulCompareMatch -= ( unsigned portLONG ) 1;

        /* Setup compare match value for compare match A.  Interrupts are disabled
        before this is called so we need not worry here. */
        ucLowByte = ( unsigned portCHAR ) ( ulCompareMatch & ( unsigned portLONG ) 0xff );
        ulCompareMatch >>= 8;
        ucHighByte = ( unsigned portCHAR ) ( ulCompareMatch & ( unsigned portLONG ) 0xff );
        OCR1AH = ucHighByte;
        OCR1AL = ucLowByte;

        /* Setup clock source and compare match behaviour. */
        ucLowByte = portCLEAR_COUNTER_ON_MATCH | portPRESCALE_64;
        TCCR1B = ucLowByte;

        /* Enable the interrupt - this is okay as interrupt are currently globally
        disabled. */
        ucLowByte = TIMSK1;
        TIMSK1 = ucLowByte;
    #if configUSE_PREEMPTION == 1

         * Tick ISR for preemptive scheduler.  We can use a naked attribute as
         * the context is saved at the start of vPortYieldFromTick().  The tick
         * count is incremented after the context is saved.
        //void SIG_OUTPUT_COMPARE1A( void ) __attribute__ ( ( signal, naked ) );
        void TIMER1_COMPA_vect( void ) __attribute__ ( ( signal, naked ) );
        //void SIG_OUTPUT_COMPARE1A( void )
        void TIMER1_COMPA_vect( void )
                asm volatile ( "reti" );

         * Tick ISR for the cooperative scheduler.  All this does is increment the
         * tick count.  We don’t need to switch context, this can only be done by
         * manual calls to taskYIELD();
        //void SIG_OUTPUT_COMPARE1A( void ) __attribute__ ( ( signal ) );
        void TIMER1_COMPA_vect( void ) __attribute__ ( ( signal ) );
    //      void SIG_OUTPUT_COMPARE1A( void )
        void TIMER1_COMPA_vect( void )

Note also in the above that I commented out signals like this:

    //      void SIG_OUTPUT_COMPARE1A( void )
and replaced with singals like this:

    void TIMER1_COMPA_vect( void )

I don’t know if this is "right", but it’s working for me.  :slight_smile:

That is, everything but the serial demo - wish I could get that working.

73, kd5uwl