简体   繁体   English

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

[英]Syntax using void pointers for functions and structs in simple kernel on an embedded system

I'm writing an extremely simple kernel for an embedded systems class. 我正在为嵌入式系统类编写一个非常简单的内核。 The board is the TI Stellaris EKI-LM3S8962. 评估板是TI Stellaris EKI-LM3S8962。 It runs C and has an OLED display. 它运行C并具有OLED显示屏。 I am having issues with void pointers and de-referencing them. 我在使用void指针并取消引用它们时遇到问题。 Any help is much appreciated. 任何帮助深表感谢。

My very small initial goal is to prove the concept of passing function pointers and struct pointers around. 我很小的最初目标是证明围绕传递函数指针和结构指针的概念。 Is this the way that I access the var batteryState pointed to by the pointer batteryStatePtr which is part of the data struct passed in? 这是我访问指针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)--;
    ...

Here is a very stripped down version of my code, the important region can be located by ctrl-f "HERE IS" 这是我的代码的精简版本,重要区域可以通过ctrl -f“ HERE IS”定位

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

The taskPtr points to a function that takes a void* as an arg and has a void* to a data struct. taskPtr指向一个函数,该函数将void *作为arg并且对数据结构具有void *。 As a proof of concept I'm starting as small as possible. 作为概念的证明,我从尽可能小开始。 There are two functions, status and display. 有两个功能,状态和显示。

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

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

Status decrements the global variable batteryState through the taskDataPtr it is given. 状态通过给定的taskDataPtr递减全局变量batteryState。 Display concatenates it onto a string and shows it on the OLED. Display将其连接到字符串上,并在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;
}

The way of getting at the value batteryState through the void* structure is correct. 通过void *结构获取值batteryState的方法是正确的。 For clarity, here it is: The data structure called data has a member called batteryStatusPtr. 为了清楚起见,这里是:名为data的数据结构具有一个名为batteryStatusPtr的成员。 After getting the ptr, dereference it to get at what it is pointing at. 获取ptr后,请取消引用它以获取其指向的内容。 Add more parenthesis for order of operations. 为操作顺序添加更多括号。 (not 100% sure if those are necessary, but it allows me to sleep at night. Finally decrement it by 1. (不是100%不确定是否有必要,但这可以让我晚上入睡。最后将其递减1。

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

In one line the problem was after using sprintf() to convert it to a string, and sending it to a display function, the value became corrupted with some strange garbage number. 在一行中,问题出在使用sprintf()将其转换为字符串并将其发送到显示函数之后,该值被一些奇怪的垃圾编号损坏了。 I don't know why, but sprintf() was the cause. 我不知道为什么,但是sprintf()是原因。 I wrote my own uint to string function and the problem was solved. 我将自己的uint编写为字符串函数,问题已解决。 The sprintf worked fine on my linux box, but the Texas Instruments LM3S8962 Lumninary Evaluation Board did not like it. sprintf在我的Linux机器上运行良好,但是Texas Instruments LM3S8962 Lumninary评估板不喜欢它。

Here is a stripped down, commented version of the code. 这是该代码的简明注释版本。 As I'm a bit of a noob (in school, have a year of programming experience in Javascript, not C), I will take no responsibility for any errors. 由于我有点菜鸟(在学校里,有一年用Java语言而不是C语言进行编程的经验),因此我对任何错误概不负责。 This is to the best of my knowledge. 据我所知。 Perhaps in the process of stripping it is broken so I apologize in advance. 也许在剥离过程中它已损坏,所以我先向您道歉。

// 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))--;
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM