我正在为嵌入式系统类编写一个非常简单的内核。该板是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;
}
答案 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))--;
}
}