Author Topic: Mapping structures to hardware registers  (Read 14084 times)

0 Members and 1 Guest are viewing this topic.

Online SiliconWizard

  • Super Contributor
  • ***
  • Posts: 15435
  • Country: fr
Re: Mapping structures to hardware registers
« Reply #125 on: March 07, 2023, 07:17:32 pm »
Almost everyone (except DiTBHO) agrees it's a colossally bad idea to hide pointerness behind a typedef, the loss of readability for no reason whatsoever is obvious. You don't need to convince us about that.

IIRC from what he said earlier, he uses naming conventions to show those are pointer types. So it's not hidden. It's just a convention. And as I said, this was pretty much the same convention in Pascal, so people with a Pascal or similar background are more likely to use this convention.

I personally do not use it with C, but I'm not ferociously against it either. I also use some naming conventions, just not that.

As to namespaces, yes C "namespaces" are just a weird legacy.

But I don't think "standalone" namespaces, such as in C++, are a good idea. They are also an ugly hack. I much prefer the concept of modules, which create namespaces of their own but encapsulate code and provide a consistent structure, not just an after-thought hack. This is part of why I find C++ modules ugly. They are themselves an ugly hack not providing much of what modules should provide, and they still require declaring an explicit namespace, that's absolutely horrific.
« Last Edit: March 07, 2023, 07:20:28 pm by SiliconWizard »
 

Offline bson

  • Supporter
  • ****
  • Posts: 2465
  • Country: us
Re: Mapping structures to hardware registers
« Reply #126 on: March 07, 2023, 11:57:20 pm »
The Atmel bitfields were rather non-compliant with CMSIS, and had performance and RMW issues that were less than obvious.  The Microchip definitions are annoyingly verbose (but more consistent, I think?  I mean, it used to be difficult to tell bit numbers from bitmasks from field values.  And similar.  Now, it's not, but you have to type _MSK, _POS, _VAL, and similar all over.)
The problem as I see it is that the registers are volatile.  So setting three bits and clearing two requires five bit operations.
 

Offline westfw

  • Super Contributor
  • ***
  • Posts: 4315
  • Country: us
Re: Mapping structures to hardware registers
« Reply #127 on: March 08, 2023, 02:25:58 am »
Quote
setting three bits and clearing two requires five bit operations.
There was at least one vendor library that made use of local variables typed like the peripherals (but not volatile) that would overcome this problem.
Code: [Select]
uart_init() {
  SERCOM_UART_CTRLA_Type myctrla = SERCOM0->CTRLA;
  myctrla.bit.ENABLE = 1;
  myctrla.bit.TXPO = xx;
  myctrla.bit.RXPO = yy;
  // :
  SERCOM0->CTRLA = myctrla;
}
(might have been ASF, might have been one of ST's frameworks.)
I'm not sure that this works with properly CMSIS-compliant headers, and I'm not entirely sure I like it, but I thought it was "interesting", and it does give the compiler a chance for optimizations.
 

Online ataradov

  • Super Contributor
  • ***
  • Posts: 11780
  • Country: us
    • Personal site
Re: Mapping structures to hardware registers
« Reply #128 on: March 08, 2023, 02:45:56 am »
ARM's own CMSIS header files have stuff like:
Code: [Select]
typedef union
{
  struct
  {
    uint32_t ISR:9;                      /*!< bit:  0.. 8  Exception number */
    uint32_t _reserved0:15;              /*!< bit:  9..23  Reserved */
    uint32_t T:1;                        /*!< bit:     24  Thumb bit        (read 0) */
    uint32_t _reserved1:3;               /*!< bit: 25..27  Reserved */
    uint32_t V:1;                        /*!< bit:     28  Overflow condition code flag */
    uint32_t C:1;                        /*!< bit:     29  Carry condition code flag */
    uint32_t Z:1;                        /*!< bit:     30  Zero condition code flag */
    uint32_t N:1;                        /*!< bit:     31  Negative condition code flag */
  } b;                                   /*!< Structure used for bit  access */
  uint32_t w;                            /*!< Type      used for word access */
} xPSR_Type;
Although it is never used in their code, it is just defined for convenience. So, I'm not sure if there is any specific "compliance" thing.
Alex
 

Offline Siwastaja

  • Super Contributor
  • ***
  • Posts: 8869
  • Country: fi
Re: Mapping structures to hardware registers
« Reply #129 on: March 08, 2023, 06:40:29 am »
enums and structs confuse the hell out of me, it's like I am defining a type either way and I'm not sure what to call it. I have now settled on making it a typedef every time as it seems that is what it is and it works better.

It is confusing. There are three cases:
(1) creation of a throw-away type and a single object of that type.
(2) creation of a type in struct namespace, requiring the repetition of struct keyword when the type is used to create objects.
(3) creation of a type in global namespace with typedef. Objects can be created with type name alone.
 

Offline John Coloccia

  • Super Contributor
  • ***
  • Posts: 1217
  • Country: us
Re: Mapping structures to hardware registers
« Reply #130 on: March 08, 2023, 10:14:15 am »

C namespaces have nothing to do with actual namespaces, it's just a weird, arbitrary legacy thing. C does not have real namespaces (I'm quite OK with this limitation, though).

 I just have no idea what you're talking about. C doesn't have user defined namespaces, but it has 4 distinct, real namespaces. Not sure why you keep saying it's a weird legacy thing.  :-//
 

Offline Siwastaja

  • Super Contributor
  • ***
  • Posts: 8869
  • Country: fi
Re: Mapping structures to hardware registers
« Reply #131 on: March 08, 2023, 11:07:35 am »
I just have no idea what you're talking about. C doesn't have user defined namespaces, but it has 4 distinct, real namespaces. Not sure why you keep saying it's a weird legacy thing.  :-//

I don't know how to explain myself any better. Others seem to understand and agree. If you don't get it, then... you just don't. Good luck.
 

Online SiliconWizard

  • Super Contributor
  • ***
  • Posts: 15435
  • Country: fr
Re: Mapping structures to hardware registers
« Reply #132 on: March 08, 2023, 07:22:59 pm »
I just have no idea what you're talking about. C doesn't have user defined namespaces, but it has 4 distinct, real namespaces. Not sure why you keep saying it's a weird legacy thing.  :-//

I don't know how to explain myself any better. Others seem to understand and agree. If you don't get it, then... you just don't. Good luck.

Yeah. Those C "namespaces" are type-bound, or rather bound to classes of types. That's the oddest thing that has ever existed in any programming language as I can recall.
And while they do exist, they provide no benefit that I know of. For instance, who in their right mind would use the same identifier for an enum and for a struct?

It is obviously a legacy thing.
 
The following users thanked this post: Siwastaja

Offline JPortici

  • Super Contributor
  • ***
  • Posts: 3527
  • Country: it
Re: Mapping structures to hardware registers
« Reply #133 on: March 08, 2023, 08:19:44 pm »
For instance, who in their right mind would use the same identifier for

Exactly. Then again we have coding standards because there are people that will Buffalo buffalo Buffalo buffalo buffalo buffalo Buffalo buffalo :)
i've seen my share of
Code: [Select]
class classname {
 ...
}

...

classname classname;
classname::staticmethod();
classname.method();

simply because you can.
IIRC it is even permitted/encouraged in other languages, such as the Imperium Program Language  ;D Or at least the parser doesn't complain, the language creator said
« Last Edit: March 08, 2023, 08:25:05 pm by JPortici »
 
The following users thanked this post: Siwastaja

Offline Nominal Animal

  • Super Contributor
  • ***
  • Posts: 6963
  • Country: fi
    • My home page and email address
Re: Mapping structures to hardware registers
« Reply #134 on: March 08, 2023, 09:17:03 pm »
Then again we have coding standards
and good principles, like the Principle of Least Surprise.  When applied to source code statements, it simply means that Thou Shall Not Use Ambiguous Statements.

In my own example code, you see this in e.g. "superfluous" quotes that help humans see exactly the intent of the statement, and how I use static inline for accessors and helpers even though plain static has the exact same behaviour in C.

Ambiquity has surprisingly high maintenance cost.  Since in C the name of a function is equivalent to a pointer to that function (i.e., strlen == &strlen), one should avoid ambiquity in variable and function naming.  The one division that makes sense to me is type names having a different "namespace" than variable and function names in C, because they are unambiguous in expressions.  In C++, however, as JPortici showed, they can be ambiguous (in the example, class name vs. variable).

(My point being, because I apply the Principle of Least Surprise, I often do have variables with the same name as their type in C, but carefully try and avoid that in C++ and Python [especially wrt. class names and variable names].  In Python, I prefer to use Capitalized names for classes, and member and variable names beginning with a lowercase letter, for this particular reason; adjusting my "preferred style" to minimize ambiquity.)

For this reason, I like to investigate the reasons behind the choices in various coding styles and standards.  It is illuminating.
 

Offline nctnico

  • Super Contributor
  • ***
  • Posts: 28090
  • Country: nl
    • NCT Developments
Re: Mapping structures to hardware registers
« Reply #135 on: March 08, 2023, 10:29:36 pm »
What I usually do is have types start with a T for a struct, E for an enum and C for a class. That way it is somewhat clear what kind of type you are dealing with and what kind of parameter is passed to a function. But there are many other conventions with sound reasoning to use them. Whatever floats your boat  ;D
There are small lies, big lies and then there is what is on the screen of your oscilloscope.
 

Offline Nominal Animal

  • Super Contributor
  • ***
  • Posts: 6963
  • Country: fi
    • My home page and email address
Re: Mapping structures to hardware registers
« Reply #136 on: March 08, 2023, 10:49:36 pm »
But there are many other conventions with sound reasoning to use them. Whatever floats your boat  ;D
Yep.  In particular, when contributing to existing codebases, it always pays to familiarize oneself to the coding style/convention, before submitting even a preliminary suggestion for comments.

It is good practice for oneself (to avoid ossifying within ones existing preferences), but it also shows you're willing to spend the time and effort yourself, changing yourself from an "user" asking for/demanding a change, into a "contributor" suggesting a change.  In Libre/FOSS projects, that makes for a huge difference.

When I happen to dislike a convention, knowing the reasons behind the convention (and how that particular convention helps with the issues seen in that particular codebase) significantly reduces my irritation when having to use it.  "This is annoying, but there is these ideas and useful intent behind it, so I guess I can just deal with it" -type of thing.
 
The following users thanked this post: newbrain

Offline nctnico

  • Super Contributor
  • ***
  • Posts: 28090
  • Country: nl
    • NCT Developments
Re: Mapping structures to hardware registers
« Reply #137 on: March 08, 2023, 10:59:33 pm »
I really like the existence of formatters to convert between coding conventions. I code the way I like to code because I think it is the most readable / understandable. Don't like it? Here is your converter and go do something useful with your time  >:D

Still I'm open to suggestions. A couple of years ago I got one complaint about my coding style and that was/is that I don't use spaces in expressions. That is a remnant of writing Basic on home computers where every space took another byte of precious memory. I found it a good suggestion, wondered why it hadn't occured to me before and I've made it a point to use more spaces from that moment on.
There are small lies, big lies and then there is what is on the screen of your oscilloscope.
 

Offline cv007

  • Frequent Contributor
  • **
  • Posts: 855
Re: Mapping structures to hardware registers
« Reply #138 on: March 09, 2023, 01:12:25 am »
Quote
There was at least one vendor library that made use of local variables typed like the peripherals (but not volatile) that would overcome this problem.
The atmel headers do this. Each register with a bitfield becomes another struct/union type with its members not volatile. Not sure any other manufacturer has done register bitfields, so the list is short. This allows creating a temp var to be created where you can manipulate the temp bitfields then write the results to the full register (useful for when setting more than one bitfield in a register). It works fine since the compiler can optimize this, but gets a little tedious to write  It also prevents the use of anonymous bitfields since you now need a name for these bitfield structs (so end up with .bit access).

Another alternative is to give up some efficiency and just treat each bitfield separately-
https://godbolt.org/z/66esq9a31
It ends up doing more reads/writes than needed, but you will be able to use anonymous bitfields and most register manipulation becomes simple to write/read. You still always need to be aware what is happening behind the scenes (rmw), so have to watch out for things like clearing flag registers which cannot use the bitfield. Giving up efficiency in many cases is worth the ease of use- the smaller mcu probably does not have a lot of peripheral setup code and the larger mcu has the resources to not care very much that your setup code is not as efficient as it could be.

Same example using manufactures headers-
https://godbolt.org/z/5YnzaK35c
You now have bit manipulation code to produce, but since they are inside functions they are write-once and you will rarely have to deal with the internals of the function again.

The path of least resistance is to use what is provided by the manufacturer for peripheral register access. Peripheral register manipulation should stay inside functions, so you shouldn't find yourself having to do register bit manipulation in your app code. In the end, since it seems only atmel has provided these type of headers, and creating them on your own has its own problems (automated or not), there is little chance anyone other than some atmel users are even presented with the bitfield option.
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf