Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/26.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何使用定时器';使用MicroC/OS II实现任务调度的OSTMR创建?_C_Scheduled Tasks_Rtos_Nios_Microc - Fatal编程技术网

如何使用定时器';使用MicroC/OS II实现任务调度的OSTMR创建?

如何使用定时器';使用MicroC/OS II实现任务调度的OSTMR创建?,c,scheduled-tasks,rtos,nios,microc,C,Scheduled Tasks,Rtos,Nios,Microc,我在MicroC中完成了两项任务来模拟移动的车辆:控制任务和车辆任务。现在,我的项目应该用一个计时器来代替上下文切换,以获得更合适的时间,但我似乎无法完成它。程序现在使用语句ostimedlyhmm来实现句点,但软定时器应该与信号量一起使用。OSTMR在C/OS-II参考手册中创建(第16章)。我可以启动计时器,然后将其放入启动代码中,但我无法调用计时器并在两个任务之间正确同步,而将ostimedlyhmm替换为计时器。我认为我的解决方案变得比必要的更复杂,因为我可能不理解所有细节,例如为什么我

我在MicroC中完成了两项任务来模拟移动的车辆:控制任务和车辆任务。现在,我的项目应该用一个计时器来代替上下文切换,以获得更合适的时间,但我似乎无法完成它。程序现在使用语句
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() ;
}