I'm getting an error on a struct call inside a function. In the code, I am converting two bytes of data into one 16-bit data and I want to store it into one of my struct variables. However, I am getting an error that I can't pinpoint. The compiler is telling me that the error is in the line unsigned int fat.sector_size = combinedBytes;. What am I doing wrong here? Thanks in advance!
EDIT: The error that I'm getting is
main.c:62:19: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘.’ token
main.c:62:19: error: expected expression before ‘.’ token`
struct fileSystem_info{
unsigned int sector_size; //Sector size
int cluster_size_in_sectors; //Cluster size in sectors
int entries_in_root_directory; //Number of entries in root directory
int sectors_per_fat; //Sectors per file allocation table
int reserved_sectors; //Number of reserved sectors on the disk
int hidden_sectors; //Number of hidden sectors on the disk
int sector_number_of_first_copy_of_fat; //Sector number of the first copy of the file allocation table
int sector_number_of_first_sector_of_root_directory; //Sector number of the first sector of the root directory
int sector_numner_of_first_sector_of_first_usable_data_cluster; //Sector number of the first sector of the first usable data cluster
};
//Converts two 8 bit data to one 16 bit data
unsigned converter(unsigned mostSignificant_bit, unsigned leastSignificant_bit){
uint16_t value = (uint16_t)(mostSignificant_bit << 8) | leastSignificant_bit;
//return((mostSignificant_bit * 256) + leastSignificant_bit);
return (value);
}
unsigned int sectorSize (){
struct fileSystem_info fat;
unsigned char first_byte = buffer[11];
printf("%hhu \n", first_byte);
unsigned char second_byte = buffer[12];
printf("%hhu \n", second_byte);
unsigned int combinedBytes = converter ((int)second_byte, (int)first_byte);
unsigned int fat.sector_size = combinedBytes;
return (combinedBytes);
}
Here
unsigned int fat.sector_size = combinedBytes;
remove the type
fat.sector_size = combinedBytes;
(... and perhaps have a break ... ;-)
Refering the question on version-info in the comments below:
Do something like this:
#define VERSION_MAJOR (0) /* \ */
#define VERSION_MINOR (1) /* +--<-- adjust those for upcoming releases. */
#define VERSION_MICRO (42) /* / */
struct fileSystem_info
{
unsigned int version;
unsigned int sector_size; //Sector size
...
When initialising an instance of struct fileSystem_info, do:
struct fileSystem_info fsi = {0};
fsi.version = (VERSION_MAJOR << 24) | (VERSION_MINOR << 16) | VERSION_MICRO};
Doing so allows you a maximum version number of 255.255.65535.
As you always write version to disk you could later determine which version you wrote by reading the first unsigned int version from the structure an then in decide how to go on reading. This might be relevant in case the structure and how its content is to be interpreted following version changed during the different releases of your program.
An identifier cannot have ..
At
unsigned int fat.sector_size = combinedBytes;
you are defining a new variable of unsigned int type, called fat.sector_size (which is an invalid identifier.
If you want to refer to the member sector_size of the fat variable, don't use the syntax for variable definition. Just write
fat.sector_size = combinedBytes;
Related
I have a problem to understand how I can use this macro to get the lenght of the IP header. I have a file called framehdr.h and I have included that file in my main.c. The struct in the framehdr.h file look like this:
struct ip_hdr {
unsigned char vhl; /* Version and header length */
unsigned char tos; /* Type of service */
unsigned short len; /* Total length */
unsigned short id; /* Identification */
unsigned short off; /* Fragment offset field */
unsigned char ttl; /* Time to live */
unsigned char p; /* Protocol */
unsigned short ip_sum; /* Checksum */
unsigned int src, dst; /* Source and dest address */
};
I can manually get the lentgh by adding all the sizes like this:
unsigned int sizeIP = sizeof(testOne.vhl) + sizeof(testOne.tos) +
sizeof(testOne.len) + sizeof(testOne.id) +
sizeof(testOne.off) + sizeof(testOne.ttl) +
sizeof(testOne.p) + sizeof(testOne.ip_sum) +
sizeof(testOne.src) + sizeof(testOne.dst);
But I'm suppose to use the macro that look like this to get the size:
#define IP_HL(ip) ((((ip)->vhl) & 0x0f) * 4)
What does this macro return? Is it a digit so I can store it in a int and then print it or how does it work?
It looks like vhl (which is an 8 bit member, unless CHAR_BIT is a weird value on your platform) is used to store the version in the significant 4 bits and the header length in the other 4 bits.
((ip)->vhl) & 0x0f) extracts the least significant 4 bits of the vhl member of the struct to which ip is pointing.
The multiplication by 4 to get the actual length is merely obeying the conventions of that member.
The way you are using sizeof to "manually get the length" is making assumptions about the header length corresponding to the sum of the sizes of the individual members. Member padding and undocumented conventions centred around the serialisation technique used for your struct might mean this is not the case.
Within a struct I need some space where I can put in something. This space have to be able to collect all data types, so I want to define an union. The space is limited to n bytes (unsigned char).
How do I have to define my union, so that it can contain char, int, float and so on?
Have I to do it this way?
#define SIZE (128)
union {
unsigned char uchar[SIZE];
char schar[SIZE];
unsigned int uint[SIZE/sizeof(unsigned int)];
int sint[SIZE/sizeof(int)];
float flt[SIZE/sizeof(float)];
double dbl[SIZE/sizeof(double)];
}memory;
Or is there a possibility to define only the size of the unsigned char array and then to define size of the int array automatically? What does happen, if SIZE isn't divisible by 4?
EDIT: (related to the comments)
I want to build something like an timed event handler. That means, I have a struct containing an array of events. Each event has an execution time and a related function (stored as a pointer). When the timer counter of the event handler matches the event execution time, I call the related function. Within the function I will know, wich arguments are expected, so I don't need to save a tag value. The problem is, that the events are created within a funtion and because I don't want to make the events static (to save memory), I added some memory (ring buffer) to my event handler where all functions can put in some data. Each event will have a variable containing the pointer to the (first) data. The type of data are only the nativ data types, no own structs.
This is my current code:
startSystemClock() will be called at start up
executeSystemEvent() will be called by the interrupt service routine of timer 1 by setting sysEventHandler.execute=TRUE and a while(1)-loop checks this flag and then calls executeSystemEvent()
// typedefs requird for timed events
typedef union __attribute__ ((packed)){
int *i; // pointer, where data is stored
int value; // if there is a pointer assigned, value differs from zero
}systemEventData_u;
typedef union __attribute__ ((packed)){
int value; // if there is a pointer assigned, value differs from zero
void (*voidFct_noData)();
void (*voidFct_data)(systemEventData_u);
}systemEventFct_u;
typedef struct{
int time;
unsigned int id;
systemEventFct_u fct;
systemEventData_u data;
}systemEvent_t;
#define SYSTEM_EVENT_HANDLER_BUFFER_SIZE (10)
#define SYSTEM_EVENT_HANDLER_MEMORY_SIZE (10)
typedef struct{
unsigned int actualCnt;
unsigned int nextEventCnt;
unsigned char execute;
systemEvent_t events[SYSTEM_EVENT_HANDLER_BUFFER_SIZE];
systemEvent_t* write;
// create some persistent memory usable by all functions
int* memWrite;
union __attribute__ ((packed)){
unsigned char uchar[0];
char schar[0];
unsigned int uint[0];
int sint[SYSTEM_EVENT_HANDLER_MEMORY_SIZE];
float flt[0];
double dbl[0];
}memory;
}systemEventHandler_t;
void startSystemClock(){
// initialize event handler
sysEventHandler.actualCnt=0;
sysEventHandler.nextEventCnt=-1;
sysEventHandler.execute=FALSE;
sysEventHandler.write=sysEventHandler.events;
sysEventHandler.memWrite=sysEventHandler.memory.sint;
unsigned int i=SYSTEM_EVENT_HANDLER_BUFFER_SIZE;
systemEvent_t *ptr=sysEventHandler.events;
while(i--){
ptr->fct.value=0;
ptr->data.value=0;
ptr->time=0;
ptr++;
}
// initialize timer 1
TMR1 = 0x00;
T1CON = T3_OFF | T3_IDLE_CON | T3_GATE_OFF | T1_PS_1_8 | T1_SOURCE_INT;
IPC1SET = (INTERRUPT_PRIOR_TIMER1 << _IPC1_T1IP_POSITION) | (INTERRUPT_SUB_PRIOR_TIMER1 << _IPC1_T1IS_POSITION);
IFS0CLR = (1 << _IFS0_T1IF_POSITION);
IEC0SET = (1 << _IEC0_T1IE_POSITION);
PR1 = PR_TIMER1;
T1CONSET = (1 << _T1CON_ON_POSITION);
print_text("timer1 started\n\r");
}
void executeSystemEvent(){
asm("di");
int time=sysEventHandler.actualCnt;
asm("ei");
unsigned int i=SYSTEM_EVENT_HANDLER_BUFFER_SIZE;
unsigned int nextEventCnt=-1;
systemEvent_t *ptr=sysEventHandler.events;
while(i--){
// do not investigate, if there is no function pointer
// no function pointer means no event action
if(ptr->fct.value){
if(time>=ptr->time){
// execute function
if(ptr->data.value){
(*ptr->fct.voidFct_data)(ptr->data);
}else{
(*ptr->fct.voidFct_noData)();
}
ptr->fct.value=0;
}
}
ptr++;
}
// determine next event
// iterate again through whole queue to take added events into account also
i=SYSTEM_EVENT_HANDLER_BUFFER_SIZE;
ptr=sysEventHandler.events;
while(i--){
if(ptr->fct.value){
// get execution time to determine next one
if(ptr->time<nextEventCnt){
nextEventCnt=ptr->time;
}
}
ptr++;
}
asm("di");
sysEventHandler.nextEventCnt=nextEventCnt;
sysEventHandler.execute=FALSE;
asm("ei");
}
void addSystemEvent(systemEvent_t event){
// check, if this event will be the first event to execute
asm("di");
// get event execution time
event.time+=sysEventHandler.actualCnt;
// check, if it will be the next one to execute
if(sysEventHandler.nextEventCnt>event.time){
sysEventHandler.nextEventCnt=event.time;
}
asm("ei");
*sysEventHandler.write=event;
if(++sysEventHandler.write>=sysEventHandler.events+SYSTEM_EVENT_HANDLER_BUFFER_SIZE){
sysEventHandler.write=sysEventHandler.events;
}
}
int * storeSystemEventData(int data){
int *ptr=sysEventHandler.memWrite;
*ptr=data;
if(++sysEventHandler.memWrite>=sysEventHandler.memory.sint+SYSTEM_EVENT_HANDLER_MEMORY_SIZE){
sysEventHandler.memWrite=sysEventHandler.memory.sint;
}
return ptr;
}
To add an event, I write within any function:
systemEvent_t event;
event.fct.voidFct_data=&enablePinChangeInterrupt_wrapper;
event.data.i=storeSystemEventData((int)PUSHBUTTON_CN_BIT);
event.time=10;
addSystemEvent(event);
I know, that the storeSystemEventData-function isn't complete. But for my first purpose, I only need int, so it works.
You don't need to specify the array sizes except for the biggest. Just out-of-bounds access the other types.
#include "stdio.h"
union memory {
unsigned char uchar[128];
char schar[0];
unsigned int uint[0];
int sint[0];
float flt[0];
double dbl[0];
} ;
int main (void)
{
union memory my_mem;
my_mem.schar[5] = 'A';
my_mem.schar[6] = 'B';
my_mem.schar[7] = 'C';
my_mem.schar[8] = 'D';
printf ("%d\n", my_mem.uint[1]);
return 0;
}
C doesn't provide array bounds checking either way, so you're just out of luck if you try to access memory outside the memory object.
What does happen, if SIZE isn't divisible by 4?
I assume you ask the question about divisibility by 4 (as opposed by any other number) because it is a common sizeof(int). When SIZE is indivisible by any of the sizeofs, would end up with the largest array that fits fully inside the size, i.e. the number would be truncated. For example, setting SIZE to 13 when sizeof(int) is 4 would produce
int sint[3];
In other words, the size would be "rounded down" (truncated). If you prefer rounding up, use this expression:
unsigned int uint[(SIZE+sizeof(unsigned int)-1)/sizeof(unsigned int)];
Note, however, that the size of uint[] array may exceed the size of uchar.
is there a possibility to define only the size of the unsigned char array and then to define size of the int array automatically?
You could replace union with an array of chars, and convert void* pointer to int*, float*, etc. This would lead to a different syntax.
I have an assignment to write a packet sniffer in C. The sample code provided currently gets raw packets and parses link layer (Ethernet) header like so:
struct ethernet_header {
unsigned char dest[6];
unsigned char source[6];
char proto;
}
...
const struct ethernet_header *header;
header = (const struct ethernet_header *)data_packet;
printf("Source MAC: %02x", header->source[0]);
for (i = 1; i < 6; i++) printf(":%02x", header->source[i]);
printf("\n");
...
Now I need to parse internet layer.
For Internet Layer I have following struct:
struct ip_header {
unsigned char ip_vhl; /* version << 4 | header length >> 2 */
unsigned char ip_tos; /* type of service */
unsigned char ip_len; /* total length */
...
};
Now ip_vhl is 8 bits long, and I want to get first 4 bits and printf it as a version and last 4 bits to printf it as a header length. Can you guys help me out here.
Also in sample code they used %02x to printf header->source[i] and %hu to printf header->proto. I would really appreciate if someone could explain it and what kind of %.. I should use to printf ip_vhl, ip_tos and ip_len.
You have two options:
either use bitfields to describe 4-bit fields. Beware of implementation and platform dependent bit and byte ordering:
struct foo {
int bar:4;
int baz:4;
}
or use logical operations to extract the bits.
upper4bits = (bigvar >> 4) & 0xf;
lower4bits = bigvar & 0xf;
I am getting an error from my compiler as follow:
C51 COMPILER V9.01 - SN: C1ADC-HAI60D COPYRIGHT KEIL ELEKTRONIK GmbH
1987 - 2009
* WARNING C260 IN LINE 300 OF SEQUENCE.C: '=': pointer truncation
* ERROR C190 IN LINE 301 OF SEQUENCE.C: '&': not an lvalue
The following is my code:
struct myCond{
unsigned char currStatus;
unsigned char prevStatus;
unsigned int *timer;
unsigned char *flag;
}
struct myCond StatCond;
unsigned int data timerdata;
bit bdata timeflag;
void someSubroutine (void)
{
struct myCond *tempCond;
tempCond = &StatCond;
tempCond->timer = &((unsigned int)timerdata);
tempCond->flag = &((unsigned char)timeflag);
}
Are we supposed to guess which line is 301?
The problems, as I understand are here:
tempCond->timer = &((unsigned int)timerdata);
tempCond->flag = &((unsigned char)timeflag);
(unsigned int)timerdata and (unsigned char)timeflag are values, r-values to be precise. They cannot be modified or assigned unlike l-values, which plain timerdata and timeflag are. And so you can't take addresses of r-values with &. It would be the same as, say, writing &1. 1 on its own does not exist as an object in data memory.
You should write instead:
tempCond->timer = &timerdata;
tempCond->flag = (unsigned char*)&timeflag;
And I'm not quite sure that it is legal to take an address of a bit variable. The last line may fail to compile.
Perhaps redefining the structure would help:
struct myCond{
...
bit bdata *flag; // or maybe without bdata
}
and then you'd write tempCond->flag = &timeflag;.
unsigned int data timerdata; // what is 'data', is it defined?
bit bdata timerflag; // what are 'bit' and 'bdata', are they defined?
Check your code with regard to my questions above. Compiler errors are often reported multiple lines after the real offense.
I am tring to get sound samples from microphone through Fez Panda 2. I am using rlp to accomplish that. Here is my code:
int GHAL_AnalogIn_Read(unsigned char channel)
{
return ((*((int*)(ADC_DATA_BASE_ADDRESS) + channel)) >>8) & 0x3FF;
}
int ReadAudio(unsigned int *generalArray, void **args, unsigned int argsCount ,unsigned int *argSize)
{
unsigned char *buffer = (unsigned char*)args[0];
int buffer_lengh = argSize[0];
unsigned char channel = *(unsigned char*)args[1];
int i=0;
while(i<buffer_lengh)
{
buffer[i] = GHAL_AnalogIn_Read(channel);
i++;
RLPext->Delay(100);
}
return 0;
}
The problem is that I need float values not unsigned char because I'm performing fft on these sound samples. So I need modification that will provide me float values. Any ideas?
Have you got experience with C? Especially with the meaning of * and &? * means: get the value pointed by address. So void ** args says someting like 'get the value pointed by the value obtained from address'. void is used to freely input anything you like. As you can not put whole structures or objects in an argument, you provide the pointer (an address) to a structure or object. By using the * you obtain the value on the address of the argument.
In C you do not pass whole arrays in an argument, you pass on the address of the first index.
Now you could simply re-factor your function to be something like:
int ReadAudio(unsigned int *generalArray, float arg, unsigned int argsCount ,unsigned int *argSize)
But as void **args is pointing to a buffer now, I think you should know what operation you want to perform on the data collected. An analog read will always provide you with an integer, most ADC (analog - digital - converter) are 10-bit or so.
If a float is 4 bytes on a 32-bit system, you want to mangle your data (unsigned char *buffer) in a 4-byte boundary.
EDIT: I have overlooked this in the documentatio: Note: Parameter of all function in RLP code file must have format follow this:Note: Parameter of all function in RLP code file must have format follow this:. Just cast the buffer bytes to a float by 4 byte boundary and I think you will do fine.