LPUART, I2C Issues when porting KL27 to KL17

cancel
Showing results for 
Search instead for 
Did you mean: 

LPUART, I2C Issues when porting KL27 to KL17

1,211 Views
rbowen
Contributor II

Using a FRDM-KL27Z developed LPUART and IIC driver driver code that works great.

  • Using KEIL, MDK-Lite Version 5.18 with CMSIS version 4.3.0
  • Using SWD to program/debug.
  • Programming using the PE Micro Multilink Universal FX.

 

However, our production intent target MCU is the KL17Z256.

  1. Replaced the KL27Z64VLH4 on the FRDM-KL27Z with the KL17Z256LH4.
  2. Created new uVision project specifying the KL17Z256 as the target.
  3. Copied code changing only the headers.

 

Result is no working LPUART1 or I2C1 (currently the only modules tested).

  • Stripped the code down to initializing the LPTMR and LPUART1.
  • Testing TX in a loop with scope probe.
  • LPTMR works fine.
  • TX is always LOW (no data transferred).
  • LPUART_STAT_TDRE is set, but no data is actually transferred.
  • This exact code (minus the device header and associated CMSIS ) works great.
  • Tested on (3) different KL17Z256LH4 same result.
  • (1) of the KL17Z256LH4 was on our own board never touching the FRDM-27Z.
  • Tried programming using PE Micro and CMSIS-DAP, same result.
  • GPIO toggling on the TX pins works fine.
  • Similar issue with I2C1 as well on KL17 (no data transferred)
    SDA always HIGH, SCL does pull LOW but no CLOCK.
  • Tried different internal clock option (48MHz and 8MHz), currently do not have an external crystal.

 

Some thoughts on what could be missing?

I feel like maybe a missed register not properly set to default?

  • Do not want to use Processor expert.
  • Prefer bare metal CMSIS code base.

 

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

Tags (2)
0 Kudos
3 Replies

389 Views
rbowen
Contributor II

Issue Resolved.

  • Preformed register to register comparison in the debugger for KL17 to KL27.

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

0 Kudos

389 Views
bobpaddock
Senior Contributor III

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.

0 Kudos

389 Views
rbowen
Contributor II

Correction to initial discussion

  • LPUART_STAT_TDRE is set initially, after writing to LPUART1 DATA, LPUART_STAT_TDRE is never set again.
0 Kudos