ATMEGA128 … Changes to code
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
ATMEGA128 … Changes to code
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.
ATMEGA128 … Changes to code
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
ATMEGA128 … Changes to code
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
ATMEGA128 … Changes to code
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 :)
Jay
ATMEGA128 … Changes to code
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
}