Part 2 - Introduction To Bare Metal Programming
Part 2 - Introduction To Bare Metal Programming
Date: 18/8/2021
1
How to create Keil MDK ARM Project
Bare metal programming
Using Nucleo-L053R8
2
KEIL ® MDK ARM V5 IDE
KEIL MDK ARM V5 Integrated Development Environment is a powerful tool to edit, write and
compile code in single environment. On top it is developed with a working environment for
debugging and downloading the executable code.
(1)
(1)
(2)
(1)
(2)
(1)
(2)
(3)
Type the controller type i.e. stm32l053r8 [1] and click on the controller type displayed [2] 6
CONFIGURE THE MANAGE RUN-TIME ENVIRONMENT
(1)
(3)
(2)
Under CMSIS, tick on “core” [1], under Device, tick on “startup” [2] and make sure the project is standalone [3]
7
CONFIGURE THE OPTION FOR TARGET - DEVICE
(1)
(2)
Click on “Option for Target” [1] and ensure the correct device is selected [2]
8
CONFIGURE THE OPTION FOR TARGET - TARGET
(1)
Click on “Target” [1] and ensure the setting match the setting above
9
CONFIGURE THE OPTION FOR TARGET - OUTPUT
(1)
(3)
(2)
Click on “Output” [1], tick on “create HEX File” [2]. Naming the executable file name is an optional [3]
10
CONFIGURE THE OPTION FOR TARGET - LISTING
(1)
11
Click on “Listing” [1], and ensure the setting match the setting above
CONFIGURE THE OPTION FOR TARGET - LINKER
(1)
(2)
Click on “Linker” [1], and tick on “Use Memory Layout from Target Dialog” [2] 12
CONFIGURE THE OPTION FOR TARGET - DEBUG
(1)
(2) (3)
Click on “Debug” [1], and select “ST-Link Debugger” [2] and click setting [3] 13
CONFIGURE TARGET DRIVER SETUP - DEBUG
(1)
(2)
Using Nucleo-L053R8
15
The Simple Example Project
16
KEIL® MDK ARM PROJECT – ADD EXISTING FILE TO PROJECT
[1] { }
[2] { }
Right Click on “Source Group” [1], and select “Add New Item to Source Group 1”… [2] 17
KEIL® MDK ARM PROJECT – ADD EXISTING FILE TO PROJECT
[1] { }
[3] { }
[4] { }
[2] { }
Locate the folder where the code is located [1], make sure only C Source file/s [2], Select file/s [3] and click "Add" [4]
18
All files are provided in …………..\codesBmNo1 subfolder
KEIL® MDK ARM PROJECT – COMPILING THE PROJECT
[1] { }
[2] { }
Click on “build” icon or <FCN><F7> [1]. The correct code should generate no error [2]
19
KEIL® MDK ARM PROJECT – DOWNLOADING THE EXECUTABLE FILE
[1] { }
Click on “Download” icon or <FCN><F8> [1]. Once downloaded, press reset (black) button to execute the project.
20
Writing bare metal
code No1
The code presents the way to set System Clock to HSI16 through PLL and
working with GPIO (GPIOC13 input & GPIOA5 output)
21
(1)
(3.a)
(3.b)
(3.c)
(4)
(5)
(2) (6.a)
(6)
(6.b)
(6.c)
(7)
(8)
22
Install Keil ® MDK ARM V5
Get Nucleo-L053R8
Create a project – host the code How to Create A Project Using Nucleo L053R8.pptx
23
(1)
(2)
(3)
24
(1)
(2)
(3) (5)
(8)
(6.a)
(4)
(6.b)
(7.a)
(7.b)
25
The selection of HSI via the PLL to support the system clock
26
Clock control register (RCC_CR) – pg 184
/*enable PLL */
RCC->CR |=RCC_CR_PLLON; // PLL ON
while(!(RCC->CR & RCC_CR_PLLRDY)){}; // wait while PLL locked
/*disable PLL */
RCC->CR &=~RCC_CR_PLLON; // PLL ON
while(RCC->CR & RCC_CR_PLLRDY){}; // wait till PLL locked /*enable HSI Oscillator */
RCC->CR |= RCC_CR_HSION; // HSI16 oscillator ON
while(!(RCC->CR & (RCC_CR_HSIRDY))){}; // HSI 16 MHz oscillator not re
/*Configure to HSI is not divided */
If(RCC->CR & RCC_CR_HSIDIVF){
RCC->CR &=~ RCC_CR_HSIDIVEN; // disable HSI divide
}
27
Clock configuration register (RCC_CFGR) – pg 189
29
The step to set GPIO into input or output Mode
The steps:
1. Enable the associate port clock
2. Set the I/O mode.
3. Set the I/O output type.
4. Set the I/O output speed.
5. Select or disable the pull-up or pull-down resistor.
30
GPIO clock enable register (RCC_IOPENR)– pg 201
RCC->IOPENR |= RCC_IOPENR_IOPCEN;
RCC->IOPENR |= RCC_IOPENR_IOPAEN;
31
GPIO port mode register (GPIOx_MODER)– pg 246
GPIOA->OTYPER &=~GPIO_OTYPER_OT_5;
GPIOA->OTYPER &=~(1UL<<5);
33
GPIO port pull-up/pull-down register (GPIOx_PUPDR)– pg 247
34
CODE TO CONFIGURE PA5 OUTPUT PUSH PULL & PC13 INPUT; WITHOUT PU/PD RESISTOR
/* Configure GPIOA */
RCC->IOPENR |= RCC_IOPENR_IOPAEN; // enable GPIOA Clock
GPIOA->MODER &=~GPIO_MODER_MODE5; // PA5 output
GPIOA->MODER |= GPIO_MODER_MODE5_0;
GPIOA->OTYPER &=~GPIO_OTYPER_OT_5; // push-pull
GPIOA->PUPDR &=~GPIO_PUPDR_PUPD5; // no pull up/down
/* Configure GPIOC */
RCC->IOPENR |= RCC_IOPENR_IOPCEN; // enable GPIOC Clock
GPIOC->MODER &=~GPIO_MODER_MODE13; // PC13 input
GPIOC->PUPDR &= ~GPIO_PUPDR_PUPD13; // no pull up/down
35
GPIO port input data register (GPIOx_IDR)– pg 248
36
Note: The push button is configured in active low and buttonPos must be defined to (13)
GPIO port bit set/reset register (GPIOx_BSRR) - pg 248
GPIOA->BSRR = 1UL<<(5+16);
Turn ON LED
GPIOA->BSRR = 1UL<<ledPos;
GPIOA->BSRR = 1UL<<5;
37
Note: The LED is configured in active high and ledPos must be defined to (5)
GPIO port bit reset register (GPIOx_BRR) - pg 251
GPIOA->BRR = 1UL<<5;
38
Note: The LED is configured in active high and ledPos must be defined to (5)
39
40
41
42
…………………………..\codesBmNo2\Code No2 -bare metal
43
Copy code in ……………..\codesBmNo2\Code_No2—bare metal.pdf and paste in main.c
44
How to handle Mutiple Files
Bare metal programming
Using Nucleo-L053R8 + Multi-learning shield
45
The Simple Example Project
46
KEIL® MDK ARM PROJECT – ADD EXISTING FILES TO PROJECT
[1]
[1] { }
[2] { }
Right Click on “New Group”[1] and select “Add New Item to Source Group 1”….. [2] 49
KEIL® MDK ARM PROJECT – ADD EXISTING FILES TO PROJECT
[1] { }
[3] { }
[4] { }
[2] { }
Locate the folder where the code is located [1], make sure only C Source file/s [2], Select file/s [3] and click "Add" [4]
50
All files are provided in …………..\codesBmNo3 subfolder
KEIL® MDK ARM PROJECT – OPEN FILES, Expand & Collapse Subfolder
[1] { }
[2] { }
Left-click twice on a file to open the file, click on ‘+’ [1] to expand the subfolder, and click on ‘-’ [2]to collapse the subfolder.
51
KEIL® MDK ARM PROJECT – COMPILING THE PROJECT
[1] { }
[2] { }
Click on “build” icon or <FCN><F7> [1]. The correct code should generate no error [2]
52
KEIL® MDK ARM PROJECT – DOWNLOADING THE EXECUTABLE FILE
[1] { }
Click on “Download” icon [1] or <FCN><F8>. Once downloaded, press reset (top right) button to execute the project.
53
[1] { }
54
[1] { }
[2] { }
[3] { } [4] { }
[5] { }
Click on “Option forTarger” [1] . Choose Debug [2] Tab.
Ensure “ST-Link Debugger [3] is selected. Click on
[6] { } Setting [4] button. Click Flash Download [5] Tab.
Enable “Reset and Run” [6] function.
55
Using an Extended Interrupt
Bare metal programming
Nucleo-L053R8
56
Time and event trigger – An Overview
In the reset state, all interrupt is disabled. The processor starts executing foreground code instructions (in the main function for example) which are
generally at the lowest priority. Usually, exception handler or background code instructions are designed at a higher priority.
Since the background code is placed at a higher priority, any enabled interrupt can pre-empt the processor. When an enabled interrupt is asserted, the
interrupt is serviced by the corresponding interrupt service routine (ISR) handler. The processor runs the ISR at the priority level of the interrupt
execution. And when the ISR is complete, the original priority level is restored.
When an interrupt is asserted with a lower or equal priority level, the ISR is pended from being executed. However, when an interrupt is asserted with a
higher priority level, the lower priority ISR is pended to give way to the higher priority ISR being executed. The lower priority ISR execution57will resume
upon completion of the higher priority ISR execution.
ARM PROCESSOR MODE
When an exception occurs, the current processor execution is stopped, and the
processor accesses the exception vector table
(1) The address of the exception vector is loaded from the vector table.
(2) The exception handler is run in exception mode.
(3) The handler is returned to the previous processor handler.
59
Exception Types
60
Exception Types
Reset
Reset is invoked on power up or a warm reset. The exception model treats reset as a special form of exception. When reset is asserted, the
operation of the processor stops, potentially at any point in an instruction. When reset is deasserted, execution restarts from the address
provided by the reset entry in the vector table. Execution restarts as privileged execution in Thread mode.
NMI A
NonMaskable Interrupt (NMI) can be signalled by a peripheral or triggered by software. This is the highest priority exception other than reset. It is
permanently enabled and has a fixed priority of -2. NMIs cannot be: • Masked or prevented from activation by any other exception. • Preempted
by any exception other than Reset.
HardFault
A HardFault is an exception that occurs because of an error during normal or exception processing. HardFaults have a fixed priority of -1, meaning
they have higher priority than any exception with configurable priority.
SVCall
A Supervisor Call (SVC) is an exception that is triggered by the SVC instruction. In an OS environment, applications can use SVC instructions to
access OS kernel functions and device drivers.
PendSV
PendSV is an interrupt-driven request for system-level service. In an OS environment, use PendSV for context switching when no other exception
is active
SysTick
A SysTick exception is an exception the system timer generates when it reaches zero. Software can also generate a SysTick exception. In an OS
environment, the processor can use this exception as system tick.
Interrupt (IRQ)
An interrupt, or IRQ, is an exception signalled by a peripheral, or generated by a software request. All interrupts are asynchronous to instruction
execution. In the system, peripherals use interrupts to communicate with the processor.
61
PM0223 Programming manual page 26-27
Exception States
Inactive
The exception is not active and not pending.
Pending
The exception is waiting to be serviced by the processor. An interrupt
request from a peripheral or from software can change the state of
the corresponding interrupt to pending.
Active
An exception that is being serviced by the processor but has not
completed. Note: An exception handler can interrupt the execution of
another exception handler. In this case both exceptions are in the
active state.
62
PM0223 Programming manual page 26
EXTENDED INTERRUPT – Interrupt Vector Table
63
PM0223 Programming manual page 29
EXTENDED INTERRUPT – Startup file
64
Exceptions Priorities Overview
65
PM0223 Programming manual page 27
EXTI (External Interrupts) Controller
EXTI Controller Overview
The extended interrupt/event controller consists of 28 edge detector lines used to generate
interrupt/event requests. Each line can be individually configured to select the trigger event (rising
edge, falling edge, both) and can be masked independently. A pending register maintains the status
of the interrupt requests.
66
EXTI Controller Block Diagram
Functional Description
For the configurable interrupt lines, the interrupt line should be
configured and enabled in order to generate an interrupt. This is done
by programming the two trigger registers with the desired edge
detection and by enabling the interrupt request by writing a ‘1’ to the
corresponding bit in the interrupt mask register. When the selected
edge occurs on the interrupt line, an interrupt request is generated.
The pending bit corresponding to the interrupt line is also set. This
request is cleared by writing a ‘1’ in the pending register.
Hardware interrupt selection
To configure a line as an interrupt source, use the following
procedure:
1. Configure the mask bits of the Interrupt lines (EXTI_IMR)
2. Configure the Trigger Selection bits of the Interrupt lines
(EXTI_RTSR and EXTI_FTSR)
3. Configure the enable and mask bits that control the NVIC IRQ
channel mapped to the extended interrupt controller (EXTI) so
that an interrupt coming from any one of the lines can be
correctly acknowledged.
67
RM0367 Reference manual page 287
EXTI External Interrupts GPIO Mapping
68
RM0367 Reference manual page 288-289
Interrupt
Request
69
Setting Up GPIO into EXTI
/* (1) Enable the peripheral clock of GPIOC */
/* (2) Select input mode (00) on GPIOC pin 13 */
/* (3) Select Port C for pin 13 extended interrupt by writing 0010
in EXTI13 (reset value) */
/* (4) Configure the corresponding mask bit in the EXTI_IMR register */
/* (5) Configure the Trigger Selection bits of the Interrupt line
on rising edge */
/* (6) Configure the Trigger Selection bits of the Interrupt line
on falling edge */
/* Configure NVIC for Extended Interrupt */
/* (7) Set priority for EXTI4_15 */
/* (7) Enable Interrupt on EXTI4_15 */
70
RM0367 Reference manual page 260-261 & 957
Code to set GPIO into EXTI
void initEXTI(void)
{
RCC->IOPENR |= 1UL<<2; // enable GPIOC Clock
GPIOC->MODER &=~(3UL<<13*2); // input
GPIOC->PUPDR &=~(3UL<<13*2); // no pull up/down
71
Interrupt service routine EXTI4_15
void EXTI4_15_IRQHandler(void)
{
static int i;
if (EXTI->PR & 1UL<<13) // if request from EXTI13
{
EXTI->PR &= 1UL << 13; // Clear the EXTI status flag.
/* do whatever */
for(i=0;i<1000;i++){};
if((blueButtonPort->IDR & 1UL<<13)==0) // reduce key debounce effect
greenLEDPort->ODR ^= 1UL<<13; // toggle green LED
}
}
72
The Simple Example Project
o The green LED toggles at interval 2000ms
o The green LED toggles if the blue button is pressed.
73
All files are provided in …………..\codesBmNo4 subfolder
Using System Tick Timer
Bare metal Programming
Nucleo-L053R8 + Multi-learning shield
74
SYS TICK TIMER – An Overview
• Standard hardware component
built into ARM Cortex-M
• Periodically forces the processor to
execute the ISR
Example usage:
Measuring time elapsed such as time delay
function
Executing task periodically, such periodically
polling and OS CPU scheduling
24-bit
75
SYS TICK TIMER – Initialize and Handler Interrupted each 1ms
void SysTick_Init(void) {
SysTick->CTRL = 0;
SysTick->LOAD = (uint32_t)((systemClk/1000) - 1); /* SysTick Counter Value */
//SysTick->VAL = 0;
SysTick->CTRL = (SysTick_CTRL_TICKINT_Msk | /* Enable SysTick exception */
SysTick_CTRL_ENABLE_Msk) | /* Enable SysTick system timer */
SysTick_CTRL_CLKSOURCE_Msk; /* Use processor clock source */
}
void SysTick_Handler(void)
The theSystick variable increase on each interrupt
{
theSystick++;
}
Returns the present theSystick variable value/contents
uint32_t getSysTick(void)
{
return theSystick;
} * systemClk must be defined to the operational System Clock frequency
76
PM0223 Programming manual page 95-98
SYS TICK TIMER – How to use Sys Tick Timer?
--------
tick0=tick1=….=tickN =getSysTick();
--------
while(1) {
if(tick0<getSysTick()){
tick0 += val?;
-----------------
//user code
-----------------
}//tick0
if(tick1<getSysTick()){
tick1 += val?;
-----------------
//user code
-----------------
}//tick1
-----------------
-----------------
if(tickN<getSysTick()){
tickN += val?;
-----------------
//user code
-----------------
}//tickN
-------------------
} 77
SYS TICK TIMER – How to use Sys Tick Timer?
78
The Simple Example Project
79
All files are provided in …………..\codesBmNo5 subfolder
Good House Keeping
Bare metal Programming
Nucleo-L053R8 + Multi-learning shield
Motivation
81
Write a software for others as you wish they would write for you
Some Basic Things – Self-Documenting Code
Credit to Valvano
Comment describes
why the functions is executed
the maximum and minimum value of the variable
Selection of identifier
Choose any name that is make sense
User comments Colleagues comment
What are the possible valid inputs? How does it work?
What are the resulting outputs? What algorithm are used?
What are the error conditions?
82
Always, write simple and clear software that is easy to understand without comments
Some Basic Things – Software Abstraction
Credit to Valvano
Define a complex problem with a set of basic abstract techniques such as FSM, signal Flow …….
83
To define the problem is to solve the problem
Some Basic Things – Modular Programming
Credit to Valvano
Re-useable
Smaller and easier
Portability
Independently developed & tested
84
Divide and conquer
Example of Modular Programming
85
All files are provided in …………..\codesBmNo6A subfolder
86
87
88
89
More Example Project
90
All files are provided in …………..\codesBmNo6B subfolder
References
[1] STML0x3 Data Sheet, DocID025844 Rev 7, October 2016
[2] STML0x3 Reference Manual, DocID025274 Rev 3, RM0367, May 2015
[3] STM32™ Nucleo boards, DocID025838 Rev 5, NUCLEO-XXXXRX, September 2014
[4] Cortex®-M0 Programming manual, PM0223 Rev 5, October 2019
91