Servo controling with ATmega32 and FreeRTOS

robototechnik wrote on Friday, January 25, 2013:

Hi !
I have a problem with controling two servos with ATmega32 using FreeRTOS. The servos are connected to the Timer1 PWM outputs…at the beginning there was ticking process on the Timer1, now it should tick on the Timer0, but it doesnt((( the PWM generates only a frequency of the first variable and the main programm never riches the second variable((
i cannot find the problem(
here is the link to the project that i compiled in AVRStudio=)
can anybode help me, please???
thanks for everybody who will answer=)

rtel wrote on Friday, January 25, 2013:

The link to the project files has been deleted from your post for two reasons:

1) It asked me for an email address to download the files.
2) Clicking on the link caused me to be redirected to inappropriate adult material.

From your email it sounds like you updated the port layer to use timer 0 in place of timer 1 because your servo motor needs timer 1, but timer 0 is not generating the tick.

Is timer 0 generating an interrupt at all?  Try creating a basic program that does nothing but configure timer 0 to generate a periodic interrupt.  When that is working add in the the FreeRTOS code and FreeRTOS interrupt handlers are installed for timer 0 instead of timer 1.

Regards.

robototechnik wrote on Friday, January 25, 2013:

oh sorry, i didnt want, i found simply the file hoster…i thought it will be okay=)
actually i dont know, im only a beginner…ill tell again what was already done:
here ist the code which im trying to run

#include "FreeRTOS.h"
#include "task.h"
#include <avr/io.h>
///////////////////////////////////////////////////////////////////////////////////////
void vServo( void *pvParameters )
{
for (;;)
{
   		OCR1A=200;											 //800ìñ/4ìñ
		OCR1B=200;
        vTaskDelay(500 / portTICK_RATE_MS); 
		OCR1A=375;											 //1500ìñ/4ìñ
		OCR1B=375;
        vTaskDelay(500 / portTICK_RATE_MS);
		OCR1A=550;											 //2200ìñ/4ìñ
		OCR1B=550;
        vTaskDelay(500 / portTICK_RATE_MS);
													
}
}
/////////////////////////////////////////////////////////////////////////////////////////////
int main( void )
{
 
TCCR1A|=(1<<COM1A1)|(1<<COM1B1)|(1<<WGM11);		 
TCCR1B|=(1<<WGM13)|(1<<WGM12)|(1<<CS11)|(1<<CS10);
	
ICR1=4999;												
	
DDRD = 0b00110000;									
 
 xTaskCreate( vServo, 
             (signed char * ) "Servo", 
             configMINIMAL_STACK_SIZE, 
             NULL, 
             1, 
             NULL );
 
 vTaskStartScheduler();
 return 0;
}

when the FreeRTOS using Timer1 the PWM for servo will not working, because of the 1000 Hz TICK RATE, the period will be 1 ms.
one man helped me, he changed the file called PORT.c(the one for ATmega 323) and now it look so

#include <stdlib.h>
#include <avr/interrupt.h>
#include "FreeRTOS.h"
#include "task.h"
#define portFLAGS_INT_ENABLED					( ( portSTACK_TYPE ) 0x80 )
#define portCLEAR_COUNTER_ON_MATCH				( ( unsigned char ) 0x08 )
#define portPRESCALE_64							( ( unsigned char ) 0x03 )
#define portCLOCK_PRESCALER						( ( unsigned long ) 64 )
#define portCOMPARE_MATCH_A_INTERRUPT_ENABLE	( ( unsigned char ) 0x10 )
typedef void tskTCB;
extern volatile tskTCB * volatile pxCurrentTCB;
#define portSAVE_CONTEXT()									\
	asm volatile (	"push	r0						\n\t"	\
					"in		r0, __SREG__			\n\t"	\
					"cli							\n\t"	\
					"push	r0						\n\t"	\
					"push	r1						\n\t"	\
					"clr	r1						\n\t"	\
					"push	r2						\n\t"	\
					"push	r3						\n\t"	\
					"push	r4						\n\t"	\
					"push	r5						\n\t"	\
					"push	r6						\n\t"	\
					"push	r7						\n\t"	\
					"push	r8						\n\t"	\
					"push	r9						\n\t"	\
					"push	r10						\n\t"	\
					"push	r11						\n\t"	\
					"push	r12						\n\t"	\
					"push	r13						\n\t"	\
					"push	r14						\n\t"	\
					"push	r15						\n\t"	\
					"push	r16						\n\t"	\
					"push	r17						\n\t"	\
					"push	r18						\n\t"	\
					"push	r19						\n\t"	\
					"push	r20						\n\t"	\
					"push	r21						\n\t"	\
					"push	r22						\n\t"	\
					"push	r23						\n\t"	\
					"push	r24						\n\t"	\
					"push	r25						\n\t"	\
					"push	r26						\n\t"	\
					"push	r27						\n\t"	\
					"push	r28						\n\t"	\
					"push	r29						\n\t"	\
					"push	r30						\n\t"	\
					"push	r31						\n\t"	\
					"lds	r26, pxCurrentTCB		\n\t"	\
					"lds	r27, pxCurrentTCB + 1	\n\t"	\
					"in		r0, 0x3d				\n\t"	\
					"st		x+, r0					\n\t"	\
					"in		r0, 0x3e				\n\t"	\
					"st		x+, r0					\n\t"	\
				);
#define portRESTORE_CONTEXT()								\
	asm volatile (	"lds	r26, pxCurrentTCB		\n\t"	\
					"lds	r27, pxCurrentTCB + 1	\n\t"	\
					"ld		r28, x+					\n\t"	\
					"out	__SP_L__, r28			\n\t"	\
					"ld		r29, x+					\n\t"	\
					"out	__SP_H__, r29			\n\t"	\
					"pop	r31						\n\t"	\
					"pop	r30						\n\t"	\
					"pop	r29						\n\t"	\
					"pop	r28						\n\t"	\
					"pop	r27						\n\t"	\
					"pop	r26						\n\t"	\
					"pop	r25						\n\t"	\
					"pop	r24						\n\t"	\
					"pop	r23						\n\t"	\
					"pop	r22						\n\t"	\
					"pop	r21						\n\t"	\
					"pop	r20						\n\t"	\
					"pop	r19						\n\t"	\
					"pop	r18						\n\t"	\
					"pop	r17						\n\t"	\
					"pop	r16						\n\t"	\
					"pop	r15						\n\t"	\
					"pop	r14						\n\t"	\
					"pop	r13						\n\t"	\
					"pop	r12						\n\t"	\
					"pop	r11						\n\t"	\
					"pop	r10						\n\t"	\
					"pop	r9						\n\t"	\
					"pop	r8						\n\t"	\
					"pop	r7						\n\t"	\
					"pop	r6						\n\t"	\
					"pop	r5						\n\t"	\
					"pop	r4						\n\t"	\
					"pop	r3						\n\t"	\
					"pop	r2						\n\t"	\
					"pop	r1						\n\t"	\
					"pop	r0						\n\t"	\
					"out	__SREG__, r0			\n\t"	\
					"pop	r0						\n\t"	\
				);
static void prvSetupTimerInterrupt( void );
portSTACK_TYPE *pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack, pdTASK_CODE pxCode, void *pvParameters )
{
unsigned short usAddress;
	*pxTopOfStack = 0x11;
	pxTopOfStack--;
	*pxTopOfStack = 0x22;
	pxTopOfStack--;
	*pxTopOfStack = 0x33;
	pxTopOfStack--;
	usAddress = ( unsigned short ) pxCode;
	*pxTopOfStack = ( portSTACK_TYPE ) ( usAddress & ( unsigned short ) 0x00ff );
	pxTopOfStack--;
	usAddress >>= 8;
	*pxTopOfStack = ( portSTACK_TYPE ) ( usAddress & ( unsigned short ) 0x00ff );
	pxTopOfStack--;
	*pxTopOfStack = ( portSTACK_TYPE ) 0x00;	
	pxTopOfStack--;
	*pxTopOfStack = portFLAGS_INT_ENABLED;
	pxTopOfStack--;
	*pxTopOfStack = ( portSTACK_TYPE ) 0x00;	/* R1 */
	pxTopOfStack--;
	*pxTopOfStack = ( portSTACK_TYPE ) 0x02;	/* R2 */
	pxTopOfStack--;
	*pxTopOfStack = ( portSTACK_TYPE ) 0x03;	/* R3 */
	pxTopOfStack--;
	*pxTopOfStack = ( portSTACK_TYPE ) 0x04;	/* R4 */
	pxTopOfStack--;
	*pxTopOfStack = ( portSTACK_TYPE ) 0x05;	/* R5 */
	pxTopOfStack--;
	*pxTopOfStack = ( portSTACK_TYPE ) 0x06;	/* R6 */
	pxTopOfStack--;
	*pxTopOfStack = ( portSTACK_TYPE ) 0x07;	/* R7 */
	pxTopOfStack--;
	*pxTopOfStack = ( portSTACK_TYPE ) 0x08;	/* R8 */
	pxTopOfStack--;
	*pxTopOfStack = ( portSTACK_TYPE ) 0x09;	/* R9 */
	pxTopOfStack--;
	*pxTopOfStack = ( portSTACK_TYPE ) 0x10;	/* R10 */
	pxTopOfStack--;
	*pxTopOfStack = ( portSTACK_TYPE ) 0x11;	/* R11 */
	pxTopOfStack--;
	*pxTopOfStack = ( portSTACK_TYPE ) 0x12;	/* R12 */
	pxTopOfStack--;
	*pxTopOfStack = ( portSTACK_TYPE ) 0x13;	/* R13 */
	pxTopOfStack--;
	*pxTopOfStack = ( portSTACK_TYPE ) 0x14;	/* R14 */
	pxTopOfStack--;
	*pxTopOfStack = ( portSTACK_TYPE ) 0x15;	/* R15 */
	pxTopOfStack--;
	*pxTopOfStack = ( portSTACK_TYPE ) 0x16;	/* R16 */
	pxTopOfStack--;
	*pxTopOfStack = ( portSTACK_TYPE ) 0x17;	/* R17 */
	pxTopOfStack--;
	*pxTopOfStack = ( portSTACK_TYPE ) 0x18;	/* R18 */
	pxTopOfStack--;
	*pxTopOfStack = ( portSTACK_TYPE ) 0x19;	/* R19 */
	pxTopOfStack--;
	*pxTopOfStack = ( portSTACK_TYPE ) 0x20;	/* R20 */
	pxTopOfStack--;
	*pxTopOfStack = ( portSTACK_TYPE ) 0x21;	/* R21 */
	pxTopOfStack--;
	*pxTopOfStack = ( portSTACK_TYPE ) 0x22;	/* R22 */
	pxTopOfStack--;
	*pxTopOfStack = ( portSTACK_TYPE ) 0x23;	/* R23 */
	pxTopOfStack--;
	usAddress = ( unsigned short ) pvParameters;
	*pxTopOfStack = ( portSTACK_TYPE ) ( usAddress & ( unsigned short ) 0x00ff );
	pxTopOfStack--;
	usAddress >>= 8;
	*pxTopOfStack = ( portSTACK_TYPE ) ( usAddress & ( unsigned short ) 0x00ff );
	pxTopOfStack--;
	*pxTopOfStack = ( portSTACK_TYPE ) 0x26;	/* R26 X */
	pxTopOfStack--;
	*pxTopOfStack = ( portSTACK_TYPE ) 0x27;	/* R27 */
	pxTopOfStack--;
	*pxTopOfStack = ( portSTACK_TYPE ) 0x28;	/* R28 Y */
	pxTopOfStack--;
	*pxTopOfStack = ( portSTACK_TYPE ) 0x29;	/* R29 */
	pxTopOfStack--;
	*pxTopOfStack = ( portSTACK_TYPE ) 0x30;	/* R30 Z */
	pxTopOfStack--;
	*pxTopOfStack = ( portSTACK_TYPE ) 0x031;	/* R31 */
	pxTopOfStack--;
	
	return pxTopOfStack;
}
portBASE_TYPE xPortStartScheduler( void )
{
	
	prvSetupTimerInterrupt();
	portRESTORE_CONTEXT();
	
	asm volatile ( "ret" );
	return pdTRUE;
}
void vPortEndScheduler( void )
{
	
}
void vPortYield( void ) __attribute__ ( ( naked ) );
void vPortYield( void )
{
	portSAVE_CONTEXT();
	vTaskSwitchContext();
	portRESTORE_CONTEXT();
	asm volatile ( "ret" );
}
/*-----------------------------------------------------------*/
void vPortYieldFromTick( void ) __attribute__ ( ( naked ) );
void vPortYieldFromTick( void )
{
	portSAVE_CONTEXT();
	vTaskIncrementTick();
	vTaskSwitchContext();
	portRESTORE_CONTEXT();
	asm volatile ( "ret" );
}
/*-----------------------------------------------------------*/
static void prvSetupTimerInterrupt( void )
{
unsigned long ocr_value=configCPU_CLOCK_HZ / configTICK_RATE_HZ; 
unsigned long temp;
unsigned char ps_value=1; 
	
	TCCR0=0; TCNT0 = 0; 
	if(ocr_value > 255) {ocr_value /= 8; ps_value = 2;}
	if(ocr_value > 255) {ocr_value /= 8; ps_value = 3;}
	if(ocr_value > 255) {ocr_value /= 4; ps_value = 4;}
	if(ocr_value > 255) {ocr_value /= 4; ps_value = 5;}
	if(ocr_value > 255) return;
	
	OCR0 = (unsigned char) ocr_value;
	TIFR = 1<<TOV0;
	TIMSK |= 1<<TOIE0;
	TCCR0 = ps_value | (1<<WGM01); 
}
#if configUSE_PREEMPTION == 1
	void SIG_OVERFLOW0( void ) __attribute__ ( ( signal, naked ) );
	void SIG_OVERFLOW0( void )
	{
		vPortYieldFromTick();
		asm volatile ( "reti" );
	}
