I am trying to implement a Systick exception handler that can flash an LED on the FRDM KL25Z board. The code compiles but when I go to debug it I get the following error: "Error in services launch sequence"
The code is intended to flash an LED on the FRDM board around 1 Hz. I've been able to poll the SysTick without using exceptions/interrupts, but for whatever reason I am missing something while setting this up that blocks execution. I'm trying to write code that is as CMSIS-compliant as possible, so no KDS calls.
If anyone has a hint about what I should be doing differently with setting up the SysTick exception, I'm all ears. Code below...
#include <stdio.h>
#include "board.h"
#include "peripherals.h"
#include "pin_mux.h"
#include "clock_config.h"
#include "MKL25Z4.h"
/* TODO: insert other include files here. */
/* TODO: insert other definitions and declarations here. */
/* The system tick interrupt handler vector (and name) is defined in startup_mkl25z4.c
*
* */
void SysTick_Handler(void)
{
static int n = 0;
/* every 500 interrupts / exceptions toggle the LED */
if (n <= 500)
{
/* increment the counter. */
n= n+1;
}
else
{
/* "Port Toggle" on Port B: Toggle green LED on PTB19 */
PTB->PTOR = 0x080000;
/* reset the counter */
n=0;
}
}
/*
* @brief Application entry point.
*/
int main (void) {
/* Step 1: Turn on Port B via System Integration Module SIM's SCGC5 register.
* Keep existing state of SCGC5 & only set bit 10 to 1. */
SIM->SCGC5 |= SIM_SCGC5_PORTB_MASK; // The "mask" is 0x400
/* Step 2: Make Port B, Pin 19 a "General Purpose Input or Output" (GPIO)
* Look up section 10.3.1 in the manual. Alt1 mode is GPIO for Port B 19.
* Look up section 11.5.1 in the manual. The MUX bits are bits 10,9 and 8 of the PCR.
* key terms for searching: "alt0" and "pin control register" in the PDF (https://bit.ly/2J2751t)
*/
PORTB->PCR[19] = 0x100; // Mux @ Alt1 is GPIO: Bits 10,9,8 = 0b001
/* Step 3: Make Port B, pin 19 an output (instead of an input) */
PTB->PDDR |= 0x080000; /* Bit 19 is a binary "1" (output). A "0" would be input. */
// Interrupt / Exception with SysTick
// https://electronics.stackexchange.com/questions/331650/whats-the-difference-between-setting-systick-...
// http://homepage.cem.itesm.mx/carbajal/Microcontrollers/SLIDES/Interrupts.pdf
// https://community.nxp.com/thread/311713
// https://mcuoneclipse.com/2016/08/14/arm-cortex-m-interrupts-and-freertos-part-1/#more-19365
__disable_irq(); /* disable all IRQs */
/* Delay = (N+1)/sysclk
* 0.001 [sec] = (N+1) / (48000000/2) ---> N = 0.001[sec]*2400000[MHz] - 1
* So N is 24000-1.
*/
SysTick->LOAD = 24000-1;
NVIC_SetPriority(SysTick_IRQn, (1UL<<__NVIC_PRIO_BITS)-1UL); /* set Priority for Systick Interrupt to lowest interrupt */
SysTick->VAL = 24000-1;
/* Enable the timer and choose processor clock as the clock source via Bits 0 and 2
* Also, enable Systick to generate Exceptions / Interrupts via Bit 1*/
SysTick->CTRL = 0b0111;
/* = 0b0111
* ^^^^
* ||||_________ Bit 0: Enable ( 0 = disable; 1 = enable)
* |||__________ Bit 1: TickInt (interrupt/exception enabling)
* ||___________ Bit 2: Clock Source (0 = ext; 1 = proc. clock)
* |____________ Bit 3: Reserved
*/
/* Enable IRQs within NVIC */
NVIC_EnableIRQ(SysTick_IRQn); /* Enable NVIC interrupt */
/* Enable IRQs globally */
__enable_irq(); /* global enable IRQs */
/* Toggle LED every 0.5 second to give 1Hz */
while (1) {
/* do nothing */
}
}