7 years, 6 months ago.

trying to write/read a struct in local file system please help?

struct inputvalues{
uint8_t test= 77;
uint8_t test1=66;
uint8_t test2=25;
long int test3=45;
}record[100];

 inputvalues ainputvalues;
  inputvalues * pinputvalues;
  pinputvalues = &ainputvalues;
 void save() {
    FILE *fp = fopen("/local/out1.txt", "w");  // Open "out.txt" on the local file system for writing
    fprintf(fp, "%d/n%d/n%d/n%d/n", pinputvalues->test,pinputvalues->test1,pinputvalues->test2,pinputvalues->test3);
    fclose(fp);

}

 void show() {
    FILE *fp1 = fopen("/local/out1.txt", "r");  // Open "out.txt" on the local file system for writing
   
     if (fp1 != NULL) {
        char buffer[100] = {0};
        char c = {0};
        char *token;
       
        int i = 0;
 
 
        /* Read Chars Until End of Line */
        while ((c != '\n') && (i < 10)) {
            c = fgetc(fp1);
            buffer[i] = c;
            i++;
        }
 
        /* Get Token: Probably not needed, but Useful for More Numbers */
        token = strtok(buffer, "\n");
        
        /* String to Int Function */
        int result = atoi(token);
        int num = result;
 lcd.clear(); 
lcd.setPosition(0,0); 
        lcd.printf("result = %d\r\n", num);
     
    fclose(fp1);
    }
}

Does the file have to be in text?

If you save it in binary then you can just use a sizeof() to tell you how much data needs to be written/read and so if you add extra values into the structure later the load and save functions will still work without any changes (but old data files wont)

Untested code so it probably has a few typos etc... but the basic structure should work:

bool save(char* filename, struct inputvalues *dataStruct) {
   FILE *fp = fopen(filename, "wb");  // Open for writing as binary
   if (fp) {
     for (int count = 0; count < sizeof(struct inputvalues); count++)
        fputc( *( ((char*) dataStruct) + count) , fp);
     fclose(fp);
     return true;
   }
   return false;
}

bool read(char* filename, struct inputvalues *dataStruct) {
   FILE *fp = fopen(filename, "rb");  // Open file for reading as binary
   if (fp) {
     for (int count = 0; count < sizeof(struct inputvalues); count++)
        *( ((char*) dataStruct) + count) ) = fgetc(fp) ;
     fclose(fp);
     return true;
   }
   return false;
}

main () {
  struct inputvalues data;
  data.test= 255;
  data.test1= 34;
  if (!save("/local/out1.txt",&data))
    printf("Save failed for some reason\n");
  data.test= 0;
  data.test1= 0;
  printf("before load: %d\n%d\n",data.test,data.test1);
  if (!load("/local/out1.txt",&data))
    printf("Load failed for some reason\n");
  else
    printf("after load: %d\n%d\n",data.test,data.test1);
}
posted by Andy A 16 May 2017

I need to save int values and read the int values from internal eeprom of lpc1768. I need to save the settings during power cut and then load them back.

posted by jayendra mishra 16 May 2017

I got the following errors.

Error: Incomplete type is not allowed in "main.cpp", Line: 18, Col: 42 Error: Incomplete type is not allowed in "main.cpp", Line: 29, Col: 42 Warning: Expression has no effect in "main.cpp", Line: 30, Col: 10 Error: Expected a ";" in "main.cpp", Line: 30, Col: 43

posted by jayendra mishra 16 May 2017

this is the code that I tried

#include "mbed.h"
#include "TextLCD.h"
#include "SerialLCD.h"

LocalFileSystem local("local");               // Create the local filesystem under the name "local"
SerialLCD lcd(P0_9,NC);
DigitalIn pin_up(p27); 
DigitalIn pin_down(p28);
InterruptIn pin_start(p29);
InterruptIn Pin_rain(p21);
InterruptIn saver(p30);
DigitalOut myled(LED1);


bool save(char* filename, struct inputvalues *dataStruct) {
   FILE *fp = fopen(filename, "wb");  // Open for writing as binary
   if (fp) {
     for (int count = 0; count < sizeof(struct inputvalues); count++)
        fputc( *( ((char*) dataStruct) + count) , fp);
     fclose(fp);
     return true;
   }
   return false;
}
 
bool read(char* filename, struct inputvalues *dataStruct) {
   FILE *fp = fopen(filename, "rb");  // Open file for reading as binary
   if (fp) {
     for (int count = 0; count < sizeof(struct inputvalues); count++)
        *( ((char*) dataStruct) + count) ) = fgetc(fp) ;
     fclose(fp);
     return true;
   }
   return false;
}
 
