2011-10-15 2 views
0

임베디드 시스템 클래스 용으로 매우 간단한 커널을 작성하고 있습니다. 이 보드는 TI 스텔라리스 EKI-LM3S8962이다. 그것은 C를 실행하고 OLED 디스플레이가 있습니다. void 포인터에 문제가있어이를 참조 해제합니다. 어떤 도움이라도 대단히 감사합니다.임베디드 시스템의 단순 커널에서 함수 및 구조체에 void 포인터를 사용하는 구문

아주 작은 초기 목표는 함수 포인터와 struct 포인터를 전달하는 개념을 증명하는 것입니다. 이 방법은 내가 전달하는 데이터 구조체의 일부인 포인터 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에 의해 위치 될 수있다
struct MyStruct { 
    void (*taskPtr)(void*); 
    void* taskDataPtr; 
}; 
typedef struct MyStruct TCB; 

공극을 취하는 함수로 taskPtr 포인트

* "여기" arg로 그리고 void *를 데이터 구조체에가집니다. 개념의 증거로서 나는 가능한 한 작게 시작하고 있습니다. 상태와 표시의 두 가지 기능이 있습니다.

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

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

status 전역 변수 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; 
} 
+0

'(* (data-> batteryStatePtr)) - 괜찮을 것입니다 ... 거기에 문제가 있다고 생각되는 특별한 이유가 있습니까? – Dmitri

+0

답변 해 주셔서 감사합니다. 나는 문제가 있다고 생각한다. 왜냐하면 그것이 작동하지 않고 포인터 전문성이 최소한이기 때문이다. 나는 그 문법을 쌓아 놓기를 원했을뿐입니다. 나는 알고 있습니다. – Bobby

+0

컴파일러에서 경고를 표시합니까? 그리고'systemState'는 어디에 선언 되었습니까? – Dmitri

답변

0

void * 구조를 통해 값 batteryState를 얻는 방법이 정확합니다. 명확성을 위해 다음과 같습니다. data라는 데이터 구조에는 batteryStatusPtr이라는 멤버가 있습니다. ptr을 얻은 후 역 참조하여 가리키는 부분에 도달합니다. 작업 순서에 더 많은 괄호를 추가하십시오. (사람이 필요하지만,이 날 밤에 잠을 잘 수 있도록 100 % 확실하지 않은 경우. 마지막 한 줄에 1

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

하여 감소 문제는,() 문자열로 변환하는 sprintf를 사용 후했다 표시 함수에 보내면 값이 이상한 쓰레기 번호로 손상되었습니다. 이유는 모르겠지만 sprintf()가 원인이었습니다. 문자열 함수에 내 자신의 uint를 썼고 문제가 해결되었습니다. 스프린트가 작동했습니다. 내 리눅스 박스에서는 괜찮지 만, Texas Instruments LM3S8962 Lumninary Evaluation Board는 그것을 좋아하지 않았다.

다음은 코드의 주석 처리 된 버전이다. 나는 학교에서 멍청하다. 자바 프로그래밍 경험 년, 아니 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))--; 
    } 
} 
관련 문제