The preferred alternative for controlling a GPIO is via a BSP. Because this BSP (board support package) does all the work for you in setting all peripherals to good defaults and and allowing you to call a function. Possibly your BSP of choice will have a function to write a byte to an 8-bit GPIO port; your LED will only have one bit. In this case your C code could look like: (at least: it will work like this on Luminary Micro kits). (Example code; requires a bit of extra work to make it compile especially on your kit).
/* each LED is addressed by an address (byte) and a bit-within-this-byte */
struct {
address, // address of IO register for LED port
bit // bit of LED
} LEDConfigPair;
struct LEDConfigPair LEDConfig[NUMBER_OF_LEDS] = {
{GPIO_PORTB_BASE,0}, // LED_0 is at port B0
{GPIO_PORTB_BASE,1} // LED_1 is at port B1
} ;
/* function LED_init configures the GPIOs where LEDs are connected as output */
led_init(void)
{
U32 i;
for(i=0;i<NUMBER_OF_LEDS;i++)
{
GPIODirModeSet( LEDConfig[i][0], LEDConfig[i][1], GPIO_DIR_MODE_OUT );
}
}
/* my LED function
set_led_state makes use of the BSP of Luminary Micro to access a GPIO function
Implementation: this BSP requires setting 8 port wide IO, so the function will calculate a mask (
*/
set_led_state(U8 led,bool state)
{
U8 andmask;
U8 setmask;
andmask = ~(1 << LEDConfig[led].bit);// a bitmask with all 1's except bit of LED
if (true == state)
{
setmask = (1 << LEDConfig[led].bit); // set bit for LED
} else
{
setmask = 0;
}
GPIOPinWrite(LEDConfig[led].address, andmask, setmask);
}
Of course this is all spelled out; it can be done in a single lines like this:
#DEFINE SETLEDSTATE(led,state) GPIOPinWrite(LEDConfig[led].address, ~(1<<LEDConfig[led].bit),(state<<LEDConfig[led].bit))
this will do the same, but only makes sense when you can dream bit masks, and you only want to toggle some LEDs to debug the real program...
The alternative: bare metal.
In this case you need to set up everything for yourself. For an embedded system, you need to be aware of pin multiplexing and power management (assuming memory controller and cpu clocks are already set up!)
- initialization: set pin multiplexing in such a way that the function you want to control is actually mapped on the package.
- initialization of pheripheral (in this case either a UART, or a GPIO function on the same pin)