int main () {
  struct inputvalues data;
  data.test= 255;
  data.test1= 34;
  if (!save("/local/out1.txt",&data))
    printf("Save failed for some reason\n");
  data.test= 0;
  data.test1= 0;
  printf("before load: %d\n%d\n",data.test,data.test1);
  if (!read("/local/out1.txt",&data))
    printf("Load failed for some reason\n");
  else
    printf("after load: %d\n%d\n",data.test,data.test1);
}


posted by jayendra mishra 16 May 2017

The incomplete type errors are because you didn't define the inputvalues struct anywhere. This should go with the declarations at the start.

struct inputvalues{
uint8_t test;
uint8_t test1;
uint8_t test2;
long int test3;
};

Alternatively you can typdef this as Graham did in his answer and then use that type (i.e. replace "struct inputvalues" with "inputvalues_t" everywhere other than the definition)

The other issue is I had a mismatched bracket, line 30 in the above code should be:

        *( ((char*) dataStruct) + count) = fgetc(fp) ;
posted by Andy A 17 May 2017

#include "mbed.h"
#include "TextLCD.h"
#include "SerialLCD.h"

LocalFileSystem local("local");               // Create the local filesystem under the name "local"
SerialLCD lcd(P0_9,NC);
DigitalIn pin_up(p27); 
DigitalIn pin_down(p28);
InterruptIn pin_start(p29);
InterruptIn Pin_rain(p21);
InterruptIn saver(p30);
DigitalOut myled(LED1);

struct inputvalues{
uint8_t test;
uint8_t test1;
};

bool save(char* filename, struct inputvalues *dataStruct) {
   FILE *fp = fopen(filename, "wb");  // Open for writing as binary
   if (fp){
     for (int count = 0; count < sizeof(struct inputvalues); count++)
        fputc( *( ((char*) dataStruct) + count) , fp);
     fclose(fp);
     return true;
   }
   return false;
}
 
bool read(char* filename, struct inputvalues *dataStruct) {
   FILE *fp1 = fopen(filename, "rb");  // Open file for reading as binary
   if (fp1) {
     for (int count = 0; count < sizeof(struct inputvalues); count++)
        *( ((char*) dataStruct) + count)  = fgetc(fp1) ;
     fclose(fp1);
     return true;
   }
   return false;
}
 
int main () {
    
    lcd.clear(); 
lcd.setPosition(0,0); 
lcd.printf("Start");
 wait(4);   
  
  struct inputvalues data; 
  data.test= 25;
  data.test1= 34;
 
  if (!save("/local/out1.txt",&data))
  lcd.clear(); 
lcd.setPosition(0,0); 
    lcd.printf("Save failed for some reason\n");
    
  data.test= 0;
  data.test1= 0;
  
  lcd.clear(); 
lcd.setPosition(0,0); 
  lcd.printf("before load: %d %d",data.test,data.test1);
  
  if (!read("/local/out1.txt",&data))
  {
  lcd.clear(); 
lcd.setPosition(0,0); 
lcd.printf("Load failed for some reason\n");
}
else{
  lcd.clear(); 
lcd.setPosition(0,0); 
    lcd.printf("after load: %d %d",data.test,data.test1);
    wait(3);
}  
  
}
posted by jayendra mishra 18 May 2017

I tried the above code. The compiles without error but I am not getting any response from the microcontroller. The controller just hangs and all the four leds start flashing out. I tried the code with just with print command, while keeping the save and read functions, still it did not work. Please guide me.

posted by jayendra mishra 18 May 2017

1 Answer

7 years, 6 months ago.

Off the top of my head:

What actual hardware are you saving the file to? I believe most mbed devices do not have that local filesystem capability and require external storage like an sd card. If you are using a newer version of the mbed library, you could try going back to mbed 2. They've made some changes to the underlying libraries and it's possible something that once worked does not work anymore.

In the save() function, writing to the file, the newline character is the other slash. The file parsing is looking for this character so it needs to be there.

I would remove the pointer to the struct. It's not needed here as the structs are global variables.

Then I don't know what the struct does if you initialize it like that. Below is, I think a more common way. Define a type and then specifically initialize each the way you want.

typedef struct inputvalues_t {
    uint8_t  test;
    uint8_t  test1;
    uint8_t  test2;
    uint32_t test3;
} inputvalues_t;

inputvalues_t inputvalues = { .test = 77, .test1 = 66, .test2 = 25, .test3 = 45};
inputvalues_t record[100];

void save() {
    FILE *fp = fopen("/local/out1.txt", "w"); // Open "out.txt" on the local file system for writing

    fprintf(fp, "%d\n%d\n%d\n%d\n", inputvalues.test, inputvalues.test1, inputvalues.test2, inputvalues.test3);
    fclose(fp);
}

Accepted Answer

Thank you. But what will be the procedure for reading these values?

posted by jayendra mishra 16 May 2017

I am using LPC1768 which has local file system.

posted by jayendra mishra 16 May 2017