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
}
}