Home:ALL Converter>issues with pointers and PROGMEM

issues with pointers and PROGMEM

Ask Time:2020-08-17T16:23:40         Author:Andre Medina

Json Formatter

I am programming on an Arduino UNO, and have encountered a very annoying road block.

Im having a really odd issue with PROGMEM, I have narrowed it down to an issue with a pointer array.

When I index the PROGMEM array with a variable j. It returns different results depending on weather the variable j was set by a static number or if it was set by another variable.

The program number is an integer stored in an object, and is only ever set as follows, the memory is malloced and the variable holds its value. I have tested this.

*(this->program) = 0;

setting j as 0 directly produces the correct address

uint16_t j = 0;
Serial.println(j);    
//printed 0 as expected

address = (uint16_t)*(pgmStringTable + (uint16_t)j); 
Serial.println(address);   
//gave address = 105, which is correct and PROGMEM reads the correct bytes

However, setting j using the progam variable as follows produces an incorrect address

uint16_t j = *(this->program);
Serial.println(j);    
//printed 0 as expected

address = (uint16_t)*(pgmStringTable + (uint16_t)j); 
Serial.println(address);   
//gave address = 4, which isnt right and results in PROGMEM read errors

even trying to work around this set issue, like doing some arithmatic onto *(this->program) or sending it to a function that returns an integer of the same value never helps. The only thing that has work is looping through all integers as follows:

//loops through most unsigned integer values
for(uint16_t j = 0; j < 65000; j++){
  if(j == *(this->program)){
     address = (uint16_t)*(pgmStringTable + (uint16_t)j); 
     //address is correct and PROGMEM works correctly
  }
}

The above working is even more reason to confirm that the malloc is working correctly, as *(this->program) is returning the correct value when comparing it to j.

This is a very bad work around as its very inefficient and will cause major cycles wasted in my program which is pretty time sensitive.

Any pointers to a solution or a reason why the pointer is acting funny would be very useful.

The issue was from a very large project, so to help with narrowing down the error I have recreated the issue in a much smaller .ino file

The entire code is this. It produced the same error when uploaded my arduino UNO

EDITS:

  1. upon further investigation, setting j to any variable which isn't constant in my main project (so the variable cannot be altered anything else in the project) seems to break the PGM in the same way described.


const char pgmString1[] PROGMEM = "String 1__";
const char pgmString2[] PROGMEM = "2nd String";
const char *const pgmStringTable[] PROGMEM = {pgmString1, pgmString2};




class testObject{

    private:
        uint16_t* program;

    public:


        testObject(){
            program = (uint16_t*) malloc(sizeof(uint16_t));
            *(this->program) = 0;
        }

        void read(){
            if(*(this->program) == 0){
                //the console prints the below, meaning the value is definitly 0
                Serial.println("it was 0");
                *(this->program) = 0;
            }else{
                Serial.println("it wasnt 0");
                
                //if this is uncommeneted, this program outputs the correct values but the above comment will not be dispalyed
                //*(this->program) = 0;
            }

            char temp[10];
            uint16_t j = 0;
            uint16_t address = 0;   

////////////////////////////////////////////// indirectly setting j
            //sets the j value to be 0, which is what is stored in this->program
            j = *(this->program);

            //prints j to make sure its 0, then finds the address of the progmem string
            Serial.print(j);
            Serial.print("  1 Address: |"); 
            address = (uint16_t)*(pgmStringTable + (uint16_t)j);   
            Serial.print(address);     //the address printed is incorrect
            Serial.print("   ");

            //reads byte by byte from the address, it reads the wrong bytes
            for(int i = 0; i < 10; i++){    
                char myChar = pgm_read_byte( address + i );
                Serial.print(myChar);
            }
            Serial.println("\n");
                    
////////////////////////////////////////////// directly setting j
            //but just setting j = 0 works fine
            j=0;

            //so directly setting j as 0, same code as above but it produces the correct output
            //SAME AS ABOVE, COULDNT SEPERATE INTO ITS ONW FUNCTION
            Serial.print(j);
            Serial.print("  2 Address: |");
            address = (uint16_t)*(pgmStringTable + (uint16_t)j);
            Serial.print(address);
            Serial.print("   ");
            for(int i = 0; i < 10; i++){    
                char myChar = pgm_read_byte( address + i );
                Serial.print(myChar);
            }
            Serial.println();
            //

        }
};





testObject pgmReader;

void setup(){
    Serial.begin(9600);
}

void loop(){
    Serial.println("\n\n\n\n\n\n\n\n");
    delay(1000);
    pgmReader.read();

}


Author:Andre Medina,eproduced under the CC 4.0 BY-SA copyright license with a link to the original source and this disclaimer.
Link to original article:https://stackoverflow.com/questions/63447172/issues-with-pointers-and-progmem
yy