如何使用定时器';使用MicroC/OS II实现任务调度的OSTMR创建?
我在MicroC中完成了两项任务来模拟移动的车辆:控制任务和车辆任务。现在,我的项目应该用一个计时器来代替上下文切换,以获得更合适的时间,但我似乎无法完成它。程序现在使用语句如何使用定时器';使用MicroC/OS II实现任务调度的OSTMR创建?,c,scheduled-tasks,rtos,nios,microc,C,Scheduled Tasks,Rtos,Nios,Microc,我在MicroC中完成了两项任务来模拟移动的车辆:控制任务和车辆任务。现在,我的项目应该用一个计时器来代替上下文切换,以获得更合适的时间,但我似乎无法完成它。程序现在使用语句ostimedlyhmm来实现句点,但软定时器应该与信号量一起使用。OSTMR在C/OS-II参考手册中创建(第16章)。我可以启动计时器,然后将其放入启动代码中,但我无法调用计时器并在两个任务之间正确同步,而将ostimedlyhmm替换为计时器。我认为我的解决方案变得比必要的更复杂,因为我可能不理解所有细节,例如为什么我
ostimedlyhmm
来实现句点,但软定时器应该与信号量一起使用。OSTMR在C/OS-II参考手册中创建(第16章)。我可以启动计时器,然后将其放入启动代码中,但我无法调用计时器并在两个任务之间正确同步,而将ostimedlyhmm
替换为计时器。我认为我的解决方案变得比必要的更复杂,因为我可能不理解所有细节,例如为什么我需要信号量,为什么使用计时器比内置的ostimedlyhmm
更精确。到目前为止,我的全部努力如下所示:
#include <stdio.h>
#include "system.h"
#include "includes.h"
#include "altera_avalon_pio_regs.h"
#include "sys/alt_irq.h"
#include "sys/alt_alarm.h"
#define DEBUG 1
#define HW_TIMER_PERIOD 100 /* 100ms */
/* Button Patterns */
#define GAS_PEDAL_FLAG 0x08
#define BRAKE_PEDAL_FLAG 0x04
#define CRUISE_CONTROL_FLAG 0x02
/* Switch Patterns */
#define TOP_GEAR_FLAG 0x00000002
#define ENGINE_FLAG 0x00000001
/* LED Patterns */
#define LED_RED_0 0x00000001 // Engine
#define LED_RED_1 0x00000002 // Top Gear
#define LED_GREEN_0 0x0001 // Cruise Control activated
#define LED_GREEN_2 0x0002 // Cruise Control Button
#define LED_GREEN_4 0x0010 // Brake Pedal
#define LED_GREEN_6 0x0040 // Gas Pedal
/*
* Definition of Tasks
*/
#define TASK_STACKSIZE 2048
OS_STK StartTask_Stack[TASK_STACKSIZE];
OS_STK ControlTask_Stack[TASK_STACKSIZE];
OS_STK VehicleTask_Stack[TASK_STACKSIZE];
// Task Priorities
#define STARTTASK_PRIO 5
#define VEHICLETASK_PRIO 10
#define CONTROLTASK_PRIO 12
// Task Periods
#define CONTROL_PERIOD 300
#define VEHICLE_PERIOD 300
/*
* Definition of Kernel Objects
*/
// Mailboxes
OS_EVENT *Mbox_Throttle;
OS_EVENT *Mbox_Velocity;
// Semaphores
OS_EVENT *aSemaphore;
// SW-Timer
OS_TMR *SWTimer;
OS_TMR *SWTimer1;
BOOLEAN status;
/*
* Types
*/
enum active {on, off};
enum active gas_pedal = off;
enum active brake_pedal = off;
enum active top_gear = off;
enum active engine = off;
enum active cruise_control = off;
/*
* Global variables
*/
int delay; // Delay of HW-timer
INT16U led_green = 0; // Green LEDs
INT32U led_red = 0; // Red LEDs
int sharedMemory=1;
void ContextSwitch()
{
printf("ContextSwitch!\n");
sharedMemory=sharedMemory*-1;
}
int buttons_pressed(void)
{
return ~IORD_ALTERA_AVALON_PIO_DATA(DE2_PIO_KEYS4_BASE);
}
int switches_pressed(void)
{
return IORD_ALTERA_AVALON_PIO_DATA(DE2_PIO_TOGGLES18_BASE);
}
/*
* ISR for HW Timer
*/
alt_u32 alarm_handler(void* context)
{
OSTmrSignal(); /* Signals a 'tick' to the SW timers */
return delay;
}
static int b2sLUT[] = {0x40, //0
0x79, //1
0x24, //2
0x30, //3
0x19, //4
0x12, //5
0x02, //6
0x78, //7
0x00, //8
0x18, //9
0x3F, //-
};
/*
* convert int to seven segment display format
*/
int int2seven(int inval){
return b2sLUT[inval];
}
/*
* output current velocity on the seven segement display
*/
void show_velocity_on_sevenseg(INT8S velocity){
int tmp = velocity;
int out;
INT8U out_high = 0;
INT8U out_low = 0;
INT8U out_sign = 0;
if(velocity < 0){
out_sign = int2seven(10);
tmp *= -1;
}else{
out_sign = int2seven(0);
}
out_high = int2seven(tmp / 10);
out_low = int2seven(tmp - (tmp/10) * 10);
out = int2seven(0) << 21 |
out_sign << 14 |
out_high << 7 |
out_low;
IOWR_ALTERA_AVALON_PIO_DATA(DE2_PIO_HEX_LOW28_BASE,out);
}
/*
* shows the target velocity on the seven segment display (HEX5, HEX4)
* when the cruise control is activated (0 otherwise)
*/
void show_target_velocity(INT8U target_vel)
{
}
/*
* indicates the position of the vehicle on the track with the four leftmost red LEDs
* LEDR17: [0m, 400m)
* LEDR16: [400m, 800m)
* LEDR15: [800m, 1200m)
* LEDR14: [1200m, 1600m)
* LEDR13: [1600m, 2000m)
* LEDR12: [2000m, 2400m]
*/
void show_position(INT16U position)
{
}
/*
* The function 'adjust_position()' adjusts the position depending on the
* acceleration and velocity.
*/
INT16U adjust_position(INT16U position, INT16S velocity,
INT8S acceleration, INT16U time_interval)
{
INT16S new_position = position + velocity * time_interval / 1000
+ acceleration / 2 * (time_interval / 1000) * (time_interval / 1000);
if (new_position > 24000) {
new_position -= 24000;
} else if (new_position < 0){
new_position += 24000;
}
show_position(new_position);
return new_position;
}
/*
* The function 'adjust_velocity()' adjusts the velocity depending on the
* acceleration.
*/
INT16S adjust_velocity(INT16S velocity, INT8S acceleration,
enum active brake_pedal, INT16U time_interval)
{
INT16S new_velocity;
INT8U brake_retardation = 200;
if (brake_pedal == off)
new_velocity = velocity + (float) (acceleration * time_interval) / 1000.0;
else {
if (brake_retardation * time_interval / 1000 > velocity)
new_velocity = 0;
else
new_velocity = velocity - brake_retardation * time_interval / 1000;
}
return new_velocity;
}
/*
* The task 'VehicleTask' updates the current velocity of the vehicle
*/
void VehicleTask(void* pdata)
{
INT8U err;
void* msg;
INT8U* throttle;
INT8S acceleration; /* Value between 40 and -20 (4.0 m/s^2 and -2.0 m/s^2) */
INT8S retardation; /* Value between 20 and -10 (2.0 m/s^2 and -1.0 m/s^2) */
INT16U position = 0; /* Value between 0 and 20000 (0.0 m and 2000.0 m) */
INT16S velocity = 0; /* Value between -200 and 700 (-20.0 m/s amd 70.0 m/s) */
INT16S wind_factor; /* Value between -10 and 20 (2.0 m/s^2 and -1.0 m/s^2) */
printf("Vehicle task created!\n");
while(1)
{
err = OSMboxPost(Mbox_Velocity, (void *) &velocity);
OSTimeDlyHMSM(0,0,0,VEHICLE_PERIOD);
/* Non-blocking read of mailbox:
- message in mailbox: update throttle
- no message: use old throttle
*/
msg = OSMboxPend(Mbox_Throttle, 1, &err);
if (err == OS_NO_ERR)
throttle = (INT8U*) msg;
/* Retardation : Factor of Terrain and Wind Resistance */
if (velocity > 0)
wind_factor = velocity * velocity / 10000 + 1;
else
wind_factor = (-1) * velocity * velocity / 10000 + 1;
if (position < 4000)
retardation = wind_factor; // even ground
else if (position < 8000)
retardation = wind_factor + 15; // traveling uphill
else if (position < 12000)
retardation = wind_factor + 25; // traveling steep uphill
else if (position < 16000)
retardation = wind_factor; // even ground
else if (position < 20000)
retardation = wind_factor - 10; //traveling downhill
else
retardation = wind_factor - 5 ; // traveling steep downhill
acceleration = *throttle / 2 - retardation;
position = adjust_position(position, velocity, acceleration, 300);
velocity = adjust_velocity(velocity, acceleration, brake_pedal, 300);
printf("Position: %dm\n", position / 10);
printf("Velocity: %4.1fm/s\n", velocity /10.0);
printf("Throttle: %dV\n", *throttle / 10);
show_velocity_on_sevenseg((INT8S) (velocity / 10));
}
}
/*
* The task 'ControlTask' is the main task of the application. It reacts
* on sensors and generates responses.
*/
void ControlTask(void* pdata)
{
INT8U err;
INT8U throttle = 40; /* Value between 0 and 80, which is interpreted as between 0.0V and 8.0V */
void* msg;
INT16S* current_velocity;
printf("Control Task created!\n");
while(1)
{
msg = OSMboxPend(Mbox_Velocity, 0, &err);
current_velocity = (INT16S*) msg;
err = OSMboxPost(Mbox_Throttle, (void *) &throttle);
OSTimeDlyHMSM(0,0,0, CONTROL_PERIOD);
}
}
/*
* The task 'StartTask' creates all other tasks kernel objects and
* deletes itself afterwards.
*/
void StartTask(void* pdata)
{
INT8U err;
void* context;
static alt_alarm alarm; /* Is needed for timer ISR function */
/* Base resolution for SW timer : HW_TIMER_PERIOD ms */
delay = alt_ticks_per_second() * HW_TIMER_PERIOD / 1000;
printf("delay in ticks %d\n", delay);
/*
* Create Hardware Timer with a period of 'delay'
*/
if (alt_alarm_start (&alarm,
delay,
alarm_handler,
context) < 0)
{
printf("No system clock available!n");
}
/*
* Create and start Software Timer
*/
SWTimer = OSTmrCreate(0,
CONTROL_PERIOD/(4*OS_TMR_CFG_TICKS_PER_SEC),
OS_TMR_OPT_PERIODIC,
ContextSwitch,
NULL,
NULL,
&err);
if (err == OS_ERR_NONE) {
/* Timer was created but NOT started */
printf("SWTimer was created but NOT started \n");
}
status = OSTmrStart(SWTimer,
&err);
if (err == OS_ERR_NONE) {
/* Timer was started */
printf("SWTimer was started!\n");
}
/*
* Creation of Kernel Objects
*/
// Mailboxes
Mbox_Throttle = OSMboxCreate((void*) 0); /* Empty Mailbox - Throttle */
Mbox_Velocity = OSMboxCreate((void*) 0); /* Empty Mailbox - Velocity */
/*
* Create statistics task
*/
OSStatInit();
/*
* Creating Tasks in the system
*/
err = OSTaskCreateExt(
ControlTask, // Pointer to task code
NULL, // Pointer to argument that is
// passed to task
&ControlTask_Stack[TASK_STACKSIZE-1], // Pointer to top
// of task stack
CONTROLTASK_PRIO,
CONTROLTASK_PRIO,
(void *)&ControlTask_Stack[0],
TASK_STACKSIZE,
(void *) 0,
OS_TASK_OPT_STK_CHK);
err = OSTaskCreateExt(
VehicleTask, // Pointer to task code
NULL, // Pointer to argument that is
// passed to task
&VehicleTask_Stack[TASK_STACKSIZE-1], // Pointer to top
// of task stack
VEHICLETASK_PRIO,
VEHICLETASK_PRIO,
(void *)&VehicleTask_Stack[0],
TASK_STACKSIZE,
(void *) 0,
OS_TASK_OPT_STK_CHK);
printf("All Tasks and Kernel Objects generated!\n");
/* Task deletes itself */
OSTaskDel(OS_PRIO_SELF);
}
/*
*
* The function 'main' creates only a single task 'StartTask' and starts
* the OS. All other tasks are started from the task 'StartTask'.
*
*/
int main(void) {
printf("Cruise Control\n");
aSemaphore = OSSemCreate(1); // binary semaphore (1 key)
OSTaskCreateExt(
StartTask, // Pointer to task code
NULL, // Pointer to argument that is
// passed to task
(void *)&StartTask_Stack[TASK_STACKSIZE-1], // Pointer to top
// of task stack
STARTTASK_PRIO,
STARTTASK_PRIO,
(void *)&StartTask_Stack[0],
TASK_STACKSIZE,
(void *) 0,
OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR);
OSStart();
return 0;
}
更新141001 15:57 CET
2个信号灯+2个计时器似乎是一个很好的改进。我希望它能被检查或测试
#include <stdio.h>
#include "system.h"
#include "includes.h"
#include "altera_avalon_pio_regs.h"
#include "sys/alt_irq.h"
#include "sys/alt_alarm.h"
#define DEBUG 1
#define HW_TIMER_PERIOD 100 /* 100ms */
/* Button Patterns */
#define GAS_PEDAL_FLAG 0x08
#define BRAKE_PEDAL_FLAG 0x04
#define CRUISE_CONTROL_FLAG 0x02
/* Switch Patterns */
#define TOP_GEAR_FLAG 0x00000002
#define ENGINE_FLAG 0x00000001
/* LED Patterns */
#define LED_RED_0 0x00000001 // Engine
#define LED_RED_1 0x00000002 // Top Gear
#define LED_GREEN_0 0x0001 // Cruise Control activated
#define LED_GREEN_2 0x0002 // Cruise Control Button
#define LED_GREEN_4 0x0010 // Brake Pedal
#define LED_GREEN_6 0x0040 // Gas Pedal
/*
* Definition of Tasks
*/
#define TASK_STACKSIZE 2048
OS_STK StartTask_Stack[TASK_STACKSIZE];
OS_STK ControlTask_Stack[TASK_STACKSIZE];
OS_STK VehicleTask_Stack[TASK_STACKSIZE];
// Task Priorities
#define STARTTASK_PRIO 5
#define VEHICLETASK_PRIO 10
#define CONTROLTASK_PRIO 12
// Task Periods
#define CONTROL_PERIOD 300
#define VEHICLE_PERIOD 300
/*
* Definition of Kernel Objects
*/
// Mailboxes
OS_EVENT *Mbox_Throttle;
OS_EVENT *Mbox_Velocity;
// Semaphores
OS_EVENT *aSemaphore;
OS_EVENT *aSemaphore2;
// SW-Timer
OS_TMR *SWTimer;
OS_TMR *SWTimer1;
BOOLEAN status;
/*
* Types
*/
enum active {on, off};
enum active gas_pedal = off;
enum active brake_pedal = off;
enum active top_gear = off;
enum active engine = off;
enum active cruise_control = off;
/*
* Global variables
*/
int delay; // Delay of HW-timer
INT16U led_green = 0; // Green LEDs
INT32U led_red = 0; // Red LEDs
int sharedMemory=1;
void TimerCallback(params)
{
// Post to the semaphore to signal that it's time to run the task.
OSSemPost(aSemaphore); // Releasing the key
}
void ContextSwitch()
{
printf("ContextSwitch!\n");
sharedMemory=sharedMemory*-1;
}
int buttons_pressed(void)
{
return ~IORD_ALTERA_AVALON_PIO_DATA(DE2_PIO_KEYS4_BASE);
}
int switches_pressed(void)
{
return IORD_ALTERA_AVALON_PIO_DATA(DE2_PIO_TOGGLES18_BASE);
}
/*
* ISR for HW Timer
*/
alt_u32 alarm_handler(void* context)
{
OSTmrSignal(); /* Signals a 'tick' to the SW timers */
return delay;
}
void release()
{
printf("release key!\n");
//OSSemPost(aSemaphore); // Releasing the key
OSSemPost(aSemaphore2); // Releasing the key
printf("released key!\n");
}
void release2()
{
printf("release2!\n");
OSSemPost(aSemaphore2); // Releasing the key
printf("release2!\n");
}
static int b2sLUT[] = {0x40, //0
0x79, //1
0x24, //2
0x30, //3
0x19, //4
0x12, //5
0x02, //6
0x78, //7
0x00, //8
0x18, //9
0x3F, //-
};
/*
* convert int to seven segment display format
*/
int int2seven(int inval){
return b2sLUT[inval];
}
/*
* output current velocity on the seven segement display
*/
void show_velocity_on_sevenseg(INT8S velocity){
int tmp = velocity;
int out;
INT8U out_high = 0;
INT8U out_low = 0;
INT8U out_sign = 0;
if(velocity < 0){
out_sign = int2seven(10);
tmp *= -1;
}else{
out_sign = int2seven(0);
}
out_high = int2seven(tmp / 10);
out_low = int2seven(tmp - (tmp/10) * 10);
out = int2seven(0) << 21 |
out_sign << 14 |
out_high << 7 |
out_low;
IOWR_ALTERA_AVALON_PIO_DATA(DE2_PIO_HEX_LOW28_BASE,out);
}
/*
* shows the target velocity on the seven segment display (HEX5, HEX4)
* when the cruise control is activated (0 otherwise)
*/
void show_target_velocity(INT8U target_vel)
{
}
/*
* indicates the position of the vehicle on the track with the four leftmost red LEDs
* LEDR17: [0m, 400m)
* LEDR16: [400m, 800m)
* LEDR15: [800m, 1200m)
* LEDR14: [1200m, 1600m)
* LEDR13: [1600m, 2000m)
* LEDR12: [2000m, 2400m]
*/
void show_position(INT16U position)
{
}
/*
* The function 'adjust_position()' adjusts the position depending on the
* acceleration and velocity.
*/
INT16U adjust_position(INT16U position, INT16S velocity,
INT8S acceleration, INT16U time_interval)
{
INT16S new_position = position + velocity * time_interval / 1000
+ acceleration / 2 * (time_interval / 1000) * (time_interval / 1000);
if (new_position > 24000) {
new_position -= 24000;
} else if (new_position < 0){
new_position += 24000;
}
show_position(new_position);
return new_position;
}
/*
* The function 'adjust_velocity()' adjusts the velocity depending on the
* acceleration.
*/
INT16S adjust_velocity(INT16S velocity, INT8S acceleration,
enum active brake_pedal, INT16U time_interval)
{
INT16S new_velocity;
INT8U brake_retardation = 200;
if (brake_pedal == off)
new_velocity = velocity + (float) (acceleration * time_interval) / 1000.0;
else {
if (brake_retardation * time_interval / 1000 > velocity)
new_velocity = 0;
else
new_velocity = velocity - brake_retardation * time_interval / 1000;
}
return new_velocity;
}
/*
* The task 'VehicleTask' updates the current velocity of the vehicle
*/
void VehicleTask(void* pdata)
{
INT8U err;
void* msg;
INT8U* throttle;
INT8S acceleration; /* Value between 40 and -20 (4.0 m/s^2 and -2.0 m/s^2) */
INT8S retardation; /* Value between 20 and -10 (2.0 m/s^2 and -1.0 m/s^2) */
INT16U position = 0; /* Value between 0 and 20000 (0.0 m and 2000.0 m) */
INT16S velocity = 0; /* Value between -200 and 700 (-20.0 m/s amd 70.0 m/s) */
INT16S wind_factor; /* Value between -10 and 20 (2.0 m/s^2 and -1.0 m/s^2) */
printf("Vehicle task created!\n");
// Create a semaphore to represent the "it's time to run" event.
// Initialize the semaphore count to zero because it's not time
// to run yet.
// Create a periodic software timer which calls TimerCallback()
// when it expires.
/*
* Create and start Software Timer
*/
SWTimer1 = OSTmrCreate(0,
CONTROL_PERIOD/(4*OS_TMR_CFG_TICKS_PER_SEC),
OS_TMR_OPT_PERIODIC,
TimerCallback,
NULL,
NULL,
&err);
if (err == OS_ERR_NONE) {
/* Timer was created but NOT started */
printf("SWTimer1 was created but NOT started \n");
}
status = OSTmrStart(SWTimer1,
&err);
if (err == OS_ERR_NONE) {
/* Timer was started */
printf("SWTimer1 was started!\n");
}
while(1)
{
OSSemPend(aSemaphore, 0, &err); // Trying to access the key
err = OSMboxPost(Mbox_Velocity, (void *) &velocity);
//OSTimeDlyHMSM(0,0,0,VEHICLE_PERIOD);
/* Non-blocking read of mailbox:
- message in mailbox: update throttle
- no message: use old throttle
*/
msg = OSMboxPend(Mbox_Throttle, 1, &err);
if (err == OS_NO_ERR)
throttle = (INT8U*) msg;
/* Retardation : Factor of Terrain and Wind Resistance */
if (velocity > 0)
wind_factor = velocity * velocity / 10000 + 1;
else
wind_factor = (-1) * velocity * velocity / 10000 + 1;
if (position < 4000)
retardation = wind_factor; // even ground
else if (position < 8000)
retardation = wind_factor + 15; // traveling uphill
else if (position < 12000)
retardation = wind_factor + 25; // traveling steep uphill
else if (position < 16000)
retardation = wind_factor; // even ground
else if (position < 20000)
retardation = wind_factor - 10; //traveling downhill
else
retardation = wind_factor - 5 ; // traveling steep downhill
acceleration = *throttle / 2 - retardation;
position = adjust_position(position, velocity, acceleration, 300);
velocity = adjust_velocity(velocity, acceleration, brake_pedal, 300);
printf("Position: %dm\n", position / 10);
printf("Velocity: %4.1fm/s\n", velocity /10.0);
printf("Throttle: %dV\n", *throttle / 10);
show_velocity_on_sevenseg((INT8S) (velocity / 10));
//OSSemPost(aSemaphore); // Releasing the key
}
}
/*
* The task 'ControlTask' is the main task of the application. It reacts
* on sensors and generates responses.
*/
void ControlTask(void* pdata)
{
INT8U err;
INT8U throttle = 40; /* Value between 0 and 80, which is interpreted as between 0.0V and 8.0V */
void* msg;
INT16S* current_velocity;
printf("Control Task created!\n");
while(1)
{
OSSemPend(aSemaphore2, 0, &err); // Trying to access the key
msg = OSMboxPend(Mbox_Velocity, 0, &err);
current_velocity = (INT16S*) msg;
printf("Control Task!\n");
err = OSMboxPost(Mbox_Throttle, (void *) &throttle);
//OSSemPost(aSemaphore2); // Releasing the key
//OSTimeDlyHMSM(0,0,0, CONTROL_PERIOD);
}
}
/*
* The task 'StartTask' creates all other tasks kernel objects and
* deletes itself afterwards.
*/
void StartTask(void* pdata)
{
INT8U err;
void* context;
static alt_alarm alarm; /* Is needed for timer ISR function */
/* Base resolution for SW timer : HW_TIMER_PERIOD ms */
delay = alt_ticks_per_second() * HW_TIMER_PERIOD / 1000;
printf("delay in ticks %d\n", delay);
/*
* Create Hardware Timer with a period of 'delay'
*/
if (alt_alarm_start (&alarm,
delay,
alarm_handler,
context) < 0)
{
printf("No system clock available!n");
}
/*
* Create and start Software Timer
*/
SWTimer = OSTmrCreate(0,
CONTROL_PERIOD/(4*OS_TMR_CFG_TICKS_PER_SEC),
OS_TMR_OPT_PERIODIC,
release,
NULL,
NULL,
&err);
if (err == OS_ERR_NONE) {
/* Timer was created but NOT started */
printf("SWTimer was created but NOT started \n");
}
status = OSTmrStart(SWTimer,
&err);
if (err == OS_ERR_NONE) {
/* Timer was started */
printf("SWTimer was started!\n");
}
/*
* Creation of Kernel Objects
*/
// Mailboxes
Mbox_Throttle = OSMboxCreate((void*) 0); /* Empty Mailbox - Throttle */
Mbox_Velocity = OSMboxCreate((void*) 0); /* Empty Mailbox - Velocity */
/*
* Create statistics task
*/
OSStatInit();
/*
* Creating Tasks in the system
*/
err = OSTaskCreateExt(
ControlTask, // Pointer to task code
NULL, // Pointer to argument that is
// passed to task
&ControlTask_Stack[TASK_STACKSIZE-1], // Pointer to top
// of task stack
CONTROLTASK_PRIO,
CONTROLTASK_PRIO,
(void *)&ControlTask_Stack[0],
TASK_STACKSIZE,
(void *) 0,
OS_TASK_OPT_STK_CHK);
err = OSTaskCreateExt(
VehicleTask, // Pointer to task code
NULL, // Pointer to argument that is
// passed to task
&VehicleTask_Stack[TASK_STACKSIZE-1], // Pointer to top
// of task stack
VEHICLETASK_PRIO,
VEHICLETASK_PRIO,
(void *)&VehicleTask_Stack[0],
TASK_STACKSIZE,
(void *) 0,
OS_TASK_OPT_STK_CHK);
printf("All Tasks and Kernel Objects generated!\n");
/* Task deletes itself */
OSTaskDel(OS_PRIO_SELF);
}
/*
*
* The function 'main' creates only a single task 'StartTask' and starts
* the OS. All other tasks are started from the task 'StartTask'.
*
*/
int main(void) {
printf("Cruise Control 2014\n");
aSemaphore = OSSemCreate(1); // binary semaphore (1 key)
aSemaphore2 = OSSemCreate(0); // binary semaphore (1 key)
OSTaskCreateExt(
StartTask, // Pointer to task code
NULL, // Pointer to argument that is
// passed to task
(void *)&StartTask_Stack[TASK_STACKSIZE-1], // Pointer to top
// of task stack
STARTTASK_PRIO,
STARTTASK_PRIO,
(void *)&StartTask_Stack[0],
TASK_STACKSIZE,
(void *) 0,
OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR);
OSStart();
return 0;
}
ostimedlyhmm()
此调用允许您以小时为单位指定延迟时间,
分钟、秒和毫秒,而不是滴答声。这意味着在适当的时间结束之前,你不会让一项任务工作。即使所有其他任务都已工作和/或CPU处于“空闲”状态,您的任务也不会继续工作,直到适当的时间点(在您的情况下为秒或其他时间点)结束。如果你真的需要一个事件在如此“重大”的时间之后发生,当然它仍然值得使用
然而,定时器的使用方法不应与信号量混淆。后者用于防止数据冲突,并保护共享资源或代码的关键部分不被多次重入
在不深入挖掘代码的情况下,我建议尽可能使用
ostimely()
组织系统。对于信号量,当多个任务可以异步调用同一函数或访问同一资源(如内存、寄存器、数据总线或任何硬件)时,请使用它们 我的印象是,您有两项任务需要定期运行。你想用一个软件定时器和信号量来完成这个任务。如果这是正确的,那么您可以按如下方式完成
每个任务将使用自己的信号量和计时器。信号量可用作事件发生的信号。在这种情况下,使用信号量来指示计时器已过期,任务已到运行时间。将软件计时器设置为定期过期,并调用回调函数。回调函数应该发送到信号量。任务应该挂起其while循环中的信号量。这样,每当计时器过期时,任务都会在循环中运行一次迭代
以下是一些psuedo代码:
void TimerCallback(params)
{
// Post to the semaphore to signal that it's time to run the task.
}
void TaskFunction(void)
{
// Create a semaphore to represent the "it's time to run" event.
// Initialize the semaphore count to zero because it's not time
// to run yet.
// Create a periodic software timer which calls TimerCallback()
// when it expires.
while(1)
{
// Wait until it's time to run by pending on the semaphore.
// Do task specific stuff.
}
}
此软件计时器和信号量实现的周期性比使用ostimedlyhmm()更精确。原因是软件计时器周期的运行与任务的执行时间无关。但是ostimedlyhmm()的时间段是任务执行时间之外的时间段。如果任务被其他任务或中断抢占,则任务的执行时间可能因一次迭代到下一次迭代而不同。因此,使用ostimedlyhmm()不是获取周期性事件的非常精确的方法。对于周期性进程,
ostimedlyhmm()
和OSTimeDly()
的问题在于,它们没有考虑线程其余部分的处理时间。例如:
// Task loop
for(;;)
{
OSTimeDly( 100 ) ;
doStuffHere() ;
}
您可能希望dostufhere()
每隔100个刻度运行一次,除非dostufhere()
本身需要更长的1个刻度周期。例如,它本身可能包含延迟,或某个其他事件的阻塞
// Task loop
for(;;)
{
OSTimeDly( 100 ) ;
doStuffHere() ;
}
通过使用计时器,可以克服这一问题:
// Note this is illustrative and not uC/OS-II code
timer_handle = createTimer( 100, PERIODIC ) ;
// Task loop
for(;;)
{
waitForTimer( timer_handle ) ;
doStuffHere() ;
}
在这里,dostufhere()
只需要不到100个刻度,循环就完全是周期性的,这比一个刻度要好得多
所有这些都表明,如果您可以保证dostufhere()
所需的时间不到一个刻度-即使被优先级更高的任务抢先,那么延迟也要简单得多
另一方面,使用计时器的另一个优点是,延迟上的阻塞只能对延迟到期作出反应,而信号量上的任务阻塞可以对发出信号量的任何事件作出反应,因此可以导致在包括计时器在内的多个事件上运行。类似地,对于其他IPC机制,如队列或事件标志。您必须使用信号量来同步ControlTask和VehicletTask,还是只能使用OSMbox?如果您不必使用信号量,您可以尝试删除
ostimedlyhmm()
,并将OSMboxPend()
中的等待时间增加到所需的值,例如VEHICLE\u PERIOD
或CONTROL\u PERIOD
@SSC,这非常有趣。但这是一个大学项目,教授明确指示我使用信号量“连接”计时器(复数形式,因此我假设我应该使用两个计时器)。我可以运行和更改代码,但如果在没有ostimedlyhmm()
的情况下使用信号量,我在同步任务和获取竞争密码方面会遇到问题。我也不完全理解为什么软件计时器应该比bultin功能更精确,我认为我应该使用2个计时器+信号量来进行更精确的任务调度/上下文切换。在这种情况下,您可以尝试创建两次和两个信号量(每个任务一个)。在每个计时器的回调处理程序(例如代码中的报警处理程序()
)中,执行OSSemPost()
。在车辆任务
和控制任务
开始时,执行OSSemPend()
,超时值为0(表示永远等待)。因此,当计时器关闭时,您的任务可以运行一个循环并在信号灯旁停止,等待下一个计时器关闭。@SSC我认为这会起作用。我要试试看
// Task loop
for(;;)
{
OSTimeDly( 100 ) ;
doStuffHere() ;
}
// Note this is illustrative and not uC/OS-II code
timer_handle = createTimer( 100, PERIODIC ) ;
// Task loop
for(;;)
{
waitForTimer( timer_handle ) ;
doStuffHere() ;
}