1
\$\begingroup\$

My question may seem weird, but I am very new in nxp micro-controllers. It seems to me that people use different syntax in C programming. For example, in order to set a pin as an output we have:

LPC_GPIO1->FIODIR |= (1<<29);

while there is another syntax which does the same thing and it looks like this:

FIO1DIR |= (1<<29);

And they both have similar libraries. As I am learning the second type, I wanted to know if there is a reference for this type of coding?

\$\endgroup\$
  • 2
    \$\begingroup\$ Open up the header files and trace back until you find where those are defined. As you can see, they're spelled differently. When you've found them, you'll see what the difference is. \$\endgroup\$ – pipe Mar 15 '17 at 16:56
1
\$\begingroup\$

it is all driven by the header files used. the first approach used a struct (pointer) to the gpio base address to address all the registers related to that port. the 2nd approach used a pointer to the exactly same address.

end of the day, it is the same thing, different packaging.

edit: here is the gist of it.

typedef struct {
    uint32_t PIN;           //data register
    uint32_t SET;
    uint32_t DIR;
    uint32_t CLR;
} GPIO_TypeDef;             //gpio structure

#define GPIO                ((GPIO_TypeDef *)&IOPIN)

int main(void) {
    while (1) {
        GPIO->DIR ^=0xffff; //flip the lowest 16 bits
        IODIR     ^=0xffff; //doing the same
    }
}

This particular chip has four registers associated with its GPIO, IOPIN, IOSET, IODIR and IOCLR; one way to address it, in this case, IODIR, is to use the macro defined in the header file, as shown in the main loop.

alternatively, you can define a struct, GPIO_TypeDef that includes the four registers in the right order (as per the compiler). you then "fix" the GPIO as a pointer to that struct but anchored to the same address starting with IOPIN.

So the two approaches of flipping the lowest 16 bits in the IODIR registers will achieve the same goal.

This approach requires a few things: 1. the port structure is the same from port to port, chip to chip; 2. the endianness is known.

most newer chips (with the exception of msp430 and pic) follow that. so you will the struct approach used widely nowadays.

\$\endgroup\$
  • \$\begingroup\$ Thanks, I need to learn how they work. Where can I have a reference? \$\endgroup\$ – user2326844 Mar 15 '17 at 17:07
  • \$\begingroup\$ @user2326844 open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf is the reference. \$\endgroup\$ – pipe Mar 15 '17 at 17:12
  • \$\begingroup\$ The advantage of using structures is that it may be easier to maintain your code if you move a function from one port to another. The possible disadvantage is that it may produce slightly bigger code but in practice most modern optimising compilers will realise that these are just two different ways of talking to the same register so this will be optimised out and should make no difference to final code size. \$\endgroup\$ – Warren Hill Mar 15 '17 at 23:42
2
\$\begingroup\$

This is elementary C programming has nothing to do with your microcontroller.

You can have a variable:

unsigned int jim;

and you can have structures

typedef struct
{
    unsigned int bob;
    unsigned int ted;
    unsigned int carol;
    unsigned int alice;
}  MYSTRUCT;
MYSTRUCT one;
MYSTRUCT *two;

In the case of one, we have asked the compiler to allocate the memory for that structure, it is compiled in basically not a malloc thing. For the two case that is saying we have allocated a pointer only, the address to the structure, but the memory for the structure is not yet allocated. in the case of what you are seeing, they use the latter case then use C tricks to force the address of two to be a specific address, then we can know/assume that from that bob, ted, ... are known offsets, so if you have say a bank of uart registers, and there are 10 of them and they are 32 bits wide you could in theory define a 10 element structure of 32 bit variables tell the compiler you want that structure aimed at the beginning of that register bank and then by accessing elements within the structure you access those registers. Or you could just make individual variables like the jim variable above and likewise point that at some location (during the declaration so that at compile time the address is forced). There is more C syntax I am not showing to force the address, but using the variable defined above the syntax for those variations is as follows:

jim=5;
one.bob=5;
two->bob=5;

with a variable you just use the name if it is a variable within a structure then it depends on if the base name of the structure is a pointer or not, if not a pointer you use a dot between the structures base name and the variable within one.bob, and if it is a pointer then you use an arrow two->bob. assume that one and two are not pointing at the same address so those are really two separate bob variables.

What you are seeing is two different ways to approach the problem of creating variables that can be used at the address of a hardware register, and by using different declaration techniques you get the two styles you pointed out in your question.

\$\endgroup\$
  • \$\begingroup\$ sorry I cannot up-vote at the moment. so, thank you so much. \$\endgroup\$ – user2326844 Mar 15 '17 at 18:06

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.