Я пишу чрезвычайно простое ядро для класса встроенных систем. Плата TI Stellaris EKI-LM3S8962. Он работает на C и имеет OLED-дисплей. У меня проблемы с указателями на void и отменой ссылки на них. Любая помощь очень ценится.
Моя очень маленькая первоначальная цель - доказать концепцию передачи указателей на функции и указателей на структуры вокруг. Это способ доступа к переменной batteryState, на которую указывает указатель batteryStatePtr, являющийся частью передаваемой структуры данных?
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 "HERE IS"
struct MyStruct {
void (*taskPtr)(void*);
void* taskDataPtr;
};
typedef struct MyStruct TCB;
TaskPtr указывает на функцию, которая принимает void * в качестве аргумента и имеет void * на структуру данных. В качестве доказательства концепции я начинаю как можно меньше. Есть две функции, статус и отображение.
typedef struct DisplayDataStruct {
uint* batteryStatePtr;
} DDS;
DDS DisplayData;
typedef struct StatusDataStruct {
uint* batteryStatePtr;
} SDS;
SDS StatusData;
Состояние уменьшает глобальную переменную batteryState через taskDataPtr, которое ей дано. Дисплей объединяет его в строку и показывает его на 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;
}