Quality RTOS & Embedded Software

 Real time embedded FreeRTOS RSS feed 
Real time embedded FreeRTOS mailing list 
Quick Start Supported MCUs PDF Books Trace Tools Ecosystem TCP & FAT Training




Loading

ATMega644 port working

Posted by JMR on May 22, 2008
Hi folks,

I've been working on a project using an ATMega640, WinAVR and FreeRTOS for the past few months.
I made the following changes to port.c to enable Timer 1 as my OS tick.
I've also modified the serial port driver to enable the serial ports on this processor. I've tried to make it generic but since so far the ATMega640 is the only processor I've used it with I don't know if it'll work on anything else... Use at your own risk...

Hope this proves useful to someone out there.

JM

in port.c:
---------------------------------------------------------------------------------------------------------------
/* 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 )


/*
* Setup timer 1 compare match A to generate a tick interrupt.
*/
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 / portCLOCK_PRESCALER;

/* calculates the RTOS tick rate based on the timer's tick rate. */
ulCompareMatch /= configTICK_RATE_HZ;

/* Adjust for correct value. */
ulCompareMatch -= ( unsigned portLONG ) 1;
//ulCompareMatch = (unsigned portLONG) 8639;
/* 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;
ucLowByte |= portCOMPARE_MATCH_A_INTERRUPT_ENABLE;
TIMSK1 = ucLowByte;
}
----------------------------------------------------------------------------------------------------------

/*
* serial.h
* Description:
* serial port driver for the ATMega640
*/

#ifndef SERIAL_COMMS_H
#define SERIAL_COMMS_H

typedef enum
{
serCOM1,
serCOM2,
serCOM3,
serCOM4,
serCOMPortInvalid
} eCOMPort;


typedef enum
{
serNO_PARITY,
serODD_PARITY,
serEVEN_PARITY,
serMARK_PARITY,
serSPACE_PARITY
} eParity;

typedef enum
{
serSTOP_1,
serSTOP_2
} eStopBits;

typedef enum
{
serBITS_5,
serBITS_6,
serBITS_7,
serBITS_8,
serBITS_9
} eDataBits;

typedef enum
{
ser50,
ser75,
ser110,
ser134,
ser150,
ser200,
ser300,
ser600,
ser1200,
ser1800,
ser2400,
ser4800,
ser9600,
ser19200,
ser38400,
ser57600,
ser115200
} eBaud;

extern eCOMPort xSerialPortInit( eCOMPort ePort, eBaud eWantedBaud, eParity eWantedParity, eDataBits eWantedDataBits, eStopBits eWantedStopBits, unsigned portBASE_TYPE uxBufferLength );
extern signed portBASE_TYPE xSerialPutString( eCOMPort ePort, const portCHAR * pcString, portTickType xBlockTime );
extern signed portBASE_TYPE xSerialGetChar( eCOMPort ePort, portCHAR *pcRxedChar, portTickType xBlockTime );
extern signed portBASE_TYPE xSerialPutChar( eCOMPort ePort, portCHAR cOutChar, portTickType xBlockTime );
extern unsigned portBASE_TYPE ubSerialIsActive(eCOMPort ePort);
extern void vSerialClose( eCOMPort xPort );

#endif




/*
* serial.c
* Description:
* This is a quad serial port driver for ATMega644.
* It gives a common interface to open/close serial ports.
* $Log: serial.c,v $
* Revision 1.7 2008-05-09 14:23:27+01 jmr
* Fixed a memory leak in the serial port driver where allocated memory for the queues wasn't freed but the pointers to the queues nulled. This meant that if a task opened the same port twice it didn't get the same queue again....
* The driver now simply will not reallocate a queue when the port is reopened.
*
*/


#include <stdlib.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include "FreeRTOSConfig.h"
#include "FreeRTOS.h"
#include "queue.h"
#include "task.h"
#include "serial.h"

#define serialMAX_NUM_PORTS 4
#define serialBAUD_DIV_CONSTANT 16

/*-----------------------------------------------------------*/
static void prvInterruptOn(eCOMPort ePort);
static void prvInterruptOff(eCOMPort ePort);
/*-----------------------------------------------------------*/

/* declare some useful constants */
static unsigned portSHORT usBaudRateDivisors[] PROGMEM =
{
configCPU_CLOCK_HZ/serialBAUD_DIV_CONSTANT/50 -1, // 50
configCPU_CLOCK_HZ/serialBAUD_DIV_CONSTANT/75 -1, // 75
configCPU_CLOCK_HZ/serialBAUD_DIV_CONSTANT/110 -1, // 110
configCPU_CLOCK_HZ/serialBAUD_DIV_CONSTANT/134 -1, // 134
configCPU_CLOCK_HZ/serialBAUD_DIV_CONSTANT/150 -1, // 150
configCPU_CLOCK_HZ/serialBAUD_DIV_CONSTANT/200 -1, // 200
configCPU_CLOCK_HZ/serialBAUD_DIV_CONSTANT/300 -1, // 300
configCPU_CLOCK_HZ/serialBAUD_DIV_CONSTANT/600 -1, // 600
configCPU_CLOCK_HZ/serialBAUD_DIV_CONSTANT/1200 -1, // 1200
configCPU_CLOCK_HZ/serialBAUD_DIV_CONSTANT/1800 -1, // 1800
configCPU_CLOCK_HZ/serialBAUD_DIV_CONSTANT/2400 -1, // 2400
configCPU_CLOCK_HZ/serialBAUD_DIV_CONSTANT/4800 -1, // 4800
configCPU_CLOCK_HZ/serialBAUD_DIV_CONSTANT/9600 -1, // 9600
configCPU_CLOCK_HZ/serialBAUD_DIV_CONSTANT/19200 -1, // 19200
configCPU_CLOCK_HZ/serialBAUD_DIV_CONSTANT/38400 -1, // 38400
configCPU_CLOCK_HZ/serialBAUD_DIV_CONSTANT/57600 -1, // 57600
configCPU_CLOCK_HZ/serialBAUD_DIV_CONSTANT/115200 -1 // 115200
};

static unsigned portCHAR ucParityBits[] PROGMEM = { 0x00, /* No parity */
0x30, /* Odd parity */
0x20, /* Even parity */
0x00, /* Mark parity (not supported) */
0x00 /* Space parity (not supported) */
};

static unsigned portCHAR ucDataBits[] PROGMEM = { 0x00, /* 5 data bits */
0x02, /* 6 data bits */
0x04, /* 7 data bits */
0x06, /* 8 data bits */
0x06 /* 9 data bits */
};

/* The Rx And Tx queues used for the serial communications */
static xQueueHandle xRxedChars[serialMAX_NUM_PORTS];
static xQueueHandle xCharsForTx[serialMAX_NUM_PORTS];

/* Serial port initialisation */
eCOMPort xSerialPortInit( eCOMPort ePort, eBaud eWantedBaud, eParity eWantedParity, eDataBits eWantedDataBits, eStopBits eWantedStopBits, unsigned portBASE_TYPE uxQueueLength )
{
unsigned portSHORT usBaudRateCounter;
unsigned portCHAR ucByte;

/* Verify that the desired port number is supported */
switch( ePort )
{
case serCOM1:
#if serialMAX_NUM_PORTS > 1
case serCOM2:
#endif
#if serialMAX_NUM_PORTS > 2
case serCOM3:
#endif
#if serialMAX_NUM_PORTS > 3
case serCOM4:
#endif
break;
default:
return serCOMPortInvalid;
break;
}
/* Modifying the serial port registers needs to have all interrupts disabled */
portENTER_CRITICAL();
{
/* Create the queues used by the com test task if they weren't created by a previous call to SerialPortInit
*/
if( xRxedChars[ePort] == NULL)
{
xRxedChars[ePort] = xQueueCreate( uxQueueLength, ( unsigned portBASE_TYPE ) sizeof( signed portCHAR ) );
}
if( xCharsForTx[ePort] == NULL)
{
xCharsForTx[ePort] = xQueueCreate( uxQueueLength, ( unsigned portBASE_TYPE ) sizeof( signed portCHAR ) );
}

/* Calculate the baud rate register value from the equation in the
data sheet. */
//usBaudRateCounter = ( configCPU_CLOCK_HZ / ( serialBAUD_DIV_CONSTANT * ulWantedBaud ) ) - ( unsigned portSHORT ) 1;
usBaudRateCounter = pgm_read_word(&usBaudRateDivisors[eWantedBaud]);

switch( ePort)
{
case serCOM1:
/* Set Parity, data and stop bits */
ucByte = 0;
ucByte |= pgm_read_byte(&ucParityBits[eWantedParity]);
ucByte |= pgm_read_byte(&ucDataBits[eWantedDataBits]);
ucByte |= eWantedStopBits? _BV(USBS0): 0;
UCSR0C = ucByte;
/* Set the baud rate. */
ucByte = ( unsigned portCHAR ) ( usBaudRateCounter & ( unsigned portSHORT ) 0xff );
UBRR0L = ucByte;
usBaudRateCounter >>= ( unsigned portSHORT ) 8;
ucByte = ( unsigned portCHAR ) ( usBaudRateCounter & ( unsigned portSHORT ) 0x0f );
UBRR0H = ucByte;
/* Enable the Rx interrupt. The Tx interrupt will get enabled
later. Also enable the Rx and Tx. */
UCSR0B = ( _BV(RXCIE0) | _BV(RXEN0) | _BV(TXEN0) |((eWantedDataBits==serBITS_9)?_BV(UCSZ02):0));
break;
case serCOM2:
/* Set Parity, data and stop bits */
ucByte = 0;
ucByte |= pgm_read_byte(&ucParityBits[eWantedParity]);
ucByte |= pgm_read_byte(&ucDataBits[eWantedDataBits]);
ucByte |= eWantedStopBits? _BV(USBS0): 0;
UCSR1C = ucByte;
/* Set the baud rate. */
ucByte = ( unsigned portCHAR ) ( usBaudRateCounter & ( unsigned portSHORT ) 0xff );
UBRR1L = ucByte;
usBaudRateCounter >>= ( unsigned portSHORT ) 8;
ucByte = ( unsigned portCHAR ) ( usBaudRateCounter & ( unsigned portSHORT ) 0x0f );
UBRR1H = ucByte;
/* Enable the Rx interrupt. The Tx interrupt will get enabled
later. Also enable the Rx and Tx. */
UCSR1B = ( _BV(RXCIE1) | _BV(RXEN1) | _BV(TXEN1) |((eWantedDataBits==serBITS_9)?_BV(UCSZ12):0) );
break;
case serCOM3:
/* Set Parity, data and stop bits */
ucByte = 0;
ucByte |= pgm_read_byte(&ucParityBits[eWantedParity]);
ucByte |= pgm_read_byte(&ucDataBits[eWantedDataBits]);
ucByte |= eWantedStopBits? _BV(USBS0): 0;
UCSR2C = ucByte;
/* Set the baud rate. */
ucByte = ( unsigned portCHAR ) ( usBaudRateCounter & ( unsigned portSHORT ) 0xff );
UBRR2L = ucByte;
usBaudRateCounter >>= ( unsigned portSHORT ) 8;
ucByte = ( unsigned portCHAR ) ( usBaudRateCounter & ( unsigned portSHORT ) 0x0f );
UBRR2H = ucByte;
/* Enable the Rx interrupt. The Tx interrupt will get enabled
later. Also enable the Rx and Tx. */
UCSR2B = ( _BV(RXCIE2) | _BV(RXEN2) | _BV(TXEN2) |((eWantedDataBits==serBITS_9)?_BV(UCSZ22):0) );
break;
case serCOM4:
/* Set Parity, data and stop bits */
ucByte = 0;
ucByte |= pgm_read_byte(&ucParityBits[eWantedParity]);
ucByte |= pgm_read_byte(&ucDataBits[eWantedDataBits]);
ucByte |= eWantedStopBits? _BV(USBS0): 0;
UCSR3C = ucByte;
/* Set the baud rate. */
ucByte = ( unsigned portCHAR ) ( usBaudRateCounter & ( unsigned portSHORT ) 0xff );
UBRR3L = ucByte;
usBaudRateCounter >>= ( unsigned portSHORT ) 8;
ucByte = ( unsigned portCHAR ) ( usBaudRateCounter & ( unsigned portSHORT ) 0x0f );
UBRR3H = ucByte;
/* Enable the Rx interrupt. The Tx interrupt will get enabled
later. Also enable the Rx and Tx. */
UCSR3B = ( _BV(RXCIE3) | _BV(RXEN3) | _BV(TXEN3) |((eWantedDataBits==serBITS_9)?_BV(UCSZ32):0) );
break;
default:
break;
}
}
portEXIT_CRITICAL();

/* Unlike other ports, this serial code does not return a pointer to a port structure
but returns the number of the port opened if successful. Otherwise it returns eCOMPortInvalid.
*/
return ePort;
}

