AnsweredAssumed Answered

LPTMR interrupt is not generated by KL03

Question asked by Andy Murray on Apr 17, 2018
Latest reply on Apr 26, 2018 by Andy Murray

Hi,

I am using KL03 and KDS. At first I used PE to configure the LPTMR. When the interrupt was generated by the timer, I read the ADC and sent the information through the LPUART. Everything worked fine.


I am trying to do the same algorithm without PE (for many reasons, including errors found in the generated code for VLPR and power up time), and I have something missing in the LPTMR configuration that doesn't take me to the interrupt to read my ADC. For debugging purposes, currently the ADC acquisition instructions are in the main loop, and I have a PTOR instruction for PORTB10 to be able to know if I got to the LPTMR0_IRQHandler (visualization with LED and oscilloscope).

 

The code that follows (main.c) shows the LPTMR configuration, including CSR, PSR, the priority of the interrupt (NVIC) and the interrupt enable (NVIC). After initilization, I enable global interrupts, set the value for the timer, and enable the timer. I am constantly looking at the value in CNR (which increments as expected), but doesn't take me to the LPTMR0_IRQHandler.

 

Any ideas of what am I missing in the configuration? I really appreciate any help you can provide. It most be something very silly but I have been stucked in this for days... 

Best,
Andy

 

//  Includes

#include "MKL03Z4.h"                         // KL03 M0+ register definitions

 

//Power modes

unsigned int power_mode_status = 0;

unsigned int dummyread;

//ADC, LPUART and LPTMR

unsigned int result_mask = 0;

uint32_t result_ADC;

uint32_t status_LPUART = 0;

uint32_t status_LPTMR = 0;

 

void MCU_Init(void);                               // initializes MCU

 

 

void MCU_Init(void)

{

                __asm__("CPSID i");                           // Disable interrupts

 

                // System Registers

                SIM->COPC=0x00;                // Disable COP watchdog; RefMan2017 Pag. 173 and 196

                SIM->SCGC5|=(SIM_SCGC5_LPUART0_MASK | SIM_SCGC5_PORTB_MASK | SIM_SCGC5_LPTMR_MASK);  // Enable clock gate for LPUART, PORTB, LPTMR registers. RefMan2017 Pag. 188

                SIM_SCGC6 |= SIM_SCGC6_ADC0_MASK; // Enable ADC0 clock gate control. RefMan2017 Pag. 189

                SIM_SOPT2 |= SIM_SOPT2_LPUART0SRC_MASK; // Set MCGIRCLK clock as LPUART0 transmit and receive clock. RefMan2017 Pag. 179

 

                // Errata 8068 fix: https://community.nxp.com/thread/350259 and https://community.nxp.com/message/902536

                SIM->SCGC6 |= SIM_SCGC6_RTC_MASK;           // enable clock to RTC

                RTC->SR = 0b00001; // Time counter disabled - RTC status register

                RTC->TSR = 0x00;     // dummy write to RTC TSR per errata 8068

                SIM->SCGC6 &= ~SIM_SCGC6_RTC_MASK;          // disable clock to RTC

 

                // System Tick Init

                SysTick->CTRL=0;        // Disable the SysTick Timer

                SysTick->LOAD=48000;  // Core Clock/1=48MHz, Period=1ms/(1/48000000Hz)=48000

                SysTick->VAL=0;  // Clear the current counter value to 0

                SysTick->CTRL=(SysTick_CTRL_ENABLE_Msk

                                                                |SysTick_CTRL_CLKSOURCE_Msk);   // Enable SYS TICK timer and set clock source to processor clock (core clock)

 

                // System clock initialization MCG_Lite

                MCG_C1 = 0b01000010U; // LIRC clock is main clock source, LIRC enabled. RefMan2017 Pag. 317

                MCG_C2 = 0b00000000U; // LIRC is in 2 MHz mode. RefMan Pag. 318

 

                //System integration module. RefMan2017 Pag 191

                SIM_CLKDIV1 &=~ (SIM_CLKDIV1_OUTDIV1(1));      // Set Core Clock/1= 2 MHz

                SIM_CLKDIV1 |= (SIM_CLKDIV1_OUTDIV4(2));       // Set Bus Clock/3= 0.666 MHz

 

                // System mode controller SMC - RefMan2017 Pag. 199

                SMC_PMPROT=SMC_PMPROT_AVLP_MASK; // Write-once register: Allow Low Leakage Power Modes (VLPR,VLPW,VLPS,LLS); Pag. 202 RefMan2017

                // Goes to VLPR before VLPW - required

                power_mode_status  = SMC_PMSTAT;                //Pag. 206 RefMan2017

                SMC_PMCTRL = SMC_PMCTRL_RUNM(2);       //VLPR mode register Pag. 204 RefMan, Pag. 211 RefMan

                dummyread = SMC_PMCTRL;

                (void)dummyread;

                SCB->SCR &= ~ SCB_SCR_SLEEPDEEP_Msk; //Sleep Deep mask cleared. From sarah's code: https://community.nxp.com/message/902536

                power_mode_status  = SMC_PMSTAT; //Pag. 206 RefMan2017

 

                // GPIO Initialization

                //Pin Mux configuration: RefMan2017 Pag. 155

                PORTB->PCR[0] = PORT_PCR_MUX(1);            // Set pin MUX for GPIO on PORTB pin 0

                PORTB->PCR[1] = PORT_PCR_MUX(2);            // Set pin MUX for Alternative 2 

                PORTB->PCR[2] = PORT_PCR_MUX(2);            // Set pin MUX for Alternative 2 

                PORTB->PCR[5] = PORT_PCR_MUX(0);            // Set pin MUX for default on PORTB pin 5

                PORTB->PCR[6] = PORT_PCR_MUX(1);            // Set pin MUX for GPIO on PORTB pin 6

                PORTB->PCR[10] = PORT_PCR_MUX(1);           // Set pin MUX for GPIO on PORTB pin 10

                PORTB->PCR[11] = PORT_PCR_MUX(1);           // Set pin MUX for GPIO on PORTB pin 11

                PORTB->PCR[13] = PORT_PCR_MUX(1);           // Set pin MUX for GPIO on PORTB pin 13

                PTB->PDDR = 0b00110001000000;                                                     // Set pins 6, 10 and 11 as outputs. RefMan2017 Pag. 167

 

                // ADC configuration

                ADC0_CFG1 = 0b10001000; //ADC config register 1. RefMan2017 Pag. 387

                                 //Bit7: low power = 1

                                 //Bit6-5: ADCK input clock / 1 = 00

                                 //Bit4: short sample time = 0

                                 //Bit3-2: single end-10 bit = 10

                                 //Bit1-0: bus clock = 00

                ADC0_SC1A = 0b00000001;  //ADC status and control. refMan2017 Pag. 383

                                 //Bit 7 COCO 0 Read-only flag which is set when a conversion completes.

                                 //Bit 6 AIEN 0 Conversion complete interrupt disabled.

                                 //Bit 4:0 ADCH 00001 Input channel ADC0_SE1 == PTB5 selected as ADC input channel.

 

                //LPUART Configuration

                LPUART0_BAUD |= LPUART_BAUD_M10_MASK;                             //Set 10-bit data characters for TX and RX

                LPUART0_CTRL |= (LPUART_CTRL_TXDIR_MASK | LPUART_CTRL_TXINV_MASK | LPUART_CTRL_TE_MASK |LPUART_CTRL_LOOPS_MASK |LPUART_CTRL_RSRC_MASK);

                                               //RefMan 2017 pag. 586

                                               //Bit 29: TXpin is an output in single-wire mode

                                               //Bit 28: Transmit data inverted

                                               //Bit 19: Tx enabled

                                               //Bit 7: Loops >> single-wire mode where TX is internally connected to RX input

                                               //Bit 5: RSRC >> Single-wire mode TX pin connected to TX output and RX input

 

                //LPTMR0 Configuration

                LPTMR0_CSR = 0b1000000;                 //RefMan2017 Pag. 488

                               // TIE (6): Set Timer Interrupt Enable, RefMan2017 Pag. 488.

                               // TFC (2): CNR resets when Timer Compare Flag (TCF) is set (0)

                               // TMS (1): Time counter mode (0)

                               // TEN (0): timer disabled

                LPTMR0_PSR = 0b0001100;                 //RefMan2017 Pag. 490

                               // PRESCALE (6:3): CLK/4 (0001)

                               // PBYP (2): Prescaler filter is bypassed (set). The selected prescaler clk directly clocks the CNR.

                               // PCS (1:0): Prescaler clock select MCGIRCLK (00)

                NVIC_SetPriority(28, 1U);                     //Sets priority to 1 (0 is highest)

                NVIC_EnableIRQ(28);                           // Enables an interrupt for a given IRQ number

}

 

//              INTERRUPT HANDLERS

void LPTMR0_IRQHandler(void) { // From https://community.nxp.com/message/929302

                LPTMR0_CSR |= LPTMR_CSR_TCF_MASK;                      // Clear interrupt flag, CNR resets

                PTB->PTOR|=(1<<10);                                                                                         // Toggle pin 10

                // Should read ADC here

}

 

 

// MAIN

int main(void)

{

                MCU_Init();

                power_mode_status  = SMC_PMSTAT;                //Pag. 206 RefMan2017

                __asm__("CPSIE i");                                             // Enable interrupts

 

                LPTMR0_CMR = 1999;                                          // Set value for Timer - Compare value. RefMan2017 Pag. 491. CNR increments. 1999 == 1 ms

                LPTMR0_CSR |= LPTMR_CSR_TEN_MASK;      //Timer enable, RefMan2017 Pag. 489

 

                while (1){

                               PTB->PSOR|=(1<<11);

                               LPTMR0->CNR = 0x11;         //Write value to be able to read: https://community.nxp.com/message/989760

                               status_LPTMR = LPTMR0_CNR;          //Value of counter of LPTMR

 

                               ADC0_SC1A = 0b00000001;                 // Initiate conversion again with interrupt disabled

                               while (result_mask == 0){

                                               //Result is NOT ready to be read

                                               result_mask = ADC0_SC1A && ADC_SC1_COCO_MASK;

                               }

                               //Result is ready to be read

                               result_mask = 0;                                     //Updates Result's mask

                               result_ADC = ADC0_RA;                       // Saves EMG in result_ADC

                               //status_LPUART = LPUART0_STAT && LPUART_STAT_TDRE_MASK;//debug

                               //status_LPUART = LPUART0_STAT && LPUART_STAT_TC_MASK;//debug

                               //LPUART0_DATA = 0b10101010;                                        // Load data to transmit

                }

}

Outcomes