Search code examples
cmemory-managementdynamic-c

Dynamic C - Error when using writeUserBlockArray()


Edit - here are some resources in response to comments:

costate: http://bamafolks.com/randy/students/embedded/dynamicC_mtask.html

writeUserBlockArray: http://ftp1.digi.com/support/documentation/html/DynCFunctionReference/12fun595.htm#1259708

The error I am getting is `-1: Invalid address or range'.

#define MAX_SAMPLES 20
#define REPORT_AFTER 3

main()
{
    int i;
    int report;

    int write_result;
    int read_result;

    struct temp_struct {
        float celcius;
        float fahrenheit;
    } temperature_data;

    struct temp_struct save_data[MAX_SAMPLES];
    struct temp_struct read_data[MAX_SAMPLES];
    unsigned int save_lens[MAX_SAMPLES];

    float *pTempC, *pTempF;

    pTempC = &temperature_data.celcius;
    pTempF = &temperature_data.fahrenheit;

    i = 0;
    report = 0;

    brdInit();

    while(1)
    {
       costate
       {
           sampleTemp(&temperature_data.celcius, &temperature_data.fahrenheit);

           save_data[i].celcius = *pTempC;
           save_data[i].fahrenheit = *pTempF;
           save_lens[i] = sizeof(temperature_data);

           if(i==MAX_SAMPLES) i=0; else i++;
           report=1; // Sample has been taken, a report can be produced
           waitfor(DelaySec(SAMPLE_DELAY_SECS));
       }

       // If REPORT_AFTER set to 3, this executed every third sample taken.
       // "report" the last set of data saved by printing out
       if(report && i%REPORT_AFTER==0 && i!=0)
       {
          write_result = writeUserBlockArray(i-REPORT_AFTER, save_data, save_lens, REPORT_AFTER);
          // Read data to check it was saved correctly
          read_result = readUserBlockArray(read_data, save_lens, REPORT_AFTER, i-REPORT_AFTER);

          // Print out all data saved here.

          report = 0; // Do not report again until another sample has been taken.
          break; // Stops after first report. Can be removed later
       } // end if
    } // end while
} // end main

float sampleTemp(float *tempC, float *tempF)
{
   auto float  Tk,      //calculated temperature kelvins
                    Draw;       //raw data value
   auto int i;

   printf("Getting temperature\n\n");

   Draw = anaIn(7, SINGLE, GAIN_1);

   //calculate temperature in kelvins
   Tk = (Bt*Tkstd) / ( Tkstd * ( log( fabs( (-Draw*Rs) / (Rtstd*(Draw-(Dmax*Gain))) ) ) ) + Bt );

   *tempC = Tk - 273.15;                //convert to celcius
   *tempF = 1.8*(Tk - 255.37);      //calculate fahrenheit

   return 0;
}

This is all relevant code. I am consistently getting -1 returned from the writeUserBlockArray() method which symbolises an invalid address or range.

I don't think the fact that it is Dynamic-C makes much difference but the offending method's outline is this:

writeUserBlockArray(addrOffset, arraySources, arraySourceSizes, numSources);

I am new to C and I think I am doing something wrong with the way I am saving the data to the array?

Thanks in advance.


Solution

  • The problem was that I was trying to write an array of data to the memory. The actual way of using the writeUserBlockArray(...) method is to specify an array of pointers.

    New, working, code:

    #define SAMPLE_DELAY_SECS 5
    #define MAX_SAMPLES 20
    #define REPORT_AFTER 3
    
    main()
    {
       int temp;
    
       int i; // Iteration #
       int report; // Whether to produce a report or not
    
       int write_result; // The numerical result of the write-to-memory operation
       int read_result; // The numerical result of the read-from-memory operation
    
       // Define a structure which can be used to hold both temperature measurements
       struct temp_struct {
            float celcius;
          float fahrenheit;
       } temperature_data;
    
       void *save_pointers[MAX_SAMPLES]; // An array of pointers pointing to the data to be saved in memory
       struct temp_struct save_data[MAX_SAMPLES]; // Array of actual data which can be loaded with the read operation
       unsigned int save_lens[MAX_SAMPLES]; // An array of the size (in bytes) of each element in the save_data array
    
       i = 0;
       report = 0;
    
       brdInit(); // Needs to be called before any operations are performed with the hardware.
    
       while(1)
       {
          /*
           * Costate is a way of multitasking in Dynamic-C. By using a costate block in
           * conjunction with the waitfor keyword, the block can be paused until it
           * has finished waiting.
           *
           * Further info:
           * http://bamafolks.com/randy/students/embedded/dynamicC_mtask.html
           */
          costate
          {
            // Method taken from: http://read.pudn.com/downloads107/sourcecode/embed/441399/Samples/RCM3700/Tcpip/RabbitWeb/TEMPERATURE.C__.htm
            sampleTemp(&temperature_data.celcius, &temperature_data.fahrenheit);
    
            save_pointers[i] = &temperature_data;
            save_lens[i] = sizeof(temperature_data);
    
            printf("save_data[%d].celcius is %f\n", i, save_data[i].celcius);
            printf("save_data[%d].fahrenheit is %f\n\n", i, save_data[i].fahrenheit);
    
            if(i==MAX_SAMPLES) i = 0; else i++;
    
            report=1; // Sample has been taken, a report can be produced
            waitfor(DelaySec(SAMPLE_DELAY_SECS));
          }
    
          /*
           * This IF block is used to produce a report every so often, either by
           * emailing out some data, updating the web interface or simply printing
           * it to the screen.
           *
           * A report will be produced when:
           *   a) a new sample has been taken (report)
           *   b) the desired number of samples has been reached (i%REPORT_AFTER==0)
           *   c) it is not the very first sample to be taken (i!=0)
           */
          if(report && i%REPORT_AFTER==0 && i!=0) // For every third sample
          {
             /*
              * writeUserBlockArray(address_offset (unsigned int),
              *             sources (array),
              *             source_sizes (array),
              *             num_sources (int));
              * Documentation:
              * http://ftp1.digi.com/support/documentation/html/DynCFunctionReference/12fun595.htm#1259708
              */
             write_result = writeUserBlockArray(i-REPORT_AFTER, save_pointers, save_lens, REPORT_AFTER);
    
             /*
              * readUserBlockArray(destinations (array),
              *            destination_sizes (array),
              *            num_sources (int),
              *            address_offset (unsigned int));
              * Documentation:
              * http://ftp1.digi.com/support/documentation/html/DynCFunctionReference/12fun441.htm#1259907
              */
             read_result = readUserBlockArray(save_data, save_lens, REPORT_AFTER, i-REPORT_AFTER);
    
             printf("Write Result: %d\nRead Result: %d\n\n", write_result, read_result);
    
             printf("Most recent data...\n");
             for(temp = 0; temp < REPORT_AFTER; temp++)
             {
            printf("save_data[%d].C: %f\n", temp, save_data[temp].celcius);
                printf("save_data[%d].F: %f\n", temp, save_data[temp].fahrenheit);
             }
    
             report = 0; // Do not report again until another sample has been taken.
          }// End if
       }// End while
    }// End main