Using a FRDM-KL27Z developed LPUART and IIC driver driver code that works great.
However, our production intent target MCU is the KL17Z256.
Result is no working LPUART1 or I2C1 (currently the only modules tested).
Some thoughts on what could be missing?
I feel like maybe a missed register not properly set to default?
// CODE USED (Works on KL27Z after replacing the device header)
#include "MKL17Z4.h" // Device header
void LPTMR_init(void);
void LPTMR_delay(unsigned int length_ms);
int main()
{
// Initialize the LPTMR
LPTMR_init();
// Clock Configuration
MCG_C1 |= MCG_C1_CLKS(1); // Internal reference clock IRC8M
MCG_C2 |= MCG_C2_IRCS_MASK; // Fast internal reference clock selected,8MHz
MCG_SC = 0x0; // FCRDIV = 8M/1
LPTMR_delay(10);
SIM_CLKDIV1 |= SIM_CLKDIV1_OUTDIV1(0) | // Core clock 8M/1
SIM_CLKDIV1_OUTDIV4(0); // Bus clock 8M/1/1
SMC_PMPROT = SMC_PMPROT_AVLP_MASK; // Allow VLPR, VLPW and VLPS
SMC_PMCTRL = SMC_PMCTRL_RUNM(0); // Normal run
// Enable Clock Gating on PORTC for LPUART1 TX
SIM->SCGC5 |= SIM_SCGC5_PORTC_MASK;
// Set the MUX LPUART1 TX
PORTC->PCR[4] = PORT_PCR_MUX(3);
// Set the clock source
SIM->SOPT2 |= SIM_SOPT2_LPUART1SRC(1);
// Enable LPUART Module
SIM->SCGC5 |= SIM_SCGC5_LPUART1_MASK;
// Disable TX and RX while configuring
LPUART1->CTRL &= ~(LPUART_CTRL_TE_MASK | LPUART_CTRL_RE_MASK);
// Baud Register Options
// 9600 with 8 MHz clock
LPUART1->BAUD = LPUART_BAUD_OSR(0x03)
| LPUART_BAUD_SBR(0xD0)
| LPUART_BAUD_BOTHEDGE_MASK;
// Control Register Options
LPUART1->CTRL = 0;
// Stat Register Options
LPUART1->STAT = 0;
// Enable TX and RX
LPUART1->CTRL |= LPUART_CTRL_TE_MASK | LPUART_CTRL_RE_MASK;
while(1)
{
// Wait until space is available in the FIFO
while(!(LPUART1->STAT & LPUART_STAT_TDRE_MASK));
// Send a test character
LPUART1->DATA = 0xA5;
// Delay 100ms
LPTMR_delay(100);
}
return 0;
}
void LPTMR_init(void)
{
// Turn on clock gate for the LPTMR
SIM->SCGC5 |= SIM_SCGC5_LPTMR_MASK;
// Set up LPTMR to use 1kHz LPO with no prescaler as its clock source
LPTMR0->PSR = LPTMR_PSR_PCS(1) | LPTMR_PSR_PBYP_MASK;
}
void LPTMR_delay(unsigned int length_ms)
{
// Clear settings
LPTMR0->CSR = 0;
// Compare value (ms) based on 1 kHz LPO
LPTMR0->CMR = length_ms;
// Start the timer
LPTMR0->CSR |= LPTMR_CSR_TEN_MASK;
// Wait for counter to reach compare value
while (!(LPTMR0->CSR & LPTMR_CSR_TCF_MASK));
// Disable counter and Clear Timer Compare Flag
LPTMR0->CSR &= ~LPTMR_CSR_TEN_MASK;
}
Original Attachment has been moved to: main.c.zip
Issue Resolved.
In the previous posted code, LPUART1 was selected to use the IRC48M clock. Thus, the following is required on the KL17 but was not on the KL27.
// Enable HIRC
MCG_MC = MCG_MC_HIRCEN_MASK;
Default register values appear to be different between KL17 and KL27!
Thanks bobpaddock for the heads up on the I2C repeated starts. I also ran into that issue and saw the workarounds posted. I was able to get the repeated start to write the correct data to SDA by adding a few clock cycles after initiating the repeated start. I still have yet to confirm the work around on the KL17, next on list...
I2C on the KL27 is broken. When a Repeated Start is issues the KL27 resends the slave address. Some peripherals don't care and others fail to work correctly. Freescale/NXP has yet to issue an errata about this. Search the forum here for the details.
The KL27 also has a errata about the PIT timers not always starting up with a work around.
I'm not convinced the work around works reliably. If you get a complex combination of DMA/DMAMUX/PIT/TPM1/LUART running the part locks up every few hours (PIT did not start up). :-(
As to the KL17 vs KL27 check the header file against the datasheet. I've been burned by bad header files in the past.
Has been as bad as using the same name for completely different function. :-(
Myself I've lost any faith that the KL27 family works correctly and switching to a KL26.
Correction to initial discussion