在嵌入式系统上的简单内核中使用void指针的函数和结构的语法

时间:2011-10-15 00:47:35

标签: c void-pointers embedded

我正在为嵌入式系统类编写一个非常简单的内核。该板是TI Stellaris EKI-LM3S8962。它运行C并具有OLED显示屏。我遇到了无效指针和解引用它们的问题。非常感谢任何帮助。

我最初的小目标是证明传递函数指针和结构指针的概念。这是我访问指针batteryStatePtr所指向的var batteryState的方式,该指针是传入的数据结构的一部分吗?

void status (void* taskDataPtr) {
    // make a temporary pointer to a Status Data Struct type
    SDS* data;
    // set data equal to the void* taskDataPtr now cast as a SDS pointer
    data = (SDS*)(taskDataPtr);
    (*data->batteryStatePtr)--;
    ...

这是我的代码的一个非常简化的版本,重要的区域可以通过ctrl-f&#34来定位;这里是"

struct MyStruct {
     void (*taskPtr)(void*);
     void* taskDataPtr;
};
typedef struct MyStruct TCB;

taskPtr指向一个函数,该函数将void *作为arg并且对数据结构具有void *。作为概念证明,我尽可能小。有两个功能,状态和显示。

typedef struct DisplayDataStruct {
    uint*  batteryStatePtr;
} DDS;
DDS DisplayData;

typedef struct StatusDataStruct {
    uint* batteryStatePtr;
} SDS;
SDS StatusData;

状态通过给定的taskDataPtr递减全局变量batteryState。显示将其连接到字符串上并在OLED上显示。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef unsigned int uint;
typedef unsigned char uchar;
typedef unsigned short ushort;

void status (void* taskDataPtr);
void display (void* taskDataPtr);

void delay(uint msDelay);

//  Declare a TCB structure
struct MyStruct {
      void (*taskPtr)(void*);
      void* taskDataPtr;
};
typedef struct MyStruct TCB;

// status var
uint batteryState = 200;

typedef struct DisplayDataStruct {
    uint*  batteryStatePtr;
} DDS;
DDS DisplayData;

typedef struct StatusDataStruct {
    uint* batteryStatePtr;
} SDS;
SDS StatusData;

void main(void)
{
    DisplayData.batteryStatePtr = &batteryState;

    StatusData.batteryStatePtr = &batteryState;

      int i = 0;  //  queue index
      TCB* aTCBPtr;

      TCB* queue[2];

      TCB StatusTCB;
      TCB DisplayTCB;

      StatusTCB.taskPtr = status;
      StatusTCB.taskDataPtr = (void*)&StatusData;
      DisplayTCB.taskPtr = display;
      DisplayTCB.taskDataPtr = (void*)&DisplayData;

      // Initialize the task queue
      queue[0] = &StatusTCB;
      queue[1] = &DisplayTCB;

      // schedule and dispatch the tasks
      while(1)
      {
          for (i = 0; i < 2; i++) {
             aTCBPtr = queue[i];
             aTCBPtr->taskPtr( (void*)(aTCBPtr->taskDataPtr) );
          }
          systemState = (systemState + 1) % 100;
          delay(50);
      }
}

void status (void* taskDataPtr) {
    // return if systemState != 0 aka run once every 5 sec
    if (systemState) {
      return;
    }
    // make a temporary pointer to a Status Data Struct type
    SDS* data;
    // set data equal to the void* taskDataPtr now cast as a SDS pointer
    data = (SDS*)(taskDataPtr);


    // HERE IS where I am stumped. Is (*data->batteryStatePtr)-- the way you do this????
    // access the batteryStatePtr through the struct data
    // then dereference the whole thing to get at batteryState
    if ((*(data->batteryStatePtr)) > 0) {
      // decrement batteryState
      (*(data->batteryStatePtr))--;
    }
    return;
}

void display (void* taskDataPtr) {
    // run once every 5 sec
    if (systemState) {
      return;
    }
    DDS* data;
    data = (DDS*) taskDataPtr;
    char hold[12] = "Batt: ";
    char numHold[4];
    sprintf(numHold, "%u", (*(data->batteryStatePtr)));
    strcat(hold, numHold);

    // display the string hold
    RIT128x96x4StringDraw(hold, 15, 44, 15);
    return;
}

// use for loops to waste cycles, delay taken in ms
void delay(uint msDelay)
{
      // when i == 60000 and j == 100 function delays for ~ 7.6 sec
      msDelay = msDelay * 150 / 19;
      volatile unsigned long i = 0;
      volatile unsigned int j = 0;

      for (i = msDelay; i > 0; i--) {
             for (j = 0; j < 100; j++);
      }
      return;
}

1 个答案:

答案 0 :(得分:0)

通过void *结构获取值batteryState的方法是正确的。为清楚起见,这里是: 名为data的数据结构有一个名为batteryStatusPtr的成员。获得ptr之后,取消引用它以获得它所指向的内容。为操作顺序添加更多括号。 (不是100%肯定是否有必要,但它允许我在晚上睡觉。最后减少1。

(*(data->batteryStatusPtr))--;

在一行中,问题是在使用sprintf()将其转换为字符串并将其发送到显示函数后,该值被一些奇怪的垃圾编号损坏。我不知道为什么,但sprintf()是原因。我写了自己的uint到字符串函数,问题解决了。 sprintf在我的linux机箱上工作正常,但德州仪器LM3S8962 Lumninary Evaluation Board不喜欢它。

以下是代码的精简版评论版。因为我有点像菜鸟(在学校,有一年的Javascript编程经验,而不是C),我对任何错误都不承担任何责任。据我所知,这是最好的。也许在剥离的过程中它被打破了所以我提前道歉。

// typedef uint as an unsigned integer for reference
typedef unsigned int uint;

// typedef TCB as a structure with two elements,
// first a address of a function (actually not 100% sure about this one,
//  i'm kinda a noob but I think that's right)
// second a void pointer to a struct that stores data
struct MyStruct {
    void (*taskPtr)(void*);
    void* taskDataPtr;
};
typedef struct MyStruct TCB;

// declare a data struct SDS which holds data for the status function
// there is only one variable in there, a uint* to the batteryState
// called batteryStatePtr
typedef struct StatusDataStruct {
    uint* batteryStatePtr;
} SDS;

// declare the global variable batteryState
uint batteryState;

// declare the function status that returns void and accepts a void* taskDataPtr
void status (void* taskDataPtr);

void main() {

    // declare a status TCB
    TCB StatusTCB;
    // declare a StatusDataStructure called StatusData
    SDS StatusData;

    // set the SDS task pointer to the address of the function status
    StatusTCB.taskPtr = &status;
    // set the SDS task data pointer to the address of the StatusDataStructure
    // which is cast as a void pointer
    StatusTCB.taskDataPtr = (void*)&StatusData;

    // declare a TCB pointer task and point it at the StatusTCB
    TCB* taskPtr = &StatusTCB;

    // call the status function through the TCBPtr and send it the dataStruct
    // associated with that TCB (StatusData)
    TCBPtr->taskPtr( (void*)(TCBPtr->taskDataPtr) );
}

void status (void* taskDataPtr) {
    // make a temporary pointer to a Status Data Struct type
    SDS* data;
    // set data equal to the void* taskDataPtr now cast as a SDS pointer
    data = (SDS*)(taskDataPtr);
    // access the global variable batteryState through the data struct associated
    // with the status TCB, of type SDS
    // decrement it if greater than 0
    if ((*(data->batteryStatePtr)) > 0) {
        (*(data->batteryStatePtr))--;
    }
}