4

I'm trying to set a library in C++ for AVR. The idea is to have an easy way of configuring what pins you use on each device. This is the library:

class PINS{
public:
//ATTRIBUTES
uint8_t* DDRaddr;
uint8_t* PORTaddr;
uint8_t* PINaddr;
int pinnum;
//METHODS
void usepin(volatile uint8_t *pin, int num);};

void PINS::usepin(volatile uint8_t *pin, int num){
this->pinnum=num;
if(pin==&PORTB){
    this->DDRaddr=&DDRB;
    this->PINaddr=&PINB;
    this->PORTaddr=&PORTB;}
if(pin==&PORTC){
    this->DDRaddr=&DDRC;
    this->PINaddr=&PINC;
    this->PORTaddr=&PORTC;}
if(pin==&PORTD){
    this->DDRaddr=&DDRD;
    this->PINaddr=&PIND;
    this->PORTaddr=&PORTD;} 
return;}

And this is what calls for it:

PINS RS;
RS.usepin(&PORTC, 0);

Now this is how I thought it would work:

  1. Write e.g. "PINS RS;" to create an instance of class PINS; a new pin with the name RS.
  2. Write "RS.usepin(PORTB,0);" to configure RS pin to PORTB0 of MCU.
  3. Use RS.DDRaddr for DDR, RS.PINaddr for PIN and RS.PORTaddr for PORT register
  4. Use RS.pinnum for the pin number; eg: RS.DDRaddr|=(1<

When I try to build it in Atmel Studio I have the following error for every line like this: "this->DDRaddr=&DDRB;" The error says:

Error 1 invalid conversion from volatile uint8_t* to uint8_t*

It used to work before I made uint8_t* DDRaddr a class member. I can't understand what is the problem, i couldn't make a conclusion from similar - but yet not quite the same - questions. Is there anyone who could have an idea of what is wrong with this specific code?

tux3
  • 7,171
  • 6
  • 39
  • 51
Kostas Dafnomilis
  • 629
  • 1
  • 5
  • 13
  • 1
    Why can't you declare the members `volatile` as well? – Ignacio Vazquez-Abrams Apr 11 '15 at 19:00
  • 1
    Just like you can't implicitly remove constness, the same goes for volatility. – chris Apr 11 '15 at 19:01
  • Remember to take "snapshots" of volatile pins. The term `volatile` means the values will change by a means outside of the program's control. – Thomas Matthews Apr 11 '15 at 19:04
  • 2
    By the way, you can save some text space and typing by accessing the members directly rather than using the `this->` syntax. – Thomas Matthews Apr 11 '15 at 19:08
  • I don't understand what's your goal! I find DDRn, PINn and PORTn very clear. What's an example of functionality your class will offer? I think that AVRs are micros and each function is introduced in a FW uses memory that might be used to manage the functionality we want to develope. Introducing functions that use sequences of if and branch, besides the waste of the memory, can cause delays. AVRs aren't 64 bit CPU with 4 Gb of memory!!! :) – Sir Jo Black Apr 12 '15 at 17:14
  • You may be right about the memory waste Sergio, it will show in progress... All i meant to do is an elegant way of setting up the AVR pins one will use for an external device. I could just #define RSport PORTB, #define RSpin PINB and so on... Just experimenting if there's an easier way... – Kostas Dafnomilis Apr 13 '15 at 08:58
  • thanks for all the notes. Yes the problem was the volatility. I declared the members as volatile it now works fine. – Kostas Dafnomilis Apr 13 '15 at 09:05
  • @Thomas Matthews: I did that, thanks. – Kostas Dafnomilis Apr 13 '15 at 09:27

2 Answers2

4

Apparently DDRB is of type volatile uint8_t, but you're trying to assign its address into a uint8_t*. That's not allowed - volatile follows the same rules as const in this regard.

If you intend to use the members like this, you'll have to declare them as pointers to volatile:

class PINS{
public:
//ATTRIBUTES
volatile uint8_t* DDRaddr;
volatile uint8_t* PORTaddr;
volatile uint8_t* PINaddr;
// ... rest as before
Angew is no longer proud of SO
  • 167,307
  • 17
  • 350
  • 455
2

"volatile" means that reading or writing a value is a side effect that cannot be optimised away. Reading or writing a volatile value might be affecting some hardware, it might cause the value to be modified in different ways than you think and so on. As a result, assumptions that the compiler would usually make (if you store x to a variable and then read it again the result will be x, and so on) are wrong.

If you cast away the volatile-ness, then the compiler could generate code that is wrong. Therefore, you have to do this explicitely and not implicitly.

gnasher729
  • 51,477
  • 5
  • 75
  • 98
  • I will add that **volatile** needs to be used also when we use variables **shared** between **ISR** (interrupt sub routines) and the rest of the program, because the compiler is not always able to recognize this situations! – Sir Jo Black Apr 12 '15 at 17:19