FreeRTOS Port For ATmega32

balace wrote on Sunday, November 20, 2011:

I am doing a project on Atmega32. I am suppose to use FreeRTOS. I started off with the demo
project for Atmega323 and later removed the demo project files and
included mine. It all works fine and runs without errors(I am using WinAVR
and AVRStudio5).
The problem I have is running more than one task. I created
two tasks(one puts ON some LEDs and then delays for about 250ms, and the other puts OFF
the LEDs and also delays) and just one works. There is no preemption
since I created both tasks with thesame priorities. Even at different
priorities, it still doesn’t work. Preemption is enabled in the config file.
I would like to seek your help and advice because I have tried all I can
to no avail.

I found out also that FreeRTOS in my case is low-active(e.g DDRA = 0xFF
sets it as input instead) don’t know why.

rtel wrote on Monday, November 21, 2011:

How are you implementing the delays?  Using the vTaskDelay/vTaskDelayUntil or using a different method?

Can you post your code?

Regards.

balace wrote on Monday, November 21, 2011:

Thanks for the quick reply Mr Barry,  I am using vTaskDelayUntil, though I also tried with vTaskDelay and it still did not work.
Below are the tasks and some changes I made in the makefile of ATmega323 to suit ATmega32
NB: I am using an STK500 board
****************************************************************************************************

Task A:

void taskA(void *pV)
{
char *name;
name = (char*)pV;
portTickType xLastWakeTime;
xLastWakeTime = xTaskGetTickCount();

DDRA  = 0x00; // 8 Switches are connected to this port but are not used for this task
DDRC  = 0xFF;  // Eight LEDs are connected to this port

    for(;:wink:
    {
        //TODO:: Please write your application code

PORTC = 0xFF;
vTaskDelayUntil(250/portTICK_RATE_MS);

    }
}

****************************************************************************************************

Task B:

void taskB(void *pV)
{
char *name;
name = (char*)pV;
portTickType xLastWakeTime;
xLastWakeTime = xTaskGetTickCount();

    for(;:wink:
    {
        //TODO:: Please write your application code

PORTC = 0xFF;
vTaskDelayUntil(250/portTICK_RATE_MS);                    // 250ms Delay

    }
}

****************************************************************************************************
Main File:

#include <avr/io.h>
#include <util/delay.h>
#include “FreeRTOS.h”
#include “list.h”
#include “task.h”
#include “queue.h”
#include “croutine.h”
#include “timers.h”
#include “FreeRTOSConfig.h”
#include “taskA.h”
#include “taskB.h”
#include <avr/portpins.h>
#include “portable.h”
#include “timers.h”

int main(void)
{
DDRA  = 0x00;                // set port A as Input (switches are connected to this port)
DDRC  = 0xFF;               // set port B as Output (LEDs are connected to this port)

const signed char *Task_A= (const signed char *)(“My_TaskA”);
const signed char *Task_B= (const signed char *)(“my_TaskB”);

xTaskCreate(taskB, Task_A, 1000, NULL, 2, NULL );       // creates TaskB
        xTaskCreate(taskA, Task_B, 1000, NULL, 2, NULL );       // creates TaskA

vTaskStartScheduler();        // starts the Task Scheduler
for( ;; );
}

****************************************************************************************************
For the make file, the demo files were commented out and my files included. As seen below, the target and MCU name was changed amongst others. What ever is not shown here means it wasn’t altered and remains thesame for ATmega323 demo.

Makefile:

F_CPU = 8000000
# MCU name
MCU = atmega32

# Output format. (can be srec, ihex, binary)
FORMAT = ihex

# Target file name (without extension).
TARGET = AVR32PROJECT

# Optimization level, can be . 0 turns off optimization.
# (Note: 3 is not always the best optimization level. See avr-libc FAQ.)
OPT = 0

# List C source files here. (C dependencies are automatically generated.)
DEMO_DIR = …/Common/Minimal
SOURCE_DIR = …/…/Source
PORT_DIR = …/…/Source/portable/GCC/ATMega32

SRC = \
AVR32PROJECT.c \
taskA.c \
taskB.c \
$(SOURCE_DIR)/tasks.c \
$(SOURCE_DIR)/queue.c \
$(SOURCE_DIR)/list.c \
$(SOURCE_DIR)/croutine.c \
$(SOURCE_DIR)/timers.c \
$(SOURCE_DIR)/portable/MemMang/heap_1.c \
$(PORT_DIR)/port.c

#$(DEMO_DIR)/crflash.c \
#$(DEMO_DIR)/integer.c \
#$(DEMO_DIR)/PollQ.c \
#$(DEMO_DIR)/comtest.c
#main.c \
#ParTest/ParTest.c \
#serial/serial.c \
#regtest.c \

AVRDUDE_PROGRAMMER = stk500

Thanks and I gladly await your support

edwards3 wrote on Monday, November 21, 2011:

Both tasks are setting port C to the same value. Is that intended.
Have you checked that xTaskCreate() is returning pdPASS? Maybe only one task is created.

balace wrote on Monday, November 21, 2011:

hi edwards3, thanks for your reply…that wasn’t intended. TaskB was meant to set PORTC to 0x00. Its a typo.
As per your suggestion…If i create just TaskA (without TaskB), everything works fine, like wise if i create TaskB without TaskA, it also works fine. The problem comes when I create both. It seems to “hang” with the first task created. If TaskA is created first, just TaskA runs…which means the LEDs remain ON. If TaskB is created first, The LEDs remain OFF.

balace wrote on Wednesday, November 23, 2011:

Thanks to you all for your efforts…I found a solution to this problem…the stack depth is too big. After reducing this value to 500 for both tasks, everything worked fine. Any value below 500 or for both tasks that summed up to 1000(e.g 700:300, 600:400, 500:500, etc) was ok

dirtycookie wrote on Thursday, April 05, 2012:

I got a little different situation.
I took the example code and wanted to make only one task that would toogle 1 led of the stk500.
For the sake of simplicity I made 2 tasks that are defined as toggleLED6on and toggleLED6off and they are the only ones that are running.
The result is that, I only get 1 led on and that doesn’t toggle on / off.

If someone has some time to look at it, I would be greatful.
Here is the code:

#define partstALL_BITS_OUTPUT			( ( unsigned char ) 0xff )
#define partstALL_OUTPUTS_OFF			( ( unsigned char ) 0xff )
#define partstALL_OUTPUTS_ON			( ( unsigned char ) 0x00 )
void ToggleLED6on();
void ToggleLED6off();
/*
 * The task function for the "Check" task.
 */
static void vErrorChecks(void *pvParameters);
static volatile unsigned char ucCurrentOutputValue = partstALL_OUTPUTS_OFF;
/*
 * Checks the unique counts of other tasks to ensure they are still operational.
 * Flashes an LED if everything is okay. 
 */
static void prvCheckOtherTasksAreStillRunning(void);
/*
 * Called on boot to increment a count stored in the EEPROM.  This is used to 
 * ensure the CPU does not reset unexpectedly.
 */
static void prvIncrementResetCount(void);
/*
 * The idle hook is used to scheduler co-routines.
 */
void vApplicationIdleHook(void);
/*-----------------------------------------------------------*/
int main(void) {
	//prvIncrementResetCount();
	/* Setup the LED's for output. */
	vParTestInitialise();
	/* Create the standard demo tasks. */
	//vStartRegTestTasks();
	// This Task is definately responsible for the led being toggled vParTestToggleLED
	xTaskCreate(ToggleLED6on, (signed char *) "LED6on",
			configMINIMAL_STACK_SIZE, NULL, mainCHECK_TASK_PRIORITY, NULL);
	xTaskCreate(ToggleLED6off, (signed char *) "LED6off",
			configMINIMAL_STACK_SIZE, NULL, mainCHECK_TASK_PRIORITY, NULL);
	vTaskStartScheduler();
	return 0;
}
/*-----------------------------------------------------------*/
void ToggleLED6on() {
	unsigned char ucBit;
	for (;;) {
		PORTB = 0xff;
		vTaskDelay( mainCHECK_PERIOD );
	}
}
/*-----------------------------------------------------------*/
void ToggleLED6off() {
	unsigned char ucBit;
	for (;;) {
		PORTB = 0x00;
		vTaskDelay( mainCHECK_PERIOD );
	}
}

balace wrote on Thursday, April 05, 2012:

Hi dirtycookie, i’m not an expert on this but i’ll try to give some tips.

1. I suggest you remove all unused variables as they require stack, especially those defined by the tasks…e.g ucBit.

2. Check if your tasks are successfully created.

3. If the FreeRTOS was correctly implemented, then ToggleLED6off() task would turn ON the LEDs and vice-versa.

4. As off now, i think there is no mechanism to determine the exact or actual amount of stack needed by a task…so check if          your tasks are being created, if not, then increase the stack size and check again assuming all other things are OK…continue increasing the stack value and checking and you’ll get an acceptable amount.

5. configMINIMAL_STACK_SIZE is just a recommended minimum for any task…so do not just rely on this value.

Just a little observation: second parameter of xTaskCreate() should be const signed

Check the FreeRTOS manual by Richard Barry.

dirtycookie wrote on Sunday, April 08, 2012:

@balace: the atmega644 has double the flash size of the Atmega328 and 4k of ram, where I gave the heap 3.5k . The minimal stacksize is @100.

balace wrote on Monday, April 09, 2012:

@dirtycookie - Start by creating for example, ToggleLED6On() only use the XOR alternative to toggle the LED. If it works fine, disable this and create the next task and do same. It’s easier to troubleshoot this way and know which task works or does not work. Just do one at a time.

Looking at your code above, everything seems fine to me.
You should also check your initialisation and configuration files to make sure everything is correctly set and initialised.
There could be some little problems
For example, looking  at the code we can’t  determine the value of mainCHECK_PERIOD.
If this value is 0 for e.g, then the LED will appear ON because it switches (ON/OFF) so fast. So just check your definitions and initialisations.

Hint:
Like you mentioned in your initial post…“for simplicity” you created two tasks to toggle the LEDs…well depending on how you look at it, this may not be so true. If you ask me, using the XOR alternative is simpler…don’t get me wrong, your method is absolutely correct.

dirtycookie wrote on Wednesday, April 11, 2012:

@balance - thank you for being patient for seomeone being new to this subject. I rewrote everything new, along with your suggestions and it worked, though I’m not sure which one of ur suggestions are the one that brought this whole thing to work.

any thank you again.