#else
	void SIG_OVERFLOW0( void ) __attribute__ ( ( signal ) );
	void SIG_OVERFLOW0( void )
	{
		vTaskIncrementTick();
	}
#endif

now it looks like the FreeRTOS doesnt TICKs…i mean the PWM frequency is noe okay, with the period of 20ms, but the programm doesnt work, it stops at
OCR1A=200; //800ìñ/4ìñ
OCR1B=200;
vTaskDelay(500 / portTICK_RATE_MS);
and generates PWM in loop(
and i dont know the reason=(
help me please=)

rtel wrote on Friday, January 25, 2013:

As per my previous post, is the interrupt executing at all?  Are you able to successfully use the timer to generate periodic interrupts in a basic “hello world” type program without FreeRTOS?  I can’t help with the specifics of setting up a timer on an AVR, so you need to ensure the peripheral timer is executing as you want it to before you try using it with FreeRTOS.

Regards.

robototechnik wrote on Friday, January 25, 2013:

i have just tried to make another one code, and it also doesnt work….i mean it starts…a little part of the code is done and then something like sleep=)
the same situation as in the code with servos=(
can you please explain once again and siplified what should i do?=) thank you=)

edwards3 wrote on Friday, January 25, 2013:

So the interrupt is not working in a simple program without FreeRTOS? If so then you will have to get it working, but I don’t think anybody here can tell you that because it is specific to the hardware. You could loon on www.avrfreaks.net to see if you can find code for that timer.

robototechnik wrote on Friday, January 25, 2013:

no everything is working fine without FreeRTOS, but when i put this simple code into the FreeRTOS Ive found this problem with period of PWM signal and the Timer1. One man helped me to solve this problem with putting the source tick to the Timer0 to free Timer1 for servos….and it doesnt work=/
and we dont know the reason….i thought somebody from this forum can help me…???

robototechnik wrote on Friday, January 25, 2013:

the main C code and the file which we changed for putting ticking source to Timer0 from Timer1 are in the third message.
the main code shold work without problems but PORT.C…i dont know how it works at all=(
i can put also here the original PORT.C if needed

robototechnik wrote on Sunday, January 27, 2013:

is anybody here?=)

rtel wrote on Sunday, January 27, 2013:

What is it you are waiting for?  I don’t understand the problem you are describing.

As far as I can see from this thread:

- FreeRTOS works ok if you don’t change the timer used to generate the tick.
- You have to change the timer because your application code needs the timer that was originally used to generate the tick.
- After you have made the modification the tick interrupt is not working.
- It has been suggested that you get the timer interrupt working by itself, in a stand alone application, so you can be sure that your code to setup the timer and handle the timer interrupt is functioning.

Have you tried setting up the timer in a stand alone application to see if the timer peripheral is being configured correctly and that the timer interrupt is being handled correctly?  If so, I don’t understand your last couple of posts.

Regards.

robototechnik wrote on Sunday, January 27, 2013:

i hope that somebody will answer and help me…
but i didnt understand the last post…what should i do?
i know that the problem is in the PORT.C file but i really dont know how to solve it=(
could anybody help me please?its a little bit difficult to see into such a difficult code for pupil…this is the reason why i am writing here
thanks

robototechnik wrote on Monday, January 28, 2013:

tell me please if i spending my time…=(