QuestionQuestion

Transcribed TextTranscribed Text

Lab 1 – Interfacing with LED using GPIO, Interrupts, and SysTick Objectives 1. Get familiar with the Keil μVision software development environment 2. Learn the basics of GPIO configurations: input/output, push-pull/open-drain, pull-up/down, GPIO speeds 3. Program GPIO registers to perform simple digital input (interfacing push button) and output (interfacing LED) 4. Understand polling I/O (busy waiting) and its inefficiency 5. Understand I/O interrupts 6. Understand the basic procedure of interrupt handling 7. Understand auto stacking and unstacking of the interrupt handling process 8. Understand the basic concept of the system timer (SysTick) 9. Use SysTick to create time delay functions 1 Lab Overview A. Use polling to turn on, turn o↵, or toggle di↵erent LEDs when pressing down on di↵erent directions of the joystick. The left joystick button should toggle the green LED, the right joystick button should toggle the red LED, the up joystick button should turn on both LEDs, the down joystick button should turn o↵ both LEDs, and the center joystick button should toggle both LEDs. B. Implement a subset of the functionality as in part A. However, you will use interrupts instead of polling. C. Use SysTick to generate an interrupt every 1 ms. Implement a function that toggles the red LED every second by implementing function delay(). 2 Introduction 2.1 Clock Configuration There are two major types of clocks: system clock and peripheral clock. 2.1.1 System Clock To meet the requirement of performance and energy-eciency for di↵erent applications, the processor core can be driven by four di↵erent clock sources including High Speed Internal (HSI) oscillator clock, High Speed External (HSE) oscillator clock, Phase Locked Loop (PLL) clock, and Multispeed Internal (MSI) oscillator clock. A faster clock provides better performance but usually consumes more power, which is not appropriate for battery-powered systems. 2.1.2 Peripheral Clock All peripherals must be clocked to function. However, the clocks of all peripherals are turned o↵ by default to reduce power consumption. Figure 1 shows the clock tree of, the processor used on the discovery board. This particular diagram shows the configuration of a 80 MHz SYSCLK and 11.2941 MHz SAI (SAI is not used in this lab). The clock sources in the domain of Advanced High-Performance Bus (AHB), low speed Advanced Peripheral Bus 1 (APB1), and high speed Advanced Peripheral Bus 2 (APB2) can be switched on or o↵ independently when not in use. The software can select various clock sources and scaling factors to achieve the desired clock speed depending on the application’s needs. The following definition of void System Clock Init() uses the 16 MHz HSI as the input to the PLL clock. Appropriate scaling factors have been selected to achieve the maximum allowed clock speed (80 MHz). 2 void System_Clock_Init(void) { // ... // Enable the HSI oscillator RCC->CR |= RCC_CR_HSION; while(!(RCC->CR & RCC_CR_HSIRDY)); RCC->CR &= ~RCC_CR_PLLON; while((RCC->CR & RCC_CR_PLLRDY) == RCC_CR_PLLRDY); // Select PLL as the clock source RCC->PLLCFGR &= ~RCC_PLLCFGR_PLLSRC; RCC->PLLCFGR |= RCC_PLLCFGR_PLLSRC_HSI; // 00 - No clock, 01 - MSI, // 10 - HSI, 11 - HSE // Make PLL 80 MHz // f(VCO clk) = f(PLL clk input) * PLLN / PLLM = 16 MHz * 20 / 2 = 160 MHz // f(PLL_R) = f(VCO clk) / PLLR = 160 MHz / 2 = 80 MHz RCC->PLLCFGR = (RCC->PLLCFGR & ~RCC_PLLCFGR_PLLN) | 20U << 8; RCC->PLLCFGR = (RCC->PLLCFGR & ~RCC_PLLCFGR_PLLM) | 1U << 4; RCC->PLLCFGR &= ~RCC_PLLCFGR_PLLR; // 00 - PLLR = 2, 01 - PLLR = 4, // 10 - PLLR = 6, 11 - PLLR = 8 RCC->PLLCFGR |= RCC_PLLCFGR_PLLREN; // Enable Main PLLCLK output RCC->CR |= RCC_CR_PLLON; while(!(RCC->CR & RCC_CR_PLLRDY)); // Set PLL as the system clock RCC->CFGR &= ~RCC_CFGR_SW; RCC->CFGR |= RCC_CFGR_SW_PLL; // 00 - MSI, 01 - HSI, 10 - HSE, 11 - PLL // Wait until system clock is selected while((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_PLL); // ... } 3 4 2.2 GPIO – General Purpose Input/Output On the STM32L4 discovery board, there are 8 GPIO ports (A,B,C,D,...,H) with 16 pins each. Figure 2 shows a diagram of a single GPIO pin. Each of the GPIO pins can be configured in the software as an output (push-pull or open-drain), as an input (with or without pull- up/down), or as a peripheral alternative function. Each GPIO port x 2 {A,B,C,D,...,H} has Four 32 bit configuration registers GPIOx MODER (mode register) GPIOx OTYPER (output type register) GPIOx OSPEEDR (output speed register) GPIOx PUPDR (pull-up/pull-down register) Two 32 bit data registers GPIOx IDR (input data register) GPIOx ODR (output data register) One 32 bit set/reset register GPIOx BSRR One 32 bit locking register GPIOx LCKR Two 32 bit alternative function registers GPIOx AFRH (alternative function high register) GPIOx AFRL (alternative function low register) Figure 2: GPIO Pin 5 2.3 The LEDs and the Joystick on the Board There are two LEDs on the discovery board (see Figure 3): the red LED is connected to PB2 (GPIO Port B Pin 2) and the green LED is connected to PE8 (GPIO Port E Pin 8). To light an LED, the software must perform at least the following three operations: 1. Enable the clock of the corresponding GPIO port. (Recall that all peripheral clocks are turned o↵ by default to improve energy eciency.) 2. Set the mode of the corresponding GPIO pin to output. (By default, the GPIO pin mode is analog.) 3. Set the output value of the corresponding GPIO pin to 1. (When the output value of a GPIO pin is 1, the voltage on the GPIO pin is 3 V. On the other hand, when the output value of a GPIO pin is 0, the voltage on the GPIO pin is 0 V.) Figure 3: LEDs on the Discovery Board The joystick (MT-008A) is composed of five buttons. Each button is connected to a GPIO pin, which are connected to a common ground (see Figure 4). The joystick buttons are connected to pins PA0 (select/center), PA1 (left), PA2 (right), PA3 (up), and PA5 (down). Furthermore, a capacitor and resistor are connected to each GPIO pin for hardware debouncing (see Figure 5). Figure 4: Joystick on the Discovery Board Figure 5: Hardware Debouncing on the Joystick 6 3 Part A – Polling In this part of the lab, you will turn on, turn o↵, or toggle the red and green LEDs using the di↵erent buttons on the joystick. For this part of the lab, you are required to use polling (waiting while constantly checking to see whether an event occurs) to implement this function. The code you will write involves writing certain bits to di↵erent registers. To do this, we will use a technique called masking. Masking is a technique that lets us toggle, set, or reset specific bits of a word (4 bytes) while keeping the remaining bits unchanged. Given a mask and a target variable word, we can perform the following operations using bitwise operators in C. word |= mask; // Set bits in word specified by mask word &= ~mask; // Reset bits in word specified by mask word ^= mask; // Toggle bits in word specified by mask Consider a simple example. Let variable word be 1 byte and let’s say that we want to set bit 2 of the variable. We can do this with the following line of code word |= 4; Recall that a | 0 = a and a | 1 = 1. Thus, using the OR operation withmask=4=0b0100 lets us set bit 2 without modifying the rest of the bits in the variable word. Note that word = 4; is not the correct approach because bits 0, 1, and 3 are reset in addition to setting bit 2. Next, we need to determine the masks that we need for several registers so that we can per- form di↵erent tasks such as configuration of di↵erent GPIO pins. Use the following steps to initialize/configure the registers for this part of the lab. Use the provided tables to help you determine what the mask should be (in hexadecimal). Note: The register names and many macros are defined in the file stm32l476xx.h. You should be referring to this file to determine what registers you must modify (and what masks to apply). 3.1 Enable the Clock of GPIO Ports A (Joystick), B (Red LED), and E (Green LED) in RCC Register Mask Value AHB2ENR Mask = 0x AHB2ENR Value = 0x AHB2ENR 7 RNGEN 18 17 AESEN 16 14 ADCEN 13 OTGFSEN 12 11 10 GPIOPHEN 7 GPIOPGEN 6 GPIOPFEN 5 GPIOPEEN 4 GPIOPDEN 3 GPIOPCEN 2 GPIOPBEN 1 GPIOPAEN 0 31 30 29 28 27 26 25 24 23 22 21 20 19 15 9 8 3.2 Pin Initialization for Red LED (PB2) (a) Configure PB2 as Output GPIO Mode: Input (00), Output (01), Alternative Function (10), Analog (11 – default) Register Mask Value GPIO B MODER Mask = 0x GPIO B MODER Value = 0x (b) Configure PB2 Output Type as Push-Pull Output Type: Push-Pull (0, reset), Open-Drain (1) Register Mask Value GPIO B OTYPER Mask = 0x GPIO B OTYPER Value = 0x (c) Configure PB2 as No Pull-Up, No Pull-Down PUPD Type: No PUPD (00, reset), Pull-Up (01), Pull-Down (10), Reserved (11) Register Mask Value GPIO B PUPDR Mask = 0x GPIO B PUPDR Value = 0x MODER OTYPER Reserved PUPDR 8 PUPD15[1:0] 31 31 30 30 MODE15[1:0] 31 30 PUPD14[1:0] 29 29 28 28 MODE14[1:0] 29 28 PUPD13[1:0] 27 27 26 26 MODE13[1:0] 27 26 PUPD12[1:0] 25 25 24 24 MODE12[1:0] 25 24 PUPD11[1:0] 23 23 22 22 MODE11[1:0] 23 22 PUPD10[1:0] 21 21 20 20 MODE10[1:0] 21 20 PUPD9[1:0] 19 19 18 18 MODE9[1:0] 19 18 PUPD8[1:0] 17 17 16 16 MODE8[1:0] 17 16 PUPD7[1:0] 15 OT15 15 14 OT14 14 MODE7[1:0] 15 14 PUPD6[1:0] 13 OT13 13 12 OT12 12 MODE6[1:0] 13 12 PUPD5[1:0] PUPD4[1:0] 11 OT11 11 10 OT10 10 9 OT99 MODE5[1:0] 11 10 PUPD3[1:0] PUPD2[1:0] PUPD1[1:0] PUPD0[1:0] MODE3[1:0] 7 MODE2[1:0] 5 MODE4[1:0] 9 8OT88 8 7 OT77 6OT66 6 5 OT55 4OT44 4 3 OT33 2OT22 2 1 OT11 0OT00 0 MODE1[1:0] 3 MODE0[1:0] 1 3.3 Pin Initialization for Green LED (PE8) (a) Configure PE8 as Output GPIO Mode: Input (00), Output (01), Alternative Function (10), Analog (11 – default) Register Mask Value GPIO E MODER Mask = 0x GPIO E MODER Value = 0x (b) Configure PE8 Output Type as Push-Pull Output Type: Push-Pull (0, reset), Open-Drain (1) Register Mask Value GPIO E OTYPER Mask = 0x GPIO E OTYPER Value = 0x (c) Configure PE8 as No Pull-Up, No Pull-Down PUPD Type: No PUPD (00, reset), Pull-Up (01), Pull-Down (10), Reserved (11) Register Mask Value GPIO E PUPDR Mask = 0x GPIO E PUPDR Value = 0x MODER OTYPER Reserved PUPDR 9 PUPD15[1:0] 31 31 30 30 MODE15[1:0] 31 30 PUPD14[1:0] 29 29 28 28 MODE14[1:0] 29 28 PUPD13[1:0] 27 27 26 26 MODE13[1:0] 27 26 PUPD12[1:0] 25 25 24 24 MODE12[1:0] 25 24 PUPD11[1:0] 23 23 22 22 MODE11[1:0] 23 22 PUPD10[1:0] 21 21 20 20 MODE10[1:0] 21 20 PUPD9[1:0] 19 19 18 18 MODE9[1:0] 19 18 PUPD8[1:0] 17 17 16 16 MODE8[1:0] 17 16 PUPD7[1:0] 15 OT15 15 14 OT14 14 MODE7[1:0] 15 14 PUPD6[1:0] 13 OT13 13 12 OT12 12 MODE6[1:0] 13 12 PUPD5[1:0] PUPD4[1:0] 11 OT11 11 10 OT10 10 9 OT99 MODE5[1:0] 11 10 PUPD3[1:0] PUPD2[1:0] PUPD1[1:0] PUPD0[1:0] MODE3[1:0] 7 MODE2[1:0] 5 MODE4[1:0] 9 8OT88 8 7 OT77 6OT66 6 5 OT55 4OT44 4 3 OT33 2OT22 2 1 OT11 0OT00 0 MODE1[1:0] 3 MODE0[1:0] 1 3.4 Pin Initialization for Joystick (a) Configure PA0, PA1, PA2, PA3, and PA5 (Joystick Buttons) as Input GPIO Mode: Input (00), Output (01), Alternative Function (10), Analog (11 – default) Register Mask Value GPIO A MODER Mask = 0x GPIO A MODER Value = 0x (b) Configure PA0, PA1, PA2, PA3, and PA5 as No Pull-Up, No Pull-Down PUPD Type: No PUPD (00, reset), Pull-Up (01), Pull-Down (10), Reserved (11) Register Mask Value GPIO A PUPDR Mask = 0x GPIO A PUPDR Value = 0x After completing initialization of all necessary GPIO pins, you need to continuously poll to check for button presses. Use the same masking technique to implement the following func- tions: Left – Toggle the green LED Right – Toggle the red LED Up – Set both LEDs Down – Reset both LEDs Center – Toggle both LEDs MODER PUPDR 10 PUPD15[1:0] 31 30 MODE15[1:0] 31 30 PUPD14[1:0] 29 28 MODE14[1:0] 29 28 PUPD13[1:0] 27 26 MODE13[1:0] 27 26 PUPD12[1:0] 25 24 MODE12[1:0] 25 24 PUPD11[1:0] 23 22 MODE11[1:0] 23 22 PUPD10[1:0] 21 20 MODE10[1:0] 21 20 PUPD9[1:0] 19 18 MODE9[1:0] 19 18 PUPD8[1:0] 17 16 MODE8[1:0] 17 16 PUPD7[1:0] 15 14 MODE7[1:0] 15 14 PUPD6[1:0] 13 12 MODE6[1:0] 13 12 PUPD5[1:0] 11 10 MODE5[1:0] 11 10 PUPD4[1:0] 89 MODE4[1:0] 98 MODE3[1:0] 67 PUPD3[1:0] 67 PUPD2[1:0] 54 PUPD1[1:0] 32 PUPD0[1:0] 10 MODE2[1:0] 45 MODE1[1:0] 23 MODE0[1:0] 10 4 Part B – Interrupts In this part of the lab, you are to implement a subset of the functions specified in part A. Specifically, pressing left should toggle the green LED, pressing right should toggle the red LED, and pressing center should toggle both LEDs. However, you are required to use interrupts to handle button presses instead of polling. Figure 6 First, you need to set up the GPIO pins as in part A (enabling the necessary clocks and configuring the desired GPIO pins as inputs). Next, you need to set up the external interrupt (EXTI) for GPIO pin k (the pin that corresponds to the button). See Figure 6 to see which EXTI lines are connected to the GPIO pins for the joystick inputs. The following steps outline the general procedure for doing this. 1. Configure the SYSCFG external interrupt configuration register (SYSCFG EXTICR) to map GPIO port j pin k to the EXTI input line k. SYSCFG->EXTICR[0] &= ~SYSCFG EXTICR1 EXTIk; SYSCFG->EXTICR[0] |= SYSCFG EXTICR1 EXTIk Pj; Figure 7 11 2. Select a signal change that will trigger EXTI line k. The signal can be a rising edge, a falling edge, or both. This is configured through the EXTI rising edge trigger selection register (EXTI RTSR1 or EXTI RTSR2) and the EXTI falling edge trigger selection register (EXTI FTSR1 or EXTI FTSR2). Setting the bit that corresponds to input line k in the register to 0 disables the trigger and setting it to 1 enables the trigger. For this lab, use a falling edge trigger. EXTI->RTSR1 |= EXTI RTSR1 RTk; EXTI->FTSR1 |= EXTI FTSR1 FTk; 3. Enable the EXTI for input line k. This is done through the EXTI mask register (EXTI IMR1 or EXTI IMR2). Setting the bit that corresponds to input line k in the register to 0 disables the EXTI and setting it to 1 enables the EXTI. EXTI->IMR1 |= EXTI IMR1 IMk; 4. Configure the enable and mask bits that control the NVIC interrupt channel corresponding to EXTI input line k. In addition, set the interrupt priority. NVIC EnableIRQ(EXTIk IRQn); NVIC SetPriority(EXTIk IRQn, 0); 5. Write the interrupt handler for EXTI input line k. The function name of the interrupt handler can be found in the startup assembly file startup stm32l476xx.s. For example, the handler for EXTI0 is called EXTI0 IRQHandler(). The EXTI pending register (EXTI PR1 or EXTI PR2) records the source of the interrupt. Note that in the interrupt handler, you must clear the corresponding pending bit (so that future interrupts can occur). To do this, you can write a 1 to the corresponding bit of the pending register. EXTI->PR1 |= EXTI PR1 PIFk; 12 5 Part C – SysTick Figure 8 In this part of the lab, you will set up the system timer (SysTick) to generate interrupts (see Figure 8), with a period of 1 ms. The CLKSOURCE bit of the SysTick CTRL register indicates the clock source for SysTick. If CLKSOURCE is 0, the external clock is used. The frequency of SysTick is the frequency of the AHB clock divided by 8. If CLKSOURCE is 1, the processor clock is used. For this lab, you are required to configure the AHB clock frequency to be 8 MHz by using MSI. The following steps outline how to change the clock frequency. 1. Select the MSI clock range by configuring the MSIRANGE bits of RCC CR (RCC Clock Con- trol Register). Check “STM32L4 Reference Manual” and stm32l476xx.h to find out what values the MSIRANGE bits should be. MSIRANGE = Note that MSIRANGE can be modified when MSI is OFF (i.e. MSION = 0) or when MSI is ready (i.e. MSIRDY = 1). MSIRANGE must not be modified when MSI is ON and not ready (i.e. MSION = 1 and MSIRDY = 0). The MSIRGSEL bit in RCC CR selects which MSIRANGE bits will be used. If MSIRGSEL = 0, the MSIRANGE bits in RCC CSR are used to select the MSI clock range. This is the default. MSIRANGE can be written only when MSIRGSEL = 1. However, changing the MSIRANGE in RCC CSR does not change the current MSI frequency. The clock will be changed after a standby. If MSIRGSEL = 1, the MSIRANGE bits in RCC CR are used. 13 2. Set MSION (MSI Clock Enable) and wait for MSIRDY (MSI Clock Ready Flag) in RCC CR. If CLKSOURCE = 0, what is the value of the SysTick Reload Value Register that will generate an interrupt every 1 ms? SysTick LOAD = If CLKSOURCE = 1, what is the value of the SysTick Reload Value Register that will generate an iterrupt every 1 ms? SysTick LOAD = The frequency of internal clocks (RC oscillators) may vary from one chip to another due to manufacturing process variations. In addition, the operating temperature has an impact on the accuracy of the RC oscillators. At 25 C, the HSI and MSI oscillators typically have an accuracy of ±1.5 %, however the accuracy decreases in extreme temperatures in either direction (around 40 C or 105 C). In SysTimer.c, you will see a variable defined with the volatile keyword. This keyword should be used in the variable definition if the variable’s value can be changed unexpectedly (e.g. when the value is modified within an interrupt service routine). When the volatile keyword is used, the compiler takes this fact into consideration when generating the executable binary and performing optimizations to the code. Write a simple program that toggles the red LED every second. First, complete the implementa- tion of function delay(). You can then perform an action every second by calling delay(1000). 14 6 Questions 1. What is the address of the SysTick Handler() function? Verify it (i.e. take a screenshot) in the debug environment. 2. Set up a breakpoint within the SysTick Handler() function. In the debug environment, find out the exception number in the program status register when the program runs to the breakpoint. Explain what this number means. 3. As shown in Figure 9, Cortex-M supports up to 256 interrupts. What is the interrupt number of SysTick that is defined in CMSIS? Figure 9 4. Does a higher priority value represent a higher urgency? 5. Suppose a clock of 16 MHz is used to drive the system timer. What is the maximum period between two consecutive SysTick interrupts that we can possibly obtain? 6. What is GPIO output speed and what is the default output speed? 7 References [1] Yifeng Zhu, “Embedded Systems with ARM Cortex-M Microcontrollers in Assembly Lan- guage and C”, ISBN: 0982692633 15

Solution PreviewSolution Preview

This material may consist of step-by-step explanations on how to solve a problem or examples of proper writing, including the use of citations, references, bibliographies, and formatting. This material is made available for the sole purpose of studying and learning - misuse is strictly forbidden.

/*----------------------------------------------------------------------------
* Name:    B.c
* Purpose: LED Flasher
*----------------------------------------------------------------------------
* This file is part of the uVision/ARM development tools.
* This software may only be used under the terms of a valid, current,
* end user licence from KEIL for a compatible version of KEIL software
* development tools. Nothing else gives you the right to use this software.
*
* This software is supplied "AS IS" without warranties of any kind.
*
* Copyright (c) 2016 Keil - An ARM Company. All rights reserved.
*----------------------------------------------------------------------------*/

#include <stdio.h>

#include "stm32l4xx.h"                  // Device header


uint32_t red_led = 0;
uint32_t green_led = 0;

volatile uint32_t msTicks;                            /* counts 1ms timeTicks */



/*----------------------------------------------------------------------------
* SysTick_Handler:
*----------------------------------------------------------------------------*/


void SysTick_Handler(void) {
msTicks++;
}

/*----------------------------------------------------------------------------
* Delay: delays a number of Systicks0
*----------------------------------------------------------------------------*/
void Delay (uint32_t dlyTicks) {
uint32_t curTicks;

curTicks = msTicks;
while ((msTicks - curTicks) < dlyTicks) { __NOP(); }
}

/*----------------------------------------------------------------------------
* SystemCoreClockConfigure: configure SystemCoreClock using HSI
                           
*----------------------------------------------------------------------------*/
void SystemCoreClockConfigure(void) {

RCC->CR |= ((uint32_t)RCC_CR_HSION);                     /* Enable HSI */
while ((RCC->CR & RCC_CR_HSIRDY) == 0);                  /* Wait for HSI Ready */

RCC->CFGR = RCC_CFGR_SW_HSI;                            /* HSI is system clock */
while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_HSI); /* Wait for HSI used as system clock */

FLASH->ACR = (FLASH_ACR_PRFTEN    |                   /* Enable Prefetch Buffer */
                FLASH_ACR_ICEN       |                   /* Instruction cache enable */
                FLASH_ACR_DCEN       |                   /* Data cache enable */
                FLASH_ACR_LATENCY_4WS );                  /* Flash 4 wait state */

RCC->CFGR |= (RCC_CFGR_HPRE_DIV1 |                      /* HCLK = SYSCLK */
                RCC_CFGR_PPRE1_DIV2 |                      /* APB1 = HCLK/2 */
                RCC_CFGR_PPRE2_DIV1 );                   /* APB2 = HCLK/1 */

RCC->CR &= ~RCC_CR_PLLON;                               /* Disable PLL */...
$125.00 for this solution

PayPal, G Pay, ApplePay, Amazon Pay, and all major credit cards accepted.

Find A Tutor

View available Electrical Engineering Tutors

Get College Homework Help.

Are you sure you don't want to upload any files?

Fast tutor response requires as much info as possible.

Decision:
Upload a file
Continue without uploading

SUBMIT YOUR HOMEWORK
We couldn't find that subject.
Please select the best match from the list below.

We'll send you an email right away. If it's not in your inbox, check your spam folder.

  • 1
  • 2
  • 3
Live Chats