ATMEGA128 ... Changes to code

jaydmdigital wrote on Saturday, December 01, 2007:

I’m working with the ATMega128 which is based on the ATMEGA323. I’ve found some items that need to be tweaked to get the demo to run. Here are the changes I had to make. Some of these are already documented but I’m including them here for completeness. Also, I’m using WinAVR. I am running my serial at 115200 baud without issue now.

// ------------------------------------------------
in .\FreeRTOSConfig.h
#define configCPU_CLOCK_HZ    ( ( unsigned portLONG ) 16000000 )

in ./serial/serial.c

#if defined(__AVR_ATmega128__)
  #define UDR            UDR0
  #define UCSRB            UCSR0B
  #define UCSRC            UCSR0C
  #define UBRRL            UBRR0L
  #define UBRRH            UBRR0H
  #define SIG_UART_RECV        SIG_UART0_RECV
  #define SIG_UART_DATA        SIG_UART0_DATA
#endif

/* Calculate the baud rate register value from the equation in the data sheet. */
ulBaudRateCounter = ( (configCPU_CLOCK_HZ + (ulWantedBaud * 8)) / ( serBAUD_DIV_CONSTANT * ulWantedBaud ) - ( unsigned portLONG ) 1 );

//Note: this method of calculating baud rate setting was required for the demo to work for me. I picked it up from Pascal Stang

//-----------------------------------------------------

Hope this helps others.

Jay

rtel wrote on Sunday, December 02, 2007:

Thanks - I appreciate you taking the time to provide the information.

Is the baud rate calculation specific to the Mega128 class of micros, or is it generic so will also work on the 323?

Regards.

jaydmdigital wrote on Sunday, December 02, 2007:

Richard, it’s generic. I can’t say I’ve tested it on anything other than the 128, but I got it from Pascal Stang’s AVRLib library and he says his code can be used on:
#    MCU = at90s8515
#    MCU = atmega163
#    MCU = atmega323
#    MCU = atmega161
#    MCU = atmega128

Jay

jaydmdigital wrote on Sunday, December 02, 2007:

Although it may have been obvious to some, it wasn’t immediately obvious to me for the following:

#define portTICK_RATE_MS   ( ( portTickType ) 1000 / configTICK_RATE_HZ )

In use it looks like this:

vTaskDelay( ( portTickType ) 50 / portTICK_RATE_MS );    // pause 50ms or thereabouts

gives you a rounded off (int) number of clock ticks based on the configTICK_RATE_HZ value in the config file. In my case, I wanted to specify the Hz my task would need to run at (i.e. 50Hz, 20Hz).

#define motorPIDFrequency  ( ( portTickType ) 50 / configTICK_RATE_HZ  ) // 50hz or 20ms

vTaskDelayUntil( &xLastWakeTime, motorPIDFrequency );        // wait for the next cycle

So that instead of thinking in ms for my vTaskDelayUntil, I can use the required Hz. Either way, the system converts to an (int) so there will be some "error" depending on you choice of configTICK_RATE_HZ. You want simple, chose 1000 or 1 tick every 1ms … but per the API, this is excessive for most applications.

FWIW,
Jay

jaydmdigital wrote on Sunday, December 02, 2007:

Wow, I really hosed that last post up …

Should have been:

#define motorPIDFrequency ( ( portTickType ) configTICK_RATE_HZ / 50 ) // 50hz or 20ms delay

vTaskDelayUntil( &xLastWakeTime, motorPIDFrequency ); // wait for the next cycle

Apologies, too bad there are no edits :slight_smile:

Jay

cherepanov wrote on Sunday, December 02, 2007:

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 );
   
#if (defined (__AVR_ATmega128__) || defined  (__AVR_ATmega323__))
#define portCOMPARE_MATCH_A_INTERRUPT_ENABLE    ( ( unsigned portCHAR ) 0x10 )

    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 = TIMSK;
    ucLowByte |= portCOMPARE_MATCH_A_INTERRUPT_ENABLE;
    TIMSK2 = ucLowByte;
/*#endif(__AVR_ATmegaXXX__)*/
#elif defined (__AVR_AT90CAN128__)
#define portCOMPARE_MATCH_A_INTERRUPT_ENABLE    ( ( unsigned portCHAR ) 0x02 )

    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;
    ucLowByte |= portCOMPARE_MATCH_A_INTERRUPT_ENABLE;
    TIMSK1 = ucLowByte;
#else
#  if !defined(__COMPILING_AVR_LIBC__)
#    warning "device type not defined"
#  endif
#endif
}