/*-----------------------------------------------------------*/
/* Get a character from the serial port */
signed portBASE_TYPE xSerialGetChar( eCOMPort ePort, portCHAR *pcRxedChar, portTickType xBlockTime )
{
if( xRxedChars[ePort] == NULL )
{
return pdFAIL;
}

/* Get the next character from the buffer. Return false if no characters
are available, or arrive before xBlockTime expires. */
if( xQueueReceive( xRxedChars[ePort], pcRxedChar, xBlockTime ) )
{
return pdPASS;
}
else
{
return pdFAIL;
}
}

/*-----------------------------------------------------------*/
/* Write a character to the serial port */
signed portBASE_TYPE xSerialPutChar( eCOMPort ePort,portCHAR cOutChar, portTickType xBlockTime )
{
/* ensure the queue has been initialised */
if( xCharsForTx[ePort] == NULL )
{
return pdFAIL;
}

/* Return false if after the block time there is no room on the Tx queue. */
if( xQueueSend( xCharsForTx[ePort], &cOutChar, xBlockTime ) != pdPASS )
{
return pdFAIL;
}

prvInterruptOn(ePort);

return pdPASS;
}
/* write a NULL terminated string to the serial port */
signed portBASE_TYPE xSerialPutString( eCOMPort ePort, const portCHAR * pcString, portTickType xBlockTime )
{
signed portBASE_TYPE retVal = pdPASS;

while(*pcString && (retVal == pdPASS) )
{
retVal = xSerialPutChar( ePort, *pcString++, xBlockTime);
}
return retVal;
}
unsigned portBASE_TYPE ubSerialIsActive(eCOMPort ePort)
{
if( uxQueueMessagesWaiting(xRxedChars[ePort])
||uxQueueMessagesWaiting(xCharsForTx[ePort]) )
{
return pdTRUE;
}
else
{
return pdFALSE;
}
}
/*-----------------------------------------------------------*/
/* Close the serial port */
void vSerialClose( eCOMPort ePort )
{
unsigned portCHAR ucByte;

/* Turn off the interrupt. We may also want to delete the queues and/or
re-install the original ISR. */

portENTER_CRITICAL();
{
/* turn off the Tx interrupt */
prvInterruptOff(ePort);
/* now turn off the Rx interrupt */
switch( ePort )
{
case serCOM1:
ucByte = UCSR0B;
ucByte &= ~_BV(RXCIE0);
UCSR0B = ucByte;
break;
case serCOM2:
ucByte = UCSR1B;
ucByte &= ~_BV(RXCIE1);
UCSR1B = ucByte;
break;
case serCOM3:
ucByte = UCSR2B;
ucByte &= ~_BV(RXCIE2);
UCSR2B = ucByte;
break;
case serCOM4:
ucByte = UCSR3B;
ucByte &= ~_BV(RXCIE3);
UCSR3B = ucByte;
break;
default:
break;
}
/* invalidate the queue handle */
//xRxedChars[ePort] = NULL;
//xCharsForTx[ePort] = NULL;
// Don't do the above two lines as this leads to memory leakage on the massive scale!!!
}
portEXIT_CRITICAL();
}

/*-----------------------------------------------------------*/
/* Turn the transmit interrupt ON */
static void prvInterruptOn(eCOMPort ePort)
{
unsigned portCHAR ucByte;

switch( ePort )
{
case serCOM1:
ucByte = UCSR0B;
ucByte |= _BV(UDRIE0);
UCSR0B = ucByte;
break;
case serCOM2:
ucByte = UCSR1B;
ucByte |= _BV(UDRIE0);
UCSR1B = ucByte;
break;
case serCOM3:
ucByte = UCSR2B;
ucByte |= _BV(UDRIE0);
UCSR2B = ucByte;
break;
case serCOM4:
ucByte = UCSR3B;
ucByte |= _BV(UDRIE0);
UCSR3B = ucByte;
break;
default:
break;
}
}

/* Turn the transmit interrupt OFF */
static void prvInterruptOff(eCOMPort ePort)
{
unsigned portCHAR ucByte;

switch( ePort )
{
case serCOM1:
ucByte = UCSR0B;
ucByte &= ~_BV(UDRIE0);
UCSR0B = ucByte;
break;
case serCOM2:
ucByte = UCSR1B;
ucByte &= ~_BV(UDRIE0);
UCSR1B = ucByte;
break;
case serCOM3:
ucByte = UCSR2B;
ucByte &= ~_BV(UDRIE0);
UCSR2B = ucByte;
break;
case serCOM4:
ucByte = UCSR3B;
ucByte &= ~_BV(UDRIE0);
UCSR3B = ucByte;
break;
default:
break;
}
}
/*-----------------------------------------------------------*/

/*************************************************************
* Interrupt handlers below
*************************************************************/
/*
* serial port 1 Rx and Tx interrupt handlers
*/
ISR( USART0_RX_vect )
{
portCHAR cChar;
portBASE_TYPE bResVal;

/* Get the character and post it on the queue of Rxed characters.
If the post causes a task to wake force a context switch as the woken task
may have a higher priority than the task we have interrupted. */
cChar = UDR0;

portENTER_CRITICAL();
bResVal = xQueueSendFromISR( xRxedChars[0], &cChar, pdFALSE );
portEXIT_CRITICAL();
if( bResVal == pdTRUE )
{
taskYIELD();
}
}
/*-----------------------------------------------------------*/

ISR( USART0_UDRE_vect )
{
portCHAR cChar;
signed portCHAR cTaskWoken;
portBASE_TYPE bResVal;

portENTER_CRITICAL();
bResVal = xQueueReceiveFromISR( xCharsForTx[0], &cChar, &cTaskWoken );
portEXIT_CRITICAL();

if( bResVal == pdTRUE )
{
/* Send the next character queued for Tx. */
UDR0 = cChar;
}
else
{
/* Queue empty, nothing to send. */
prvInterruptOff(serCOM1);
}
}

/*
* serial port 2 Rx and Tx interrupt handlers
*/
ISR( USART1_RX_vect )
{
portCHAR cChar;

/* Get the character and post it on the queue of Rxed characters.
If the post causes a task to wake force a context switch as the woken task
may have a higher priority than the task we have interrupted. */
cChar = UDR1;

if( xQueueSendFromISR( xRxedChars[1], &cChar, pdFALSE ) )
{
taskYIELD();
}
}
/*-----------------------------------------------------------*/

ISR( USART1_UDRE_vect )
{
portCHAR cChar;
signed portCHAR cTaskWoken;

if( xQueueReceiveFromISR( xCharsForTx[1], &cChar, &cTaskWoken ) == pdTRUE )
{
/* Send the next character queued for Tx. */
UDR1 = cChar;
}
else
{
/* Queue empty, nothing to send. */
prvInterruptOff(serCOM2);
}
}

/*
* serial port 3 Rx and Tx interrupt handlers
*/
ISR( USART2_RX_vect )
{
portCHAR cChar;

/* Get the character and post it on the queue of Rxed characters.
If the post causes a task to wake force a context switch as the woken task
may have a higher priority than the task we have interrupted. */
cChar = UDR2;

if( xQueueSendFromISR( xRxedChars[2], &cChar, pdFALSE ) )
{
taskYIELD();
}
}
/*-----------------------------------------------------------*/

ISR( USART2_UDRE_vect )
{
portCHAR cChar;
signed portCHAR cTaskWoken;

if( xQueueReceiveFromISR( xCharsForTx[2], &cChar, &cTaskWoken ) == pdTRUE )
{
/* Send the next character queued for Tx. */
UDR2 = cChar;
}
else
{
/* Queue empty, nothing to send. */
prvInterruptOff(serCOM3);
}
}

/*
* serial port 4 Rx and Tx interrupt handlers
*/
ISR( USART3_RX_vect )
{
portCHAR cChar;

/* Get the character and post it on the queue of Rxed characters.
If the post causes a task to wake force a context switch as the woken task
may have a higher priority than the task we have interrupted. */
cChar = UDR3;

if( xQueueSendFromISR( xRxedChars[3], &cChar, pdFALSE ) )
{
taskYIELD();
}
}
/*-----------------------------------------------------------*/

ISR( USART3_UDRE_vect )
{
portCHAR cChar;
signed portCHAR cTaskWoken;

if( xQueueReceiveFromISR( xCharsForTx[3], &cChar, &cTaskWoken ) == pdTRUE )
{
/* Send the next character queued for Tx. */
UDR3 = cChar;
}
else
{
/* Queue empty, nothing to send. */
prvInterruptOff(serCOM4);
}
}

RE: ATMega644 port working

Posted by Richard on May 23, 2008
Thanks for taking the time to post this up.

Regards.

RE: ATMega644 port working

Posted by Jesper Matthiesen on May 23, 2008
nice.. i have hacked a single usart version for the ATMega2560 myself..

One thing, though.. i think you should write UBBRH *before* writing UBBRL, since writing UBBRL triggers an update of the baud rate prescaler, whereas writing UBBRH does not..

This mistake is present in the ATMega323 port as well, by the way...

RE: ATMega644 port working

Posted by JMR on May 23, 2008
I'll have to check this one out as this code hasn't been a problem for the past few months that it has been running.
Granted I only have 3 baudrates that I've tested (4800, 9600 and 115200) but you never know.
I seem to remember trying the datasheet way and not getting what I expected. Then again it could have been from other bug sources so... If I get a few minutes I'll swap the lines around and check.

RE: ATMega644 port working

Posted by Jesper Matthiesen on May 29, 2008
I am using your port mostly as is on an ATMega2560 @ 14.7MHz.
When receiving data on USART0 at 115200 baud, the received bytes, but the first one, are wrong. if i transmit manually, all bytes are ok. this is not just an issue about missed bytes, since the received bit patterns were never transmitted, so somehow, bytes transmitted closely spaced, are not received correctly (only the first one after a timeout). what is strange is, switching to USART1 makes it all work.. i was thinking of something like interrupt priorities, but that couldn't cause bytes to be received that were never sent...

there's only the receiver task running..

any ideas?

RE: ATMega644 port working

Posted by Richard on May 29, 2008
Is this thread of any help:
https://sourceforge.net/forum/forum.php?thread_id=2052807&forum_id=382005

RE: ATMega644 port working

Posted by Jesper Matthiesen on May 29, 2008
not really.. i know that i shouldn't post a byte at a time to the queue in the optimal solution, but the hardware has no fifo or dma, so... anyway, so far, i'm only doing testing, and it's really strange that it works for usart1, but not for usart0...

also, shouldn't the xQueueSendFromISR's above use the version with pointers for argument 3? i didn't discover that here at first, but it doesn't seem to make any difference on application behavior..

regards...

RE: ATMega644 port working

Posted by JMR on May 30, 2008
Are you using the code I posted to start this thread?
Unfortunately I can't check the 115200 on USART0 as on my board this is connected to a device that only works at 19200.
It does seem strange indeed that it works for USART1 but not USART0. You might want to try swapping the initialisation order of UBBR0L and UBBR0H if you're the code of this thread.

RE: ATMega644 port working

Posted by Jesper Matthiesen on May 30, 2008
i am using your serial.c with slight modifications (init UBRRH before UBRRL, made the USART_RX_vect routines look the same (usart0 was different), changed some register bit names to the correct usart number, updated the xQueueSendFromISR calls to be FreeRTOS 5 compatible, etc).

i've made sure, that the code in serial.c is similar for all 4 USART's, so unless i missed something, that's not it...

if this was a baud rate problem, the characters sent manually from a simple terminal proggy would arrive wrong, so this is not the issue..

regards...

RE: ATMega644 port working

Posted by JMR on May 30, 2008
Actually looking at my code a bit more, there are a few blushes I could have saved myself.
I think I was tinkering with getting things working on my board at the time and forgot to update the "driver" once I got things to work for me. Note to self: don't forget to update the rest of your driver before moving onto the next task.
As for your issue this is very puzzling. If with exactly the same code it works on USART1 but not USART0 I would start questioning the MCU itself.
I suppose you have tried setting a breakpoint in the ISR to check that this got fired as soon as transmission was started.
I might be able to do a wire mod to my PCB and swap USART0 and USART1 to check the behaviour there... However looking at the data-sheet I don't think that this would help you as it seems that even though the 640 is the smaller flash size version of the 2560 they have different errata...
Did you try a minimal set of code to send to the Atmel support guys? They are quite helpful, providing you've minimised the code.
What I'd do is replace the calls to FreeRTOS API by a simple write to a byte array and see if the USART0 still looses the first byte of data. If not then there's a bad interaction with FreeRTOS.

RE: ATMega644 port working

Posted by Jesper Matthiesen on June 2, 2008
JMR,

I think you misunderstood me, or i expressed myself poorly.
I am *not* missing the first byte on any USART, but on USART0, the byte *after* the first one is somehow scrambled when the bytes are closely spaced. If I transmit manually using a terminal program (typing one character at a time), bytes get received correctly. this led me to believe it was task switching related, but it can't be, since it works for USART1 and the tick timer uses a higher priority ISR than both USARTs. Also, the baud rate has to be correct, since i can receive correct characters.

cheers.


[ Back to the top ]    [ About FreeRTOS ]    [ Sitemap ]    [ ]




Copyright (C) 2004-2010 Richard Barry. Copyright (C) 2010-2016 Real Time Engineers Ltd.
Any and all data, files, source code, html content and documentation included in the FreeRTOSTM distribution or available on this site are the exclusive property of Real Time Engineers Ltd.. See the files license.txt (included in the distribution) and this copyright notice for more information. FreeRTOSTM and FreeRTOS.orgTM are trade marks of Real Time Engineers Ltd.

Latest News:

FreeRTOS V9.0.0 is now available for download.


Free TCP/IP and file system demos for the RTOS


Sponsored Links

⇓ Now With No Code Size Limit! ⇓
⇑ Free Download Without Registering ⇑


FreeRTOS Partners

ARM Connected RTOS partner for all ARM microcontroller cores

Renesas Electronics Gold Alliance RTOS Partner.jpg

Microchip Premier RTOS Partner

RTOS partner of NXP for all NXP ARM microcontrollers

Atmel RTOS partner supporting ARM Cortex-M3 and AVR32 microcontrollers

STMicro RTOS partner supporting ARM7, ARM Cortex-M3, ARM Cortex-M4 and ARM Cortex-M0

Xilinx Microblaze and Zynq partner

Silicon Labs low power RTOS partner

Altera RTOS partner for Nios II and Cortex-A9 SoC

Freescale Alliance RTOS Member supporting ARM and ColdFire microcontrollers

Infineon ARM Cortex-M microcontrollers

Texas Instruments MCU Developer Network RTOS partner for ARM and MSP430 microcontrollers

Cypress RTOS partner supporting ARM Cortex-M3

Fujitsu RTOS partner supporting ARM Cortex-M3 and FM3

Microsemi (previously Actel) RTOS partner supporting ARM Cortex-M3

Atollic Partner

IAR Partner

Keil ARM Partner

Embedded Artists