I recently broke the serial I/O routines in my KL27Z :smileysilly:: I'm now getting hard faults when I first try to access the LPUART0->STAT register in the LPUART_GetStatusFlags(base) method, specifically:
temp = base->STAT;
... where base = LPUART0 = 0x40054000.
Any hints on what I might have failed to initialize?
Prior to calling LPUART_GetStatusFlags(base), I've done the following:
// from BOARD_InitPins()CLOCK_EnableClock(kCLOCK_PortA); /* Port A Clock Gate Control: Clock enabled */
PORT_SetPinMux(PORTA, PIN1_IDX, kPORT_MuxAlt2); /* PORTA1 (pin 23) is configured as LPUART0_RX */
PORT_SetPinMux(PORTA, PIN2_IDX, kPORT_MuxAlt2); /* PORTA2 (pin 24) is configured as LPUART0_TX */
SIM->SOPT5 = ((SIM->SOPT5 &
(~(SIM_SOPT5_LPUART0TXSRC_MASK | SIM_SOPT5_LPUART0RXSRC_MASK))) /* Mask bits to zero which are setting */
| SIM_SOPT5_LPUART0TXSRC(SOPT5_LPUART0TXSRC_LPUART_TX) /* LPUART0 Transmit Data Source Select: LPUART0_TX pin */
| SIM_SOPT5_LPUART0RXSRC(SOPT5_LPUART0RXSRC_LPUART_RX) /* LPUART0 Receive Data Source Select: LPUART_RX pin */
);
// Serial initializationCLOCK_SetLpuart0Clock(0x03); // MCGIRCLK (correct?)
lpuart_config_t config;
LPUART_GetDefaultConfig(&config); config.baudRate_Bps = baud_rate; config.enableTx = true; config.enableRx = true;
LPUART_Init(LPUART0, &config, CLOCK_GetFreq(kCLOCK_McgInternalRefClk)); // ### It gets a hard fault inside the call to LPUART_GetStatusFlags ###while (!(kLPUART_TxDataRegEmptyFlag & LPUART_GetStatusFlags(LPUART0))) {
// busy wait for previous tx data...
}
// ... doesn't get here...
LPUART_WriteByte(LPUART0, ch);
Solved my problem. It was in the call to CLOCK_GetFreq(...) -- I was passing kCLOCK_McgIrc48MClk (despite what I showed in my code above) rather than kCLOCK_McgInternalRefClk for VLPR mode and kCLOCK_McgPeriphClk for RUN mode.
Hi
Check that the LPUART is enabled/clocked in SIM_SCGC5 before accessing any of its registers.
#define SIM_SCGC5_LPUART0 0x00100000
Regards
Mark
Mark: That's a good start -- thanks! I'm looking over the LPUART interrupt example:
<sdk>/boards/frdmkl27z/driver_examples/lpuart/interrupt/
... and trying to figure out where SIM_SCGC5 is getting set there. What's the name of the method there that's setting SIM_SCGC5? Thanks in advance (in the meantime I'll keep digging...).
Robert
I don't know what method is used in the example.
I use (in the uTasker project)
POWER_UP(5, SIM_SCGC5_LPUART0); // power up LPUART 0
which equates to
SIM_SCGC5 |= SIM_SCGC5_LPUART0;
and ultimately to
*(volatile unsigned long*)(0x40048038) |= 0x00100000;
Regards
Mark
Fair enough - thanks. I believe part of my problem is that I'm running in VLPR mode (rather than RUN mode) and I need to adjust clock sources accordingly. I'll keep digging.
Hi Robert,
The KSDK software is using below function to enable the LPUART0 module clock at SIM_SCGC5 register:
/*!
* @brief Enable the clock for specific IP.
*
* @param name Which clock to enable, see \ref clock_ip_name_t.
*/
static inline void CLOCK_EnableClock(clock_ip_name_t name)
{
uint32_t regAddr = SIM_BASE + CLK_GATE_ABSTRACT_REG_OFFSET((uint32_t)name);
(*(volatile uint32_t *)regAddr) |= (1U << CLK_GATE_ABSTRACT_BITS_SHIFT((uint32_t)name));
}
Please add below code to your application before any LPUART0 register access:
CLOCK_EnableClock(kCLOCK_Lpuart0);
Wish it helps.
Have a great day,
Ma Hui
-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------