⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 basetask.cpp

📁 a program that generates a pulse-width modulated (PWM)signal.
💻 CPP
📖 第 1 页 / 共 3 页
字号:
      }
    }
#endif  // USE_UDP

// Create the arrays needed for global storage
// Returns 1 for successful creation; 0 for error
int BaseTask::CreateGlobal(int nGlobal)
   {
   PrivateGlobalData = new double [nGlobal];
   GlobalData = new double [nGlobal];

   if((GlobalData == NULL) || (PrivateGlobalData == NULL))return(0);
   for(int i = 0; i < nGlobal; i++)
      {
      // Default values
      PrivateGlobalData[i] = GlobalData[i] = 0.0;
      }
   GlobalSize = nGlobal;
   return(1);  // Success
   }

// Copy global information from private to public view
// Returns 1 for successful; 0 for error
int BaseTask::CopyGlobal(void)
   {
   CriticalSectionBegin();
   for(int i = 0; i < GlobalSize; i++)
      {
      GlobalData[i] = PrivateGlobalData[i];
      }
   CriticalSectionEnd();
   return(1);
   }

int BaseTask::AcceptGlobal(double *pData,int nData)
    {
    // Accept global data from an external source
    if(nData != GlobalSize)
        {
        StopControl("<AcceptGlobal>Share array sizes don't match.\n");
        exit(1);
        }
    CriticalSectionBegin();
    for(int i = 0; i < GlobalSize; i++)
       {
       GlobalData[i] = pData[i];
       }
    CriticalSectionEnd();
    return(1);
    }

#ifdef USE_UDP
void StoreSharedData(int ToProc,int ToTask,int n,double *v)
    {
    // Interface from network functions to local task functions
    BaseTask *pTask = TasksByCode[ToTask];
    pTask->AcceptGlobal(v,n);
    }
#endif //  USE_UDP

double BaseTask::GetGlobalData(BaseTask *pb,int k)
    {
   CriticalSectionBegin();
   double v = pb->GlobalData[k];
   CriticalSectionEnd();
   return(v);
   }

double *BaseTask::GetGlobalArray(BaseTask *pb,int *n)
    {
    double *pv = pb->GlobalData;  // Address of global array
    *n = pb->GlobalSize;
    return(pv);
    }

#ifdef USE_UDP
int SendAll(void)
    {
    // Send out messages and shared data to other processes.
    // Messages are already copied into the outgoing packets
    // so nothing special has to be done with them.
    // Shared data must be copied from each task for transmission
    // to all other processes

    // Returns success -- 1 for OK, 0 for error

    BaseTask *pTask;
    int ProcNo,nData;
    #define BUFFER_SIZE 100
    double Buffer[BUFFER_SIZE];

    for(int i = 0; i < ntasks; i++)
        {
        // Scan all tasks
        pTask = AllTasks[i];
        ProcNo = pTask->GetTaskProcess();
        if(ProcNo != ThisProcess)continue; // Not in this process
                // therefore, don't send data
        double *pData = pTask->GetGlobalArray(pTask,&nData);
        if(nData <= 0)continue;  // No data for this task
        if(nData > BUFFER_SIZE)
            {
            StopControl("<SendAll> Global array too big.\n");
            exit(1);
            }
        CriticalSectionBegin();
        // Copy data to a local buffer
        for(int j = 0; j < nData; j++)Buffer[j] = pData[j];
        CriticalSectionEnd();

        for(int j = 0; j < NumberOfProcesses; j++)
            {
            // Send the data to all processes except this one
            if(j == ThisProcess)continue; // Don't send here
            if(InsertSharedArray(j,pTask->TaskCode,nData,Buffer))
                {
                StopControl("<SendAll> Error inserting shared data.\n");
                exit(1);
                }
            }  // Processes
        }  // Tasks
    if(SendData())  // Send out all available data
        {
        StopControl("<SendAll> Error sending data.\n");
        exit(1);
        }
    return(1);  // Normal return
    }
#else  // define a dummy
int SendAll(void){}
#endif  // USE_UDP

// Routines for handling task lists.
//  TListElement is an object to keep track of one
//    BaseTask on the list.  It includes a pointer to
//    the next item on the list.


TListElement::TListElement(BaseTask *ItemPointer)
        {
        Item = ItemPointer;
        Next = NULL;
        }

TListElement::~TListElement(void)
        {
        delete (Item);
        }

//  TList is an object to keep track of one list of
//    BaseTasks.  It includes a pointer to the firts,
//    last and current items on the list, as well as
//    methods for finding the next item on the list,
//    how many objects are on the list, and if the
//    list is empty.

TList::TList(char *aName)
        {
        First = Last = Current = NULL;
        Length = 0;
        Name = new char[strlen(aName) + 1];
        strcpy(Name, aName);
        }

TList::~TList(void)
        {
        TListElement *Element = First;
        TListElement *NextElement;

        delete [] Name;
        while (Element != NULL)
                {
                NextElement = Element->Next;
                delete (Element);
                Element = NextElement;
                }
        }

//-------------------------------------------------------
//  Method: Append
//              Add a task to the end of the list

void TList::Append(BaseTask *Item)
        {
        TListElement *Element = new TListElement(Item);

        if(IsEmpty())
                {
                First = Element;
                Last = Element;
                Current = Element;
                }
        else
                {
                Last->Next = Element;
                Last = Element;
                }
        Length ++;
        if (Item->Name != NULL)
                cout << "Added \"" << Item->Name << "\" as task: "
                  << Length << " to task list \"" << Name << "\"\n";
        else cout << "The task you ar trying to add as the "
                  << Length << "th item on the list has no name.\n";
        }

//-------------------------------------------------------
// Method: NextItem
//              Return a pointer to the next time on
//      the list and then set that item to the
//              current item.

BaseTask * TList::NextItem(void)
        {
        if (IsEmpty())
                return NULL;

        if (Current == Last)
                {
                Current = First;
                }
        else
                {
                Current = Current->Next;
                }
                return Current->Item;
        }

//-------------------------------------------------------
//  Method: IsFirst
//              True for empty list, false otherwise

int TList::IsEmpty(void)
        {
        if (First == NULL)
                return 1;
        else
                return 0;
        }

//-------------------------------------------------------
//  Method: HowLong
//              Returns how many items are on the list

int TList::HowLong(void)
        {
        return Length;
        }

// TaskDispatcher
// List1 will be run as a sequential (low priority) list
// List2 will be run as a minimum latency list
// Sequential tasks each get 1 scan per call to TaskDispatcher
// Minimum latency tasks each get as many scans as they need per call
// to TaskDispatcher
// Either list or both can be empty

int TaskDispatcher (TList *List1, TList *List2)
        {
        BaseTask *TempTask;
        int Suspend;
        int List1Num,List2Num,jmax;
        // Check to see which lists have entries to be run
        if (List2 == NULL)
                List2Num = 0;
        else
                List2Num = List2->HowLong();
        if (List1 == NULL)
                List1Num = 0;
        else
                List1Num = List1->HowLong();

        // If both lists are empty, there is nothing to do!
        if(!List1Num && !List2Num)
                return (0);
        // If both lists have entries, run them with List2 having
        // higher priority.

        if(List1Num == 0)jmax = 1;      // Run outer loop once even if List1 is empty
        else jmax = List1Num;

        for (int j=0; j < jmax; j++)
                {
                for (int i=0; i < List2Num; i++)
                        {
                        if ((TempTask = List2->NextItem()) == NULL)
                                {// Get the next Task on the list
                                cout << "\nTried to access empty task list\n";
                                return(-1);
                                }
                         Suspend = 0;
                         TempTask->StartProfile();
                         while (Suspend != 1)
                                  {
                                  Suspend = TempTask->Run();
                                  IncrementTime();
                                  if (Suspend == -1)
                                          {
                                          cout << "\nProblem running Task: " <<
                                                           TempTask->Name << "\n";
                                          TempTask->EndProfile();
                                          return(-1);
                                          }
                                  }
                        TempTask->EndProfile();
                        }
                if(List1Num == 0)break; // No items in List1
                if ((TempTask = List1->NextItem()) == NULL)
                        {// Get the next Task on the list
                        cout << "\nTried to access empty task list\n";
                        return(-1);
                        }
                TempTask->StartProfile();
                Suspend = TempTask->Run(); // Run the Task
                IncrementTime();
                TempTask->EndProfile();
                if (Suspend == -1)
                        {
                        cout << "\nProblem running Task: " <<
                                TempTask->Name << "\n";
                        return(-1);
                        }
                }
        return (0);
        }

// System dependent call to disable all maskable interrupts.
void DisableInterrupt (void)
         {
         #ifdef ISR_SCHEDULING
         _disable();
         #endif // ISR_SCHEDULING
         }

// System dependent call to enable all maskable interrupts.
void EnableInterrupt (void)
         {
         #ifdef ISR_SCHEDULING
         _enable();
         #endif // ISR_SCHEDULING
         }

// Sections of code which needs to be protected against
//  preemption should be bracketed by calls to CriticalSectionBegin()
//  and CriticalSectionEnd().  This method is preferred to diabling
//  interrupts because the interrupt helps to keep track of time
//  when the combination of interrupts and Timer0 are used.
// If the CriticalSection flag is set to 1, the scheduling in the
//  interrupt is diabled
static int CriticalSection = 0;
static int CriticalCounter = 0;  // Used to indicate when to actually end a
// critical section -- this is done so nested critical sections are handled
// properly.

// void CriticalSectionBegin (void)
//  Do not allow interrupt scheduling to occur after a call to
//  this function until CriticalSectionEnd() is subsequently called.
void CriticalSectionBegin (void)
         {
         DisableInterrupt();
         CriticalCounter++;  // Increment for each entry
         CriticalSection = 1;
         EnableInterrupt();
         }

// void CriticalSectionEnd (void)
//  Allow the interrupt to resume scheduling tasks.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -