Author Topic: [gcc C] concatenating text to make up code  (Read 19876 times)

0 Members and 1 Guest are viewing this topic.

Offline TK

  • Super Contributor
  • ***
  • Posts: 1722
  • Country: us
  • I am a Systems Analyst who plays with Electronics
Re: [gcc C] concatenating text to make up code
« Reply #50 on: October 07, 2018, 09:32:18 pm »
Code: [Select]

#define PORTS__OFFSET 0x4000
#define PORTS__OFFSET_GAP 0X20
#define PORTA__OFFSET 0x0400
#define PARTB__OFFSET 0x0420
#define PORTC__OFFSET 0x0440
#define PORTD__OFFSET 0x0460
#define PORTE__OFFSET 0x0480
#define PORTF__OFFSET 0x04A0

#define DATA_DIRECTION 0x00
#define DATA_DIR_SET 0x01
#define DATA_DIR_CLEAR 0x02
#define DATA_DIR_TOGGLE 0x03
#define DATA_OUTPUT 0x04
#define DATA_OUTPUT_SET 0x05
#define DATA_OUTPUT_CLEAR 0x06
#define DATA_OUTPUT_TOGGLE 0x07
#define DATA_INPUT_PIN_VALUE 0x08
#define PIN_INTERRUPT_FLAGS 0x09
#define PORT_CONTROL 0x0A
#define PIN_CONTROL 0x10

#define PORT_A 0x00
#define PORT_B 0x01
#define PORT_C 0x02
#define PORT_D 0x03
#define PORT_E 0x04
#define PORT_F 0x05

#define PIN_0 0x00
#define PIN_1 0x01
#define PIN_2 0x02
#define PIN_3 0x03
#define PIN_4 0x04
#define PIN_5 0x05
#define PIN_6 0x06
#define PIN_7 0x07

#define PULLUP 0x03

void setup_input_w_pullup(uint8_t port, uint8_t pin){
PORTS__OFFSET + PORTS__OFFSET_GAP * port + DATA_DIR_SET = 0x01 << pin;
PORTS__OFFSET + PORTS__OFFSET_GAP * port + PIN_CONTROL + pin = 0x01 << PULLUP;
}
I don't think this code compiles without errors as the left side expression is not assignable a value
 

Offline cv007

  • Frequent Contributor
  • **
  • Posts: 825
Re: [gcc C] concatenating text to make up code
« Reply #51 on: October 07, 2018, 09:32:39 pm »
I guess you got close, but I'll help. You must not have tried to compile it.

Code: [Select]
static inline void setup_input_w_pullup(uint8_t port, uint8_t pin){
*(volatile uint8_t*)(PORTS__OFFSET + PORTS__OFFSET_GAP * port + DATA_DIR_SET) = 0x01 << pin;
*(volatile uint8_t*)(PORTS__OFFSET + PORTS__OFFSET_GAP * port + PIN_CONTROL + pin) = 0x01 << PULLUP;
}

//I assume this is close to what you want
#define SW1_PORT PORT_A
#define SW1_PIN PIN_2
//OR
#define SW1 PORT_A,PIN_2
//#define SW1 PIN_2,PORTA //<- wrong order, but will get no complaints

int main(){
    setup_input_w_pullup(SW1_PORT, SW1_PIN); //ok
    setup_input_w_pullup(SW1_PIN, SW1_PORT); //<- wrong usage, but no error
    setup_input_w_pullup(PORT_A, PULLUP); //<- wrong usage, but no error
    //OR
    setup_input_w_pullup(SW1); //<- cannot mix up order unless define uses mixed up order
}
I guess we are just going to do 1, and not 2 and 3 also.

In my simple example, there is a reason I did not create defines for anything- they are only used in one place so its not needed. I did not comment the code, but that would take care of it-
static inline void pin_dir(PIN_t pin, DIR_t io){
    //io- OUT=1 (DIRSET) IN=2 (DIRCLR)
    ((volatile uint8_t*)(pin & 0XFF0))[io] = 1<<(pin&7);
}

You could also eliminate many defines-
Code: [Select]
#define PORT_BASE 0x400
#define PORT_A 0x00
#define PORT_B 0x20
#define PORT_C 0x40
#define PORT_D 0x60
#define PORT_E 0x80
#define PORT_F 0xA0

static inline void setup_input_w_pullup(uint8_t port, uint8_t pin){
    //PORT_BASE = PORTA base address
    //[1]=DIRSET
    ((volatile uint8_t*)(PORT_BASE+port))[1] = 1 << pin;
    //0x10 = PINCTRL offset, PULLUPEN = bit3
    ((volatile uint8_t*)(PORT_BASE+port))[0x10+pin] = 1 << 3;
}

#define SW1_PORT PORT_A
#define SW1_PIN 2
//OR
#define SW1 PORT_A,2
//#define SW1 2,PORTA //<- wrong order, but no complaints
The comments would take care of filling in the user about what bits/registers are used. Either that or they have to hunt down the define.

Or simply forget the defines altogether (I'm probably getting annoying).
« Last Edit: October 07, 2018, 10:15:10 pm by cv007 »
 

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 17814
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: [gcc C] concatenating text to make up code
« Reply #52 on: October 08, 2018, 06:20:51 am »
Code: [Select]

#define PORTS__OFFSET 0x4000
#define PORTS__OFFSET_GAP 0X20
#define PORTA__OFFSET 0x0400
#define PARTB__OFFSET 0x0420
#define PORTC__OFFSET 0x0440
#define PORTD__OFFSET 0x0460
#define PORTE__OFFSET 0x0480
#define PORTF__OFFSET 0x04A0

#define DATA_DIRECTION 0x00
#define DATA_DIR_SET 0x01
#define DATA_DIR_CLEAR 0x02
#define DATA_DIR_TOGGLE 0x03
#define DATA_OUTPUT 0x04
#define DATA_OUTPUT_SET 0x05
#define DATA_OUTPUT_CLEAR 0x06
#define DATA_OUTPUT_TOGGLE 0x07
#define DATA_INPUT_PIN_VALUE 0x08
#define PIN_INTERRUPT_FLAGS 0x09
#define PORT_CONTROL 0x0A
#define PIN_CONTROL 0x10

#define PORT_A 0x00
#define PORT_B 0x01
#define PORT_C 0x02
#define PORT_D 0x03
#define PORT_E 0x04
#define PORT_F 0x05

#define PIN_0 0x00
#define PIN_1 0x01
#define PIN_2 0x02
#define PIN_3 0x03
#define PIN_4 0x04
#define PIN_5 0x05
#define PIN_6 0x06
#define PIN_7 0x07

#define PULLUP 0x03

void setup_input_w_pullup(uint8_t port, uint8_t pin){
PORTS__OFFSET + PORTS__OFFSET_GAP * port + DATA_DIR_SET = 0x01 << pin;
PORTS__OFFSET + PORTS__OFFSET_GAP * port + PIN_CONTROL + pin = 0x01 << PULLUP;
}
I don't think this code compiles without errors as the left side expression is not assignable a value

How is the left expression not assigned a value?
 

Online ataradov

  • Super Contributor
  • ***
  • Posts: 11238
  • Country: us
    • Personal site
Re: [gcc C] concatenating text to make up code
« Reply #53 on: October 08, 2018, 06:23:10 am »
Your code is parsed by the compiler like this: "PORTS__OFFSET + PORTS__OFFSET_GAP * port + (DATA_DIR_SET = 0x01 << pin)". And  DATA_DIR_SET is a constant. This is a wrong code all around.
Alex
 

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 17814
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: [gcc C] concatenating text to make up code
« Reply #54 on: October 08, 2018, 06:23:52 am »


Or simply forget the defines altogether (I'm probably getting annoying).


Yes you are. While I understand that using defines to define code is a bad idea they are not bad in themselves and used by the manufacturers, without them any address location would be a number and then that code would not be portable across devices maybe in the same family. Just look at the manufacturers own chip header file.
 

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 17814
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: [gcc C] concatenating text to make up code
« Reply #55 on: October 08, 2018, 06:24:28 am »
Your code is parsed by the compiler like this: "PORTS__OFFSET + PORTS__OFFSET_GAP * port + (DATA_DIR_SET = 0x01 << pin)". And  DATA_DIR_SET is a constant. This is a wrong code all around.

So I need parenthesis?
 

Online ataradov

  • Super Contributor
  • ***
  • Posts: 11238
  • Country: us
    • Personal site
Re: [gcc C] concatenating text to make up code
« Reply #56 on: October 08, 2018, 06:25:33 am »
So I need parenthesis?
No, you need to rewrite the code, so it makes sense. I believe somebody actually posted the correct version of this code. You've got to read what people write.
Alex
 

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 17814
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: [gcc C] concatenating text to make up code
« Reply #57 on: October 08, 2018, 06:30:23 am »
So microchip are mad to write things like:


#define CLKCTRL_MCLKCTRLA  _SFR_MEM8(0x0060)


which allows me to say

CLKCTRL_MCLKCTRLA  = "some value"
« Last Edit: October 08, 2018, 07:44:43 am by Simon »
 

Online ataradov

  • Super Contributor
  • ***
  • Posts: 11238
  • Country: us
    • Personal site
Re: [gcc C] concatenating text to make up code
« Reply #58 on: October 08, 2018, 06:32:54 am »
I don't understand what do you mean. As far as I can see _SFR_MEM8 is a just a dummy, so the code is wrong. I'm not sure why you think you can do this.

Actually no, _SFR_MEM8 for C is defined as "_MMIO_BYTE(mem_addr)". Look it up and see that it is exactly the same thing as fixed code proposes. For assembly it is just a number.

So ultimately your code turns into  (*(volatile uint8_t *)(0x0060)) = "some value". You need to do the same in your code.
« Last Edit: October 08, 2018, 06:35:45 am by ataradov »
Alex
 

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 17814
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: [gcc C] concatenating text to make up code
« Reply #59 on: October 08, 2018, 06:38:12 am »

So ultimately your code turns into  (*(volatile uint8_t *)(0x0060)) = "some value". You need to do the same in your code.

So what is the difference there? that assigns a value to a calculated address location, or is it the asterisks that make it work (pointers?)
 

Online ataradov

  • Super Contributor
  • ***
  • Posts: 11238
  • Country: us
    • Personal site
Re: [gcc C] concatenating text to make up code
« Reply #60 on: October 08, 2018, 06:39:33 am »
Yes, it makes a difference. This code casts the constant address to a pointer, then dereferences the pointer and assigns the value to that dereferenced value.

You are assigning constant to a constant.
Alex
 

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 17814
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: [gcc C] concatenating text to make up code
« Reply #61 on: October 08, 2018, 06:44:25 am »
I see, so *(volatile uint8_t*) is the bit i am missing and tells the compiler it is a memory location, it feels like this was explained backwards as my initial question was: can I simply assign a value to a calculated memory address location? the answer was no you need pointers.
 

Online ataradov

  • Super Contributor
  • ***
  • Posts: 11238
  • Country: us
    • Personal site
Re: [gcc C] concatenating text to make up code
« Reply #62 on: October 08, 2018, 06:45:48 am »
You do need pointers. This expression is full of pointer operations.
Alex
 

Offline Nusa

  • Super Contributor
  • ***
  • Posts: 2416
  • Country: us
Re: [gcc C] concatenating text to make up code
« Reply #63 on: October 08, 2018, 06:57:29 am »
* in this context is called dereferencing, or indirection.
https://en.wikipedia.org/wiki/Dereference_operator

So *(0x0060) says we want to access the location pointed to by 0x0060.

The (volatile uint8_t *) part is assigning a type override so the compiler knows that we want to do a byte operation rather than a word operation. And to keep the compiler from throwing errors at you since the typing is necessary when using raw constants like this. (edited to be more correct)

« Last Edit: October 08, 2018, 07:10:24 am by Nusa »
 

Online ataradov

  • Super Contributor
  • ***
  • Posts: 11238
  • Country: us
    • Personal site
Re: [gcc C] concatenating text to make up code
« Reply #64 on: October 08, 2018, 06:59:30 am »
Not really. "*(0x0060)" is not a valid expression in C. Typecast is not just to prevent compiler from complaining, it is necessary there.
Alex
 

Offline Nusa

  • Super Contributor
  • ***
  • Posts: 2416
  • Country: us
Re: [gcc C] concatenating text to make up code
« Reply #65 on: October 08, 2018, 07:08:08 am »
Yes, I know...when it's a variable instead of a constant, the variable already has an associated type. But I was trying to show the dereference separate from the typing, since Simon is having trouble grasping the whole.
 

Offline cv007

  • Frequent Contributor
  • **
  • Posts: 825
Re: [gcc C] concatenating text to make up code
« Reply #66 on: October 08, 2018, 10:44:29 am »
Quote
Just look at the manufacturers own chip header file.
I know quite well how they do it, that's where I was getting my numbers in my example. I think I said in one of your other threads- either embrace them (manufacturers headers) or do your own thing. As long as you are doing your own thing, you are free to do as you wish and not restricted to the way everybody does it.

I have a pic32mm which I wrote 'drivers' for every peripheral and usb- I have a total of 6 defines in all the code (2 for isr declarations, 4 in usb for generating parts of descriptor- when there was no other option). It will work for every pic32mm-gpm chip made (they only vary by pin count, memory size). I dislike their headers, their code generators, so I decided to do my own thing. So I'm not unaware what you want to do.

Quote
So microchip are mad to write things like:
I think I also showed in another one of your threads how this works-
https://www.eevblog.com/forum/microcontrollers/(atmega-0)-tcat-(aka-union-tca-union)-has-no-member-named-ctrl/msg1771667/#msg1771667

mini tutorial-
((volatile uint8_t*)(0x400))[0x10] = 8;
0x400 - just a number
(uint8_t*)0x400 - an address that points to an 8bit number
(volatile uint8_t*)0x400 - an address that points to an 8bit number which is volatile- tell compiler it has to read/write every time it is used as it can change without anyone's knowledge (hardware)
*(volatile uint8_t*)0x400 - get/set the 8bit value in the location 0x400
((volatile uint8_t*)0x400)[0] - or get/set the 8bit value in the location 0x400+0 (0x400 now acts like a pointer to an array of 8bit numbers, and we want the first element)

result-
((volatile uint8_t*)(0x400))[0x10] = 8; //write the value of 8 to the 16th element in the array of 8bit numbers which are at address 0x400 (ultimately at address 0x410)
 

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 17814
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: [gcc C] concatenating text to make up code
« Reply #67 on: October 08, 2018, 04:41:09 pm »
so the [0x10] has the effect of +0x10 ? why not just +0x10 then?

So essentially to address memory i need to multiply the address by (volatile uint8_t*) or is it *(volatile uint8_t*) ?
 

Online ataradov

  • Super Contributor
  • ***
  • Posts: 11238
  • Country: us
    • Personal site
Re: [gcc C] concatenating text to make up code
« Reply #68 on: October 08, 2018, 04:44:29 pm »
You really need to understand how this works, not just copy-paste. This stuff is critical in C.

[0x10] is a standard array operation. It is equivalent to incrementing the address by sizeof(uint8_t) * 0x10. This is important, since the element size is uint8_t, and increment happens in bytes. This will not be the case if the array element type is different.

"a[ b ]" in C is 100% the same as "*(a + b)". Either a or be may be a pointer and the other one must be an integer.
« Last Edit: October 08, 2018, 04:46:36 pm by ataradov »
Alex
 

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 17814
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: [gcc C] concatenating text to make up code
« Reply #69 on: October 08, 2018, 05:01:19 pm »
Yes i have every intention of understanding pointers but I'm not there yet.
 

Online langwadt

  • Super Contributor
  • ***
  • Posts: 4414
  • Country: dk
Re: [gcc C] concatenating text to make up code
« Reply #70 on: October 08, 2018, 06:46:50 pm »
so the [0x10] has the effect of +0x10 ? why not just +0x10 then?

So essentially to address memory i need to multiply the address by (volatile uint8_t*) or is it *(volatile uint8_t*) ?

multiply is the wrong word 
(volatile uint8_t*)  tells the compiler that the following should be seen as a pointer to volatile uint8_t
putting a * in front tell it use it as a pointer
 

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 17814
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: [gcc C] concatenating text to make up code
« Reply #71 on: October 08, 2018, 07:38:45 pm »
OK, I see, notes to self:

Pointers in C
Variables contain values and reside in a memory location that has an address. Pointers hold the address of another variable.
The address value of the variable x is represented by &x.
The data type of a pointer variable is the same as the data type of the variable who’s address it is to store. A pointer variable is declared by putting an asterisk before its name.

int *pointer;
pointer = &x;

The pointer can be used to refer to the value of the data stored at the address of the variable pointed to. To do this put an asterisk in front of the pointer.

Int x, y;
int *pointer;
int pointer = &x;
y = *pointer;

y is now the same value of x.

« Last Edit: October 08, 2018, 08:20:41 pm by Simon »
 

Online IanB

  • Super Contributor
  • ***
  • Posts: 11859
  • Country: us
Re: [gcc C] concatenating text to make up code
« Reply #72 on: October 08, 2018, 09:42:17 pm »
Yes, and in addition pointers know the size of the thing they point to.

For example:

int *pointer1; /* pointer1 points to ints */
int x;
pointer1 = &x; /* OK, because x is an int and it matches the pointer type */
int *pointer2 = pointer1 + 1; /* pointer2 points to the next integer in memory */

Be very careful to understand that pointer2 does not point one memory address after pointer1. If an int is 4 bytes, then pointer2 points 4 bytes after pointer1. When you increment a pointer or do pointer arithmetic, the arithmetic always works with objects of the size the pointer references.
 

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 17814
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: [gcc C] concatenating text to make up code
« Reply #73 on: October 09, 2018, 06:20:00 am »
OK but I still do not understand how all of this relates to:

(*(volatile uint8_t*)(PORTS__OFFSET + PORTS__OFFSET_GAP * port + DATA_DIR_SET)) = 0x01 << pin;


(*(volatile uint8_t*) ????? and I am still not clear on if it is one asterisk or two.

The first asterisk which seems to be the optional one would suggest that we are pointing to the data at the address of the variable that presumably is being made up on the spot and is the address we want to write to? The second one is a mystery or is it also denoting the number as an address and using the parenthesis to stop things getting misinterpreted by the compiler?

(*(volatile uint8_t*) is something I have not found an explanation to anywhere.
 

Offline tombi

  • Regular Contributor
  • *
  • Posts: 163
  • Country: au
Re: [gcc C] concatenating text to make up code
« Reply #74 on: October 09, 2018, 07:06:45 am »
Dunno if this helps

So the PORTS_OFFSET... expression calculates a pointer address

(uint8_t *) casts this as a pointer to an 8 bit unsigned integer. Lets leave volatile for a bit but then using *(uint8_t *)(XXX) then de-references the pointer (i.e. gets the 8 bit unsigned integer the pointer points at).

Volatile is a way of making the compiler not snip out references to data it thinks shouldn't have changed (for example because it thinks the program didn't change it). Without volatile it might replace this with a constant as it thinks the value hasn't changed.

Tom
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf