Author Topic: creating a function but not always using all the arguments  (Read 15417 times)

0 Members and 1 Guest are viewing this topic.

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 17814
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: creating a function but not always using all the arguments
« Reply #50 on: August 26, 2019, 04:39:53 pm »
So I cannot directly address memory (registers). i cannot write a "memory address = value" to write to a register.
 

Online oPossum

  • Super Contributor
  • ***
  • Posts: 1415
  • Country: us
  • Very dangerous - may attack at any time
Re: creating a function but not always using all the arguments
« Reply #51 on: August 26, 2019, 04:48:22 pm »
So is that a question.

*(uint32_t *)0x1234 = 0x5678;
 

Offline sokoloff

  • Super Contributor
  • ***
  • Posts: 1799
  • Country: us
Re: creating a function but not always using all the arguments
« Reply #52 on: August 26, 2019, 04:49:00 pm »
You are the master of incompletely specified questions/comments...  :-DD

If you want to write a byte "value" to the memory address PORTC_OS, you could do something like:

Code: [Select]
unsigned char value = 0x80;  // Or whatever value you want
unsigned char *port_C_OS = (unsigned char *) PORTC_OS;
*port_C_OS = value;
 

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 17814
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: creating a function but not always using all the arguments
« Reply #53 on: August 26, 2019, 05:02:15 pm »
OK, i am confused here. My defines are clashing with the ones already loaded and if i don't load them nothing works. But how the hell do i use the existing definitions?

If I type "PORT" I get that as a suggestion frommicrochips defines and it's equivalent to the address that PORTA starts at. Great, that's no use to me. What is the chip maker actually giving me? other than no instructions as to what they are they expect me to use their own code generator. Looking at the header files that I can find no register is explicitly pointed to with a variable. So what the hell am I doing? This is so stupid. If the manufacturer wants to supply existing headers why not document them for the slighly less giften in unravelling files and files linked together.

Unless I rewrite everything I can't even program the thing.
 

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 17814
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: creating a function but not always using all the arguments
« Reply #54 on: August 26, 2019, 05:12:33 pm »
So for example:

Code: [Select]
#define REG_PORT_DIR0              (*(RwReg  *)0x41000000UL) /**< \brief (PORT) Data Direction 0 */
#define REG_PORT_DIRCLR0           (*(RwReg  *)0x41000004UL) /**< \brief (PORT) Data Direction Clear 0 */
#define REG_PORT_DIRSET0           (*(RwReg  *)0x41000008UL) /**< \brief (PORT) Data Direction Set 0 */
#define REG_PORT_DIRTGL0           (*(RwReg  *)0x4100000CUL) /**< \brief (PORT) Data Direction Toggle 0 */
#define REG_PORT_OUT0              (*(RwReg  *)0x41000010UL) /**< \brief (PORT) Data Output Value 0 */
#define REG_PORT_OUTCLR0           (*(RwReg  *)0x41000014UL) /**< \brief (PORT) Data Output Value Clear 0 */
#define REG_PORT_OUTSET0           (*(RwReg  *)0x41000018UL) /**< \brief (PORT) Data Output Value Set 0 */
#define REG_PORT_OUTTGL0           (*(RwReg  *)0x4100001CUL) /**< \brief (PORT) Data Output Value Toggle 0 */
#define REG_PORT_IN0               (*(RoReg  *)0x41000020UL) /**< \brief (PORT) Data Input Value 0 */
#define REG_PORT_CTRL0             (*(RwReg  *)0x41000024UL) /**< \brief (PORT) Control 0 */
#define REG_PORT_WRCONFIG0         (*(WoReg  *)0x41000028UL) /**< \brief (PORT) Write Configuration 0 */
#define REG_PORT_EVCTRL0           (*(RwReg  *)0x4100002CUL) /**< \brief (PORT) Event Input Control 0 */
#define REG_PORT_PMUX0             (*(RwReg  *)0x41000030UL) /**< \brief (PORT) Peripheral Multiplexing 0 */
#define REG_PORT_PINCFG0           (*(RwReg  *)0x41000040UL) /**< \brief (PORT) Pin Configuration 0 */
#define REG_PORT_DIR1              (*(RwReg  *)0x41000080UL) /**< \brief (PORT) Data Direction 1 */
#define REG_PORT_DIRCLR1           (*(RwReg  *)0x41000084UL) /**< \brief (PORT) Data Direction Clear 1 */
#define REG_PORT_DIRSET1           (*(RwReg  *)0x41000088UL) /**< \brief (PORT) Data Direction Set 1 */
#define REG_PORT_DIRTGL1           (*(RwReg  *)0x4100008CUL) /**< \brief (PORT) Data Direction Toggle 1 */
#define REG_PORT_OUT1              (*(RwReg  *)0x41000090UL) /**< \brief (PORT) Data Output Value 1 */
#define REG_PORT_OUTCLR1           (*(RwReg  *)0x41000094UL) /**< \brief (PORT) Data Output Value Clear 1 */
#define REG_PORT_OUTSET1           (*(RwReg  *)0x41000098UL) /**< \brief (PORT) Data Output Value Set 1 */
#define REG_PORT_OUTTGL1           (*(RwReg  *)0x4100009CUL) /**< \brief (PORT) Data Output Value Toggle 1 */
#define REG_PORT_IN1               (*(RoReg  *)0x410000A0UL) /**< \brief (PORT) Data Input Value 1 */
#define REG_PORT_CTRL1             (*(RwReg  *)0x410000A4UL) /**< \brief (PORT) Control 1 */
#define REG_PORT_WRCONFIG1         (*(WoReg  *)0x410000A8UL) /**< \brief (PORT) Write Configuration 1 */
#define REG_PORT_EVCTRL1           (*(RwReg  *)0x410000ACUL) /**< \brief (PORT) Event Input Control 1 */
#define REG_PORT_PMUX1             (*(RwReg  *)0x410000B0UL) /**< \brief (PORT) Peripheral Multiplexing 1 */
#define REG_PORT_PINCFG1           (*(RwReg  *)0x410000C0UL) /**< \brief (PORT) Pin Configuration 1 */

So each port register is defined with a name and this seems to be the closest thing to what microchip provides for me to use out of the box.
Ports have now been renamed 1 and 2 instead of A and B, why not just do that, write all of the documentation in terms of port numbers instead of letters
 

Offline cv007

  • Frequent Contributor
  • **
  • Posts: 825
Re: creating a function but not always using all the arguments
« Reply #55 on: August 26, 2019, 05:14:23 pm »
This thread is hard to nail down, in more ways than one.

>But how the hell do i use the existing definitions?

You didn't like my little example of using the headers?
https://www.eevblog.com/forum/programming/creating-a-function-but-not-always-using-all-the-arguments/msg2642181/#msg2642181

You should just explain how you want your code to look- not how to implement. Once you decide what you want it to look like in use, then implementation becomes easier.


int main(){

  //I have 2 leds as outputs, 2 switches as input with pullups, this is how I would do it
  //forget that its not implemented, just how its going to be used when its all done

  //fill in what you want pin setup code to look like here...

}
 

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 17814
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: creating a function but not always using all the arguments
« Reply #56 on: August 26, 2019, 05:20:35 pm »
This thread is hard to nail down, in more ways than one.

>But how the hell do i use the existing definitions?

You didn't like my little example of using the headers?
https://www.eevblog.com/forum/programming/creating-a-function-but-not-always-using-all-the-arguments/msg2642181/#msg2642181

You should just explain how you want your code to look- not how to implement. Once you decide what you want it to look like in use, then implementation becomes easier.


int main(){

  //I have 2 leds as outputs, 2 switches as input with pullups, this is how I would do it
  //forget that its not implemented, just how its going to be used when its all done

  //fill in what you want pin setup code to look like here...

}

It's my usual brain storm when i try to use a new chip and the toss up between trying to do it my own way that i understand or work out how to drive the manufacturers stuff around without it getting in the way. Yes the topic has shifted somewhat. At the moment i can't even care what my code will look like as i am wrestling with how the manufacturer has defined things ani can i throw out anything that clashes as I'm a little worried about how much of the predefined stuff is for manual coding and how much is for the atmel start bull.

The Mega 0 series was hard work at the start until I realized how they had done the headers and it all made sense:

peripery instance followed by instance number . register, plain and simple. But what i see here does not look like it was made for human consumption but atmel start. If i try to redefine things i could just make matters worse.

 

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 17814
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: creating a function but not always using all the arguments
« Reply #57 on: August 26, 2019, 05:24:07 pm »
So is that a question.

*(uint32_t *)0x1234 = 0x5678;


Right, so that is the basis of naming a register and a value to put into it? Great. OK, I can see it uses pointers which i now gather is the only way C will let me access memory addresses. But that looks nothing like what several books on C for PC have to say about pointers. i can of course just take that as gospel and use it to address anf memory location (register) i need to but in makes no sense to me and sooner or later I will clash with a vendor definition. If i remove the vendor headers everything falls apart. I seem to be stuck in the middle.
 

Offline cv007

  • Frequent Contributor
  • **
  • Posts: 825
Re: creating a function but not always using all the arguments
« Reply #58 on: August 26, 2019, 05:28:13 pm »
you need to ignore stuff inside-
#if (defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
(but there could be an #else buried in the middle, so watch for it)

which is what you posted a few posts back

in include/yourdevice.h, the port address is defined as a pointer to a Port struct
#define PORT              ((Port     *)0x41004400UL) /**< \brief (PORT) APB Base Address */
#define PORT_IOBUS        ((Port     *)0x60000000UL) /**< \brief (PORT) IOBUS Base Address */

in include/component/port.h-
you will find all the structs, starting at the bottom of the file will be the outermost struct

in include/pio/yourdevice.h
will be pin number defines
 

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 17814
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: creating a function but not always using all the arguments
« Reply #59 on: August 26, 2019, 05:31:36 pm »
you need to ignore stuff inside-
#if (defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
(but there could be an #else buried in the middle, so watch for it)

which is what you posted a few posts back

Yes so it says if using assembly use this lot otherwise use: what I posted which I assume is being used for C and sets up a define for each register. The naming is a bit weired but it's the best i have so far.
 

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 17814
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: creating a function but not always using all the arguments
« Reply #60 on: August 26, 2019, 05:33:32 pm »
Port.h only has defines, no structs. I'll have a look for them. This is half my concern, this stuff is all over the place. What happens if we have to move to MAPLABX will everything still work?
 

Offline sokoloff

  • Super Contributor
  • ***
  • Posts: 1799
  • Country: us
Re: creating a function but not always using all the arguments
« Reply #61 on: August 26, 2019, 05:36:53 pm »
So for example:
Code: [Select]
#define REG_PORT_DIR0              (*(RwReg  *)0x41000000UL) /**< \brief (PORT) Data Direction 0 */

So each port register is defined with a name and this seems to be the closest thing to what microchip provides for me to use out of the box.
Ports have now been renamed 1 and 2 instead of A and B, why not just do that, write all of the documentation in terms of port numbers instead of letters
That macro definition is designed to make REG_PORT_DIR0 "look like" a variable. It contains the definition of the pointer:
Code: [Select]
(RwReg  *)0x41000000UL
and the dereferencing of the pointer:
Code: [Select]
(* <the pointer as above> )so to assign an unsigned 32 bit value to it (the RwReg is defined as uint32_t), you just write:
Code: [Select]
REG_PORT_DIR0 = <the value you want to assign>
 

Offline sokoloff

  • Super Contributor
  • ***
  • Posts: 1799
  • Country: us
Re: creating a function but not always using all the arguments
« Reply #62 on: August 26, 2019, 05:38:23 pm »
which ends up functioning exactly like the code @oPossum wrote above. (I'm saying this just to help you understand pointers thoroughly "this afternoon"  :-DD )

Code: [Select]
(*(RwReg  *)0x41000000UL) = <the value>;
 

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 17814
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: creating a function but not always using all the arguments
« Reply #63 on: August 26, 2019, 05:43:51 pm »
so why does this asterisk keep moving around, the books put it before the variable that will be replaced with the address of what it points to yet all of this register stuff puts it after something follewed by a parenthisis. Is this declaration and assicnment all in one?
 

Offline sokoloff

  • Super Contributor
  • ***
  • Posts: 1799
  • Country: us
Re: creating a function but not always using all the arguments
« Reply #64 on: August 26, 2019, 05:50:10 pm »
I'll take a stab at it, but it's not going to be second-nature for a while.

In the expression:
(*(RwReg *)0x41000000UL) = <the value>;

I think of it this way:
Take an unsigned long number 0x41000000
Treat is as a pointer to an RwReg.
Then, take that pointer and assign the location to which it points the value.
 

Offline cv007

  • Frequent Contributor
  • **
  • Posts: 825
Re: creating a function but not always using all the arguments
« Reply #65 on: August 26, 2019, 05:53:43 pm »
an attempt at a simple explanation-

//include/yourdevice.h
#define PORT  ((Port     *)0x41004400UL)

//include/pio/yourdevice.h
#define PIN_PA05 5
#define PORT_PA05 (_UL_(1) <<  5)

//include/component/port.h
typedef struct {
       PortGroup Group[1]; //this has only one port (port A)
} Port;

typedef struct {
  __IO PORT_DIR_Type             DIR;
  __IO PORT_DIRCLR_Type          DIRCLR;
  __IO PORT_DIRSET_Type          DIRSET;
  __IO PORT_DIRTGL_Type          DIRTGL;
  __IO PORT_OUT_Type             OUT;   
  __IO PORT_OUTCLR_Type          OUTCLR;
  __IO PORT_OUTSET_Type          OUTSET;
  __IO PORT_OUTTGL_Type          OUTTGL;
  __I  PORT_IN_Type              IN;   
  __IO PORT_CTRL_Type            CTRL; 
  __O  PORT_WRCONFIG_Type        WRCONFIG;
       RoReg8                    Reserved1[0x4];
  __IO PORT_PMUX_Type            PMUX[16];
  __IO PORT_PINCFG_Type          PINCFG[32];
       RoReg8                    Reserved2[0x20];
} PortGroup;

//etc, other structs defined above this one


PORT->Group[0] will be the struct of the first PORT (port A)
PORT->Group[1] will be the struct of the second PORT (port B) if you had one


to set a pin PA05 as output-

without ->
(*PORT).Group[0].DIRSET.reg = 1<<PIN_PA05; //pin number
or with -> as its intended to make it simpler to use
PORT->Group[0].DIRSET.reg = 1<<PIN_PA05; //pin number
or
PORT->Group[0].DIRSET.reg = PORT_PA05; //this is a bitmask, but gives no info on what port it belongs to

or if you have more than port A, use the bit to figure out the port
as PIN_PxXX will be consecutive (PIN_PB02 is defined as 34)

PORT-Group[PIN_PB05/32].DIRSET.reg = 1<<(PIN_PB05%32);
« Last Edit: August 26, 2019, 06:09:20 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: creating a function but not always using all the arguments
« Reply #66 on: August 26, 2019, 06:00:41 pm »
Right so (RwReg *)0x41000000UL is making the memory location appear to be a pointed to variable

(*(RwReg *)0x41000000UL) = <the value>; puts the value in the address pointed to. But the confusing bit is that there is no variable name. i think that is what makes it look so different from standard pointers that don't explicitly control the address they only point to whatever address the compiler gave the variable.
« Last Edit: August 26, 2019, 06:39:27 pm by Simon »
 

Online Nominal Animal

  • Super Contributor
  • ***
  • Posts: 6255
  • Country: fi
    • My home page and email address
Re: creating a function but not always using all the arguments
« Reply #67 on: August 26, 2019, 07:05:58 pm »
Let's examine the macro definition:
    #define  REG_PORT_DIR0  (*(RwReg  *)0x41000000uL)
If may be easier to understand if we split it in three parts:
    #define  REG_PORT_DIR0_ADDR  0x41000000uL
    #define  REG_PORT_DIR0_PTR   ((RwReg *)REG_PORT_DIR0_ADDR)
    #define  REG_PORT_DIR0       (*REG_PORT_DIR0_PTR)
So, the key here is that the two asterisks have different meanings.

In C, expressions of form (type)value, or equivalently (type)(value), are casts.  They convert the type of the value to type.  Above, 0x41000000uL is value, and RwReg * is type, a pointer to RwReg.

The REG_PORT_DIR0 macro dereferences the RwReg pointer to 0x41000000uL.  So, in the original macro, the first asterisk dereferences a pointer, whereas the second asterisk is part of a pointer type specification, as part of a cast from integer address to an RwReg pointer.

Most likely, somewhere in the header files you'll see a typedef similar to  typedef  volatile unsigned long  RwReg; which means that
    REG_PORT_DIR0 = 5;
is effectively the same as
    *((volatile unsigned long *)0x41000000uL) = 5;
which is effectively the same as
    ((volatile unsigned long *)0x41000000uL)[0] = 5;
i.e, the part in parentheses defines a pointer to a volatile unsigned long, and that pointer is immediately dereferenced without being assigned to any variable; it is how you use "pointer literals" in C.
 

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 17814
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: creating a function but not always using all the arguments
« Reply #68 on: August 26, 2019, 07:37:08 pm »
Thank you, that makes more sense.

 

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 17814
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: creating a function but not always using all the arguments
« Reply #69 on: August 26, 2019, 08:13:42 pm »
Well i have a square wave on the screen of my scope from toggling every pin of both ports. Just a bit mystifyed as to why all of port A does not seem to work.

So I am back to square one, writing directly to register memory locations is easy, but anf definitions i write are bound to clash with those already present. If i try to remove the monster of header files that are automatically attched to the project nothing will work any more.
 

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 17814
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: creating a function but not always using all the arguments
« Reply #70 on: August 26, 2019, 08:50:25 pm »
aha, removed their setup code and my defines seem to work now and no errors. Porta still does not work. i am getting a wavefom through but it's like when you set an output to toggle but forget to set the pin direction up and the high impedance of the scope just manages to see the waveform anyway.
« Last Edit: August 26, 2019, 08:52:20 pm by Simon »
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf