GPIO_IOF_SEL in LED Fade Demo

I’m carefully examining each line of the code for led_fade.c and arrived at this (line #83)

GPIO_REG(GPIO_IOF_SEL) &= ~IOF0_UART0_MASK;

I read the FE310-G000 documentation regarding GPIO, but do not understand why the IOF_SEL is inverting the mask above and ANDing it to the register. The net effect is that the mask bits (16 & 17 for UART GPIO) are cleared in the IOF_SEL register. How is this exactly selecting anything?

Most pins have a secondary hardware function (PWM, SPI, UART etc). Setting the corresponding bit in IOF_SEL allows you to override the associated hardware function and control the pin directly as GPIO instead. E.g.,:

// Disable HW functions
GPIO_REG(GPIO_IOF_SEL)   |=  (1 << PIN_18_OFFSET);
// Enable a GPIO as output
GPIO_REG(GPIO_OUTPUT_EN)   |=  (1 << PIN_18_OFFSET);
// Write value to pin
GPIO_REG(GPIO_OUTPUT_VAL) |=  (1 << PIN_18_OFFSET);

Would manually enable pin 18. The corollary is that to use the hardware function (in the case of led_fade the UART for debug prints) you’d first clear the IOF_SEL bit for those pins. It’s a little redundant as the UART has previously been enabled in ./bsp/env/freedom-e300-hifive1/init.c but it’s useful to note.

1 Like

Ok, so I guess this what I was missing. Clearing the bit enables the hardware function and not vice versa. And yes I was wondering why this was done in fade when it was already done in init() already. Thanks!

1 Like

Actually, I don’t see where _init() is called. It seems you must explicitly call it from your program?

I think env/start.S invokes init() and then main() (sorry, on my phone and don’t have the code in front of me :slight_smile: ) . That’s probably why that NO_INIT define is present, so you can effectively disable the init() and customise your own high-level startup without having to mess around with the assembly directly.

That’s the thing, no where in start.S does it call _init. I think it has to be called explicitly unless I’m missing it elsewhere.

To clarify, setting GPIO_IOF_EN enables the IOF (hardware function). For any GPIO pin, there are 2 possible IOF functions, in addition to the basic GPIO function. GPIO_IOF_SEL selects which if the IOF functions you want, which is why the code sets it to 0 for the UART (because it is on IOF 0). In contrast, many of the PWM pins use IOF 1, so they set the GPIO_IOF_SEL bits, and also set the GPIO_IOF_EN bits.

1 Like

Also, you do not need to explicitly call the _init and _fini functions. Those functions have special meaning for GCC.

3 Likes

Thanks!! That makes perfect sense! I hope documentation is updated with this information just to clarify it for future users. Awesome work Megan!

You guys discussed very usefull thinks ,thanks for the information, and i am trying to configured the UART ,through fredom-e SDk ,can you people just help me to get code

hello knor,
in the below code ,of UART base adress they have specified with UL what it indicates actually.
#define UART0_CTRL_ADDR _AC(0x10013000,UL).