1
0
mirror of https://github.com/rfivet/stm32bringup.git synced 2024-12-18 23:06:28 -05:00
stm32bringup/docs/14_ledon.html

134 lines
4.4 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>1.4 User LED ON</title>
<link type="text/css" rel="stylesheet" href="style.css">
</head>
<body>
<h1>1.4 User LED ON</h1>
Turning the user LED on is the simplest direct feedback you can get from
a board. Most boards you can buy online have two LEDs: power and user.
In order to know where the user LED is connected and how to drive it on,
you need to know the board you are developing for.
<h2>Meet your board</h2>
The board I am using is made by VCC-GND Studio and its specifications
can be found
<a href="https://stm32-base.org/boards/STM32F030F4P6-VCC-GND.html">here</a>.
Taking a look at the schematics I can see that the user LED is connected to
GPIO B1 and will turn on when that pin is driven low.
<p>
<img alt="user LED connected to GPIO B1" src="img/14_ledpb1.png">
<p>
This board is based on the micro-controller STM32F030F4P6, so let's
learn about its implementation of GPIOs.
<h2>Know your chipset</h2>
From the datasheet
<a href="https://www.st.com/content/st_com/en/search.html#q=DS9773-t=resources-page=1">
DS9773</a>,
I learn that pin 14 of the 20 pin package defaults as PB1 after reset.
It's a 3.3V tolerant I/O pin and can be configured either as an output,
an input or one of several alternate functions. The GPIO peripherals are
connected on the AHB2 Bus which means that they can be controlled
through their registers visible in the AHB2 sub-range of the Peripherals
range of address. For GPIO B, that means the address range 0x48000400 to
0x480007FF.
<p>
Diving in the reference manual
<a href="https://www.st.com/content/st_com/en/search.html#q=%20RM0360-t=resources-page=1">
RM0360</a>,
I find the layout of the GPIO B registers and their initial state plus
the info that peripheral clocks need to be enabled through the Reset and
Clock Controller (<b>RCC</b>) connected on the AHB1 bus. So I need to activate
the clocks of GPIO B through the RCC before I can access its registers.
<p>
To turn the user LED on, I need to
<ul>
<li> Enable the clock of GPIO B
<li> Configure B1 mode as an output by selecting mode 01
<li> Configure B1 type as a push-pull, which is the reset value (0)
<li> Set B1 value to 0, which is the reset value (0)
</ul>
<h2>Code and Build</h2>
I start by making a copy of <b>boot.c</b> into <b>ledon.c</b> and rework the
<b>Reset_Handler</b> to light up the LED before entering the idle loop.
<pre>
/* Memory locations defined by linker script */
extern long __StackTop ; /* &__StackTop points after end of stack */
void Reset_Handler( void) ; /* Entry point for execution */
/* Interrupt vector table:
* 1 Stack Pointer reset value
* 15 System Exceptions
* NN Device specific Interrupts
*/
typedef void (*isr_p)( void) ;
isr_p const isr_vector[ 2] __attribute__((section(".isr_vector"))) = {
(isr_p) &__StackTop,
/* System Exceptions */
Reset_Handler
} ;
#define RCC ((volatile long *) 0x40021000)
#define RCC_AHBENR RCC[ 5]
#define RCC_AHBENR_IOPBEN 0x00040000 /* 18: I/O port B clock enable */
#define GPIOB ((volatile long *) 0x48000400)
#define GPIOB_MODER GPIOB[ 0]
void Reset_Handler( void) {
/* User LED ON */
RCC_AHBENR |= RCC_AHBENR_IOPBEN ; /* Enable IOPB periph */
GPIOB_MODER |= 1 << (1 * 2) ; /* PB1 Output [01], over default 00 */
/* OTYPER Push-Pull by default */
/* PB1 output default LOW at reset */
for( ;;) ;
}
</pre>
- I use the C preprocessor to specify the mapping of the peripheral
registers.
<p>
- The naming convention is from the Reference Manual, the address
locations from the Data Sheet.
<p>
- Registers are indicated as <b>volatile</b> as they may change out of the code
control, this way the compiler will avoid optimizations based on known states.
<p>
To build I just request the format I need, either <b>.bin</b> or <b>.hex</b>.
<pre>
$ make ledon.hex
ledon.elf
text data bss dec hex filename
40 0 0 40 28 ledon.elf
ledon.hex
rm ledon.elf ledon.o
</pre>
<h2>Test</h2>
Once the board has been flashed with this code, the user LED lights up
at reset. It turns out to be blue. &#x1F60E;
<p>
<img alt="User LED on" src="img/14_ledon.png">
<h2>Checkpoint</h2>
I covered the basic of GPIO output programming by turning the user LED
on.
<p>
<a href="15_blink.html">Next</a>, I will implement the classic blinking
LED.
<hr>© 2020-2024 Renaud Fivet
</body>
</html>