📄 4avros.c
字号:
//---------------------------------------------------------------------------------------------------------//
// __ __ ___ ____ _____ //
// / // / / |_ _______/ __ \/ ___/ //
// / // /_/ /| | | / / ___/ / / /\__ \ //
// /__ __/ ___ | |/ / / / /_/ /___/ / //
// /_/ /_/ |_|___/_/ \____//____/ //
// ____ ____ _ _ _ //
// / ___|___ ___ _ __ / ___| ___| |__ ___ __| |_ _| | ___ _ __ //
// | | / _ \ / _ \| '_ \ \___ \ / __| '_ \ / _ \/ _` | | | | |/ _ \ '__| //
// | |__| (_) | (_) | |_) | ___) | (__| | | | __/ (_| | |_| | | __/ | //
// \____\___/ \___/| .__/ |____/ \___|_| |_|\___|\__,_|\__,_|_|\___|_| //
// |_| //
// __ __ //
// / / __ __ ______ ______/ /__ ____ _ //
// / _ \/ // / / __/ // / __/ __/ |/ / ' \ //
// /_.__/\_, / \__/\_,_/_/ \__/|___/_/_/_/ //
// /___/ //
// //
// //
// Copyright 2007 by Curt Van Maanen //
// //
// Version 2007.10.06 //
//---------------------------------------------------------------------------------------------------------//
// 4AvrOS.c //
//---------------------------------------------------------------------------------------------------------//
/*-----------------------------------------------------------------------------------------------------------
___ _ _ ___ _ _ _ ___ ___ ___
|_ _| \| |/ __| | | | | | \| __/ __|
| || .` | (__| |_| |_| | |) | _|\__ \
|___|_|\_|\___|____\___/|___/|___|___/
-----------------------------------------------------------------------------------------------------------*/
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <avr/wdt.h>
#include "4AvrOS_Tasks.h" // needs to be before 4AvrOS.h
#include "4AvrOS.h"
/*-----------------------------------------------------------------------------------------------------------
___ ___ ___ ___ _ _ ___ ___
| \| __| __|_ _| \| | __/ __|
| |) | _|| _| | || .` | _|\__ \
|___/|___|_| |___|_|\_|___|___/
-----------------------------------------------------------------------------------------------------------*/
/*-----------------------------------------------------------------------------------------------------------
error codes
-----------------------------------------------------------------------------------------------------------*/
#define ERR__getSema 0x11 //argument passed to function is out of range in __getSema
#define ERR__releaseSema 0x12 //argument passed to function is out of range in __releaseSema
#define ERR__releaseSemaTN 0x13 //non-owner tried to release semaphore in __releaseSema
#define ERR__set_rtr 0x14 //invalid task number passed to function
#define ERR__clear_rtr 0x15 //invalid task number passed to function
#define ERR__get_priority 0x16 //invalid task number passed to function
#define ERR__set_priority 0x17 //invalid task number passed to function
#define ERR__set_priorityP 0x18 //invalid priority number passed to function
/*-----------------------------------------------------------------------------------------------------------
timer0 is used for the osWAIT command, with the 'wait' time of 1 is set to 10ms
the prescale is set to 8, and timer0 runs in mode 0 (normal), where the timer just counts up to 255, then
the timer goes to 0, which sets the overflow flag (timer0 keeps running)
when the overflow irq fires, it will add 256 to the timer0_acc variable, and if the variable exceeds the
number of clock cycles in 10ms (cpu freq/prescale/(1/.01)), it will enable the compareA irq which will
take care of decrementing the 'ticks' variables for the tasks
if the 'ticks' variable goes from 1 to 0, that task will then be enabled
all clock freqencies will use the same prescale and timer mode, which will cause time errors in the '10ms'
time, but will be close enough, and the error will average to 0 because the 'extra' time in the variable
timer0_acc will be left in (cpu_freq/800 is subtracted from timer0_acc), and eventually the error is
taken care of
the separated timer0 irq's are used to keep the overflow irq short (less push/pop), so that it will require
less cpu time (as it runs more often), but is not necessary to split it as I have done
-----------------------------------------------------------------------------------------------------------*/
/*-----------------------------------------------------------------------------------------------------------
timer0 registers
-----------------------------------------------------------------------------------------------------------*/
#ifdef TCCR0B
#define Timer0_Control TCCR0B
#define Timer0_Irq_Mask TIMSK0
#define Timer0_Counter TCNT0
#elif defined TCCR0
#define Timer0_Control TCCR0
#define Timer0_Irq_Mask TIMSK
#define Timer0_Counter TCNT0
#else
#error "Timer0 register names unknown."
#endif
/*-----------------------------------------------------------------------------------------------------------
timer0 prescale, defines for irq calculations
-----------------------------------------------------------------------------------------------------------*/
#define Timer0_Prescale 0x02 // prescale= clkio/8
#define Timer0_tp10ms (uint16_t)(F_CPU/8/100) // timer0 ticks per 10ms
/*-----------------------------------------------------------------------------------------------------------
defines for status byte in task info struct
-----------------------------------------------------------------------------------------------------------*/
#define RTR_ON 0x80 // mask bit for rtr status of task, 0=stopped, 1=run
#define RTR_OFF 0x00 // used to set rtr initially off
#define SEMA_BITS 0x0F // mask bits 0-3 in status for semaphore number
// 0 = none wanted, 1-15 = semaphore wanted
/*-----------------------------------------------------------------------------------------------------------
___ _ ___ ___ _ _ __ ___ ___ ___ _ ___ _ ___ ___
/ __| | / _ \| _ ) /_\ | | \ \ / /_\ | _ \_ _| /_\ | _ ) | | __/ __|
| (_ | |_| (_) | _ \/ _ \| |__ \ V / _ \| /| | / _ \| _ \ |__| _|\__ \
\___|____\___/|___/_/ \_\____| \_/_/ \_\_|_\___/_/ \_\___/____|___|___/
-----------------------------------------------------------------------------------------------------------*/
/*-----------------------------------------------------------------------------------------------------------
timer0 accumulator, keeps total count of timer0 ticks
-----------------------------------------------------------------------------------------------------------*/
uint16_t timer0_acc;
/*-----------------------------------------------------------------------------------------------------------
myTasks[] stores info about each task
-----------------------------------------------------------------------------------------------------------*/
struct ts {
uint8_t *goto_label; // store goto label address for resume of task
volatile uint8_t status; // store status data for a task, rtr/semaphore
uint8_t sch_count; // how many times waiting in the scheduler
volatile uint8_t ticks; // store wait time for the tasks
} myTasks[nTasks];
/*-----------------------------------------------------------------------------------------------------------
thisTaskP points to the current task struct, inititalize with address of the first task struct of myTasks
-----------------------------------------------------------------------------------------------------------*/
struct ts *thisTaskP = myTasks;
/*-----------------------------------------------------------------------------------------------------------
thisTaskN is the the current task number
-----------------------------------------------------------------------------------------------------------*/
uint8_t thisTaskN;
/*-----------------------------------------------------------------------------------------------------------
semaOwner[] keeps track of sema task owner
-----------------------------------------------------------------------------------------------------------*/
#if (SEMAPHORES_ON)
uint8_t semaOwner[nSemas];
#endif
/*-----------------------------------------------------------------------------------------------------------
store address and init status for each task into program memory
up to 16 tasks, can expand if more needed
-----------------------------------------------------------------------------------------------------------*/
const struct PROGMEM ta {
uint16_t addr; // address of task (function)
uint8_t init; // initial rtr and priority
} taskAddress[nTasks] = {
#ifdef __Task0
{ (uint16_t)__Task0,
(__Task0_init | ((__Task0_priority & 7) << 4)) },
#endif
#ifdef __Task1
{ (uint16_t)__Task1,
(__Task1_init | ((__Task1_priority & 7) << 4)) },
#endif
#ifdef __Task2
{ (uint16_t)__Task2,
(__Task2_init | ((__Task2_priority & 7) << 4)) },
#endif
#ifdef __Task3
{ (uint16_t)__Task3,
(__Task3_init | ((__Task3_priority & 7) << 4)) },
#endif
#ifdef __Task4
{ (uint16_t)__Task4,
(__Task4_init | ((__Task4_priority & 7) << 4)) },
#endif
#ifdef __Task5
{ (uint16_t)__Task5,
(__Task5_init | ((__Task5_priority & 7) << 4)) },
#endif
#ifdef __Task6
{ (uint16_t)__Task6,
(__Task6_init | ((__Task6_priority & 7) << 4)) },
#endif
#ifdef __Task7
{ (uint16_t)__Task7,
(__Task7_init | ((__Task7_priority & 7) << 4)) },
#endif
#ifdef __Task8
{ (uint16_t)__Task8,
(__Task8_init | ((__Task8_priority & 7) << 4)) },
#endif
#ifdef __Task9
{ (uint16_t)__Task9,
(__Task9_init | ((__Task9_priority & 7) << 4)) },
#endif
#ifdef __Task10
{ (uint16_t)__Task10,
(__Task10_init | ((__Task10_priority & 7) << 4)) },
#endif
#ifdef __Task11
{ (uint16_t)__Task11,
(__Task11_init | ((__Task11_priority & 7) << 4)) },
#endif
#ifdef __Task12
{ (uint16_t)__Task12,
(__Task12_init | ((__Task12_priority & 7) << 4)) },
#endif
#ifdef __Task13
{ (uint16_t)__Task13,
(__Task13_init | ((__Task13_priority & 7) << 4)) },
#endif
#ifdef __Task14
{ (uint16_t)__Task14,
(__Task14_init | ((__Task14_priority & 7) << 4)) },
#endif
#ifdef __Task15
{ (uint16_t)__Task15,
(__Task15_init | ((__Task15_priority & 7) << 4)) },
#endif
};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -