Search code examples
cpointersmicrocontrolleravr

In C, How does one set the value at one address to the value at another address?


I'm trying to make some UART code which will put a small string on the stack to be transmitted via a system of interrupts. This is specifically for an Atmel SAM microcontroller

#define UART_BUF_LEN 16

//GPS SERIAL INSTANCE
struct usart_module usart_instance; 
char buffer[UART_BUF_LEN];
uintptr_t bufferPtr = (uintptr_t)buffer;

bool transmitting(){
    return (uintptr_t)buffer == bufferPtr; //If the read head is at the top of the array, then we are not transmitting.
}

bool transmit(char* c, uint len){
    if(!transmitting() && len<=UART_BUF_LEN){
        bufferPtr= (uintptr_t)buffer + len;//set write head to top of the len stack
        while(transmitting()){
            *bufferPtr = *c; //Set the value at the address of bufferPtr to the value at the address of c.
            bufferPtr --; //Move the buffer closer to the head of the array
            c++; //Move the head of the array down some.
        }
    }else{
        return false;
    }
    bufferPtr= (uintptr_t)buffer + len; //reset the read head so that our transmit code knows where to read from.
    return true;
}

Trouble here is the line *bufferPtr = *c;. When I build the solution, the bufferptr seems to not be dereferencable. I get the following error:

invalid type argument of unary '*' (have 'uintptr_t {aka unsigned int}')

I've looked online, and all sources tell me that I must cast uintptr_t back into a pointer of the native datatype which the memory address points to. I am not sure how to do this, as using the typecast (char *), indicating that the buffer pointer is a character pointer does not compile, giving me the same error as above.

Now the rabbit hole goes one level deeper when I change the line to \*(char\*)bufferPtr = \*c;, which does not give me any error. What does this line mean?

I expect that it means that the value at the address of the typecast of bufferPtr to a char pointer is set to the value at the address of c. Is this correct?


Solution

  • Since bufferPtr is a uintptr_t, which is an integral type, not a pointer type, you will have to cast it back to the pointer type before dereferencing it.

    *(char *)bufferPtr = *c;
    

    This is fine, since the source of bufferPtr's value came from a char array.

    char buffer[UART_BUF_LEN];
    uintptr_t bufferPtr = (uintptr_t)buffer;