mbed SDK library sources

Fork of mbed-src by mbed official

Development branch of the mbed library sources. This library is kept in synch with the latest changes from the mbed SDK and it is not guaranteed to work.

If you are looking for a stable and tested release, please import one of the official mbed library releases:

Import librarymbed

The official Mbed 2 C/C++ SDK provides the software platform and libraries to build your applications.

Files at this revision

API Documentation at this revision

Comitter:
mbed_official
Date:
Mon Jan 13 10:45:05 2014 +0000
Parent:
71:ca88dd32f209
Child:
73:299c67215126
Commit message:
Synchronized with git revision f1904ba15c06215a7530efd2d5a16c25af9d29ff

Full URL: https://github.com/mbedmicro/mbed/commit/f1904ba15c06215a7530efd2d5a16c25af9d29ff/

KL46Z: Added Sleep, LED3 and LED4 definitions, switches

Changed in this revision

targets/hal/TARGET_Freescale/TARGET_KL05Z/spi_api.c Show annotated file Show diff for this revision Revisions of this file
targets/hal/TARGET_Freescale/TARGET_KL25Z/analogin_api.c Show annotated file Show diff for this revision Revisions of this file
targets/hal/TARGET_Freescale/TARGET_KL25Z/clk_freqs.h Show annotated file Show diff for this revision Revisions of this file
targets/hal/TARGET_Freescale/TARGET_KL25Z/i2c_api.c Show annotated file Show diff for this revision Revisions of this file
targets/hal/TARGET_Freescale/TARGET_KL25Z/pwmout_api.c Show annotated file Show diff for this revision Revisions of this file
targets/hal/TARGET_Freescale/TARGET_KL25Z/serial_api.c Show annotated file Show diff for this revision Revisions of this file
targets/hal/TARGET_Freescale/TARGET_KL25Z/spi_api.c Show annotated file Show diff for this revision Revisions of this file
targets/hal/TARGET_Freescale/TARGET_KL25Z/us_ticker.c Show annotated file Show diff for this revision Revisions of this file
targets/hal/TARGET_Freescale/TARGET_KL46Z/PinNames.h Show annotated file Show diff for this revision Revisions of this file
targets/hal/TARGET_Freescale/TARGET_KL46Z/device.h Show annotated file Show diff for this revision Revisions of this file
targets/hal/TARGET_Freescale/TARGET_KL46Z/sleep.c Show annotated file Show diff for this revision Revisions of this file
targets/hal/TARGET_Freescale/TARGET_KL46Z/spi_api.c Show annotated file Show diff for this revision Revisions of this file
--- a/targets/hal/TARGET_Freescale/TARGET_KL05Z/spi_api.c	Thu Jan 09 09:00:05 2014 +0000
+++ b/targets/hal/TARGET_Freescale/TARGET_KL05Z/spi_api.c	Mon Jan 13 10:45:05 2014 +0000
@@ -115,7 +115,7 @@
     uint8_t  ref_prescaler = 0;
 
     // bus clk
-    uint32_t PCLK = 23986176u;
+    uint32_t PCLK = SystemCoreClock / (((SIM->CLKDIV1 & SIM_CLKDIV1_OUTDIV4_MASK) >> SIM_CLKDIV1_OUTDIV4_SHIFT) + 1);
     uint8_t prescaler = 1;
     uint8_t divisor = 2;
 
--- a/targets/hal/TARGET_Freescale/TARGET_KL25Z/analogin_api.c	Thu Jan 09 09:00:05 2014 +0000
+++ b/targets/hal/TARGET_Freescale/TARGET_KL25Z/analogin_api.c	Mon Jan 13 10:45:05 2014 +0000
@@ -18,6 +18,9 @@
 #include "cmsis.h"
 #include "pinmap.h"
 #include "error.h"
+#include "clk_freqs.h"
+
+#define MAX_FADC        6000000
 
 static const PinMap PinMap_ADC[] = {
     {PTE20, ADC0_SE0,  0},
@@ -54,14 +57,24 @@
     if (obj->adc & (1 << CHANNELS_A_SHIFT)) {
         cfg2_muxsel = 0;
     }
+    
+    // bus clk
+    uint32_t PCLK = bus_frequency();
+    uint32_t clkdiv;
+    for (clkdiv = 0; clkdiv < 4; clkdiv++) {
+        if ((PCLK >> clkdiv) <= MAX_FADC)
+            break;
+    }
+    if (clkdiv == 4)                    //Set max div
+        clkdiv = 0x7;
 
     ADC0->SC1[1] = ADC_SC1_ADCH(obj->adc & ~(1 << CHANNELS_A_SHIFT));
 
-    ADC0->CFG1 = ADC_CFG1_ADLPC_MASK    // Low-Power Configuration
-               | ADC_CFG1_ADIV(3)       // Clock Divide Select: (Input Clock)/8
-               | ADC_CFG1_ADLSMP_MASK   // Long Sample Time
-               | ADC_CFG1_MODE(3)       // (16)bits Resolution
-               | ADC_CFG1_ADICLK(1);    // Input Clock: (Bus Clock)/2
+    ADC0->CFG1 = ADC_CFG1_ADLPC_MASK            // Low-Power Configuration
+               | ADC_CFG1_ADIV(clkdiv & 0x3)    // Clock Divide Select: (Input Clock)/8
+               | ADC_CFG1_ADLSMP_MASK           // Long Sample Time
+               | ADC_CFG1_MODE(3)               // (16)bits Resolution
+               | ADC_CFG1_ADICLK(clkdiv >> 2);  // Input Clock: (Bus Clock)/2
 
     ADC0->CFG2 = cfg2_muxsel            // ADxxb or ADxxa channels
                | ADC_CFG2_ADACKEN_MASK  // Asynchronous Clock Output Enable
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/targets/hal/TARGET_Freescale/TARGET_KL25Z/clk_freqs.h	Mon Jan 13 10:45:05 2014 +0000
@@ -0,0 +1,91 @@
+/* mbed Microcontroller Library
+ * Copyright (c) 2006-2013 ARM Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef MBED_CLK_FREQS_H
+#define MBED_CLK_FREQS_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+//Get the peripheral bus clock frequency
+static inline uint32_t bus_frequency(void) {
+    return SystemCoreClock / (((SIM->CLKDIV1 & SIM_CLKDIV1_OUTDIV4_MASK) >> SIM_CLKDIV1_OUTDIV4_SHIFT) + 1);
+}
+
+//Get external oscillator (crystal) frequency
+static uint32_t extosc_frequency(void) {
+    uint32_t MCGClock = SystemCoreClock * (1u + ((SIM->CLKDIV1 & SIM_CLKDIV1_OUTDIV1_MASK) >> SIM_CLKDIV1_OUTDIV1_SHIFT));
+
+    if ((MCG->C1 & MCG_C1_CLKS_MASK) == MCG_C1_CLKS(2))     //MCG clock = external reference clock
+        return MCGClock;
+    
+    if ((MCG->C1 & MCG_C1_CLKS_MASK) == MCG_C1_CLKS(0)) {   //PLL/FLL is selected
+        uint32_t divider, multiplier;
+        if ((MCG->C6 & MCG_C6_PLLS_MASK) == 0x0u) {         //FLL is selected
+            if ((MCG->S & MCG_S_IREFST_MASK) == 0x0u) {     //FLL uses external reference
+                divider = (uint8_t)(1u << ((MCG->C1 & MCG_C1_FRDIV_MASK) >> MCG_C1_FRDIV_SHIFT));
+                if ((MCG->C2 & MCG_C2_RANGE0_MASK) != 0x0u)
+                    divider <<= 5u;
+                /* Select correct multiplier to calculate the MCG output clock  */
+                switch (MCG->C4 & (MCG_C4_DMX32_MASK | MCG_C4_DRST_DRS_MASK)) {
+                    case 0x0u:
+                      multiplier = 640u;
+                      break;
+                    case 0x20u:
+                      multiplier = 1280u;
+                      break;
+                    case 0x40u:
+                      multiplier = 1920u;
+                      break;
+                    case 0x60u:
+                      multiplier = 2560u;
+                      break;
+                    case 0x80u:
+                      multiplier = 732u;
+                      break;
+                    case 0xA0u:
+                      multiplier = 1464u;
+                      break;
+                    case 0xC0u:
+                      multiplier = 2197u;
+                      break;
+                    case 0xE0u:
+                    default:
+                      multiplier = 2929u;
+                      break;
+                }
+                
+                return MCGClock * divider / multiplier;
+            }
+        } else {             //PLL is selected
+            divider = (1u + (MCG->C5 & MCG_C5_PRDIV0_MASK));
+            multiplier = ((MCG->C6 & MCG_C6_VDIV0_MASK) + 24u);
+            return MCGClock * divider / multiplier;            
+        }
+    }
+    
+    //In all other cases either there is no crystal or we cannot determine it
+    //For example when the FLL is running on the internal reference, and there is also an
+    //external crystal. However these are unlikely situations
+    return 0;
+}
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
--- a/targets/hal/TARGET_Freescale/TARGET_KL25Z/i2c_api.c	Thu Jan 09 09:00:05 2014 +0000
+++ b/targets/hal/TARGET_Freescale/TARGET_KL25Z/i2c_api.c	Mon Jan 13 10:45:05 2014 +0000
@@ -18,6 +18,7 @@
 #include "cmsis.h"
 #include "pinmap.h"
 #include "error.h"
+#include "clk_freqs.h"
 
 static const PinMap PinMap_I2C_SDA[] = {
     {PTE25, I2C_0, 5},
@@ -206,7 +207,7 @@
     uint32_t ref = 0;
     uint8_t i, j;
     // bus clk
-    uint32_t PCLK = 24000000u;
+    uint32_t PCLK = bus_frequency();
     uint32_t pulse = PCLK / (hz * 2);
 
     // we look for the values that minimize the error
--- a/targets/hal/TARGET_Freescale/TARGET_KL25Z/pwmout_api.c	Thu Jan 09 09:00:05 2014 +0000
+++ b/targets/hal/TARGET_Freescale/TARGET_KL25Z/pwmout_api.c	Mon Jan 13 10:45:05 2014 +0000
@@ -64,14 +64,25 @@
     {NC , NC    , 0}
 };
 
-#define PWM_CLOCK_MHZ       (0.75) // (48)MHz / 64 = (0.75)MHz
+static float pwm_clock;
 
 void pwmout_init(pwmout_t* obj, PinName pin) {
     // determine the channel
     PWMName pwm = (PWMName)pinmap_peripheral(pin, PinMap_PWM);
     if (pwm == (PWMName)NC)
         error("PwmOut pin mapping failed");
-
+    
+    uint32_t clkdiv = 0;
+    float clkval = SystemCoreClock / 1000000.0f;
+    
+    while (clkval > 1) {
+        clkdiv++;
+        clkval /= 2.0;  
+        if (clkdiv == 7)
+            break;
+    }
+    
+    pwm_clock = clkval;
     unsigned int port = (unsigned int)pin >> PORT_SHIFT;
     unsigned int tpm_n = (pwm >> TPM_SHIFT);
     unsigned int ch_n = (pwm & 0xFF);
@@ -81,7 +92,7 @@
     SIM->SOPT2 |= SIM_SOPT2_TPMSRC(1); // Clock source: MCGFLLCLK or MCGPLLCLK
 
     TPM_Type *tpm = (TPM_Type *)(TPM0_BASE + 0x1000 * tpm_n);
-    tpm->SC = TPM_SC_CMOD(1) | TPM_SC_PS(6); // (48)MHz / 64 = (0.75)MHz
+    tpm->SC = TPM_SC_CMOD(1) | TPM_SC_PS(clkdiv); // (clock)MHz / clkdiv ~= (0.75)MHz
     tpm->CONTROLS[ch_n].CnSC = (TPM_CnSC_MSB_MASK | TPM_CnSC_ELSB_MASK); /* No Interrupts; High True pulses on Edge Aligned PWM */
 
     obj->CnV = &tpm->CONTROLS[ch_n].CnV;
@@ -125,7 +136,7 @@
 // Set the PWM period, keeping the duty cycle the same.
 void pwmout_period_us(pwmout_t* obj, int us) {
     float dc = pwmout_read(obj);
-    *obj->MOD = PWM_CLOCK_MHZ * us;
+    *obj->MOD = (uint32_t)(pwm_clock * (float)us);
     pwmout_write(obj, dc);
 }
 
@@ -138,5 +149,5 @@
 }
 
 void pwmout_pulsewidth_us(pwmout_t* obj, int us) {
-    *obj->CnV = PWM_CLOCK_MHZ * us;
+    *obj->CnV = (uint32_t)(pwm_clock * (float)us);
 }
--- a/targets/hal/TARGET_Freescale/TARGET_KL25Z/serial_api.c	Thu Jan 09 09:00:05 2014 +0000
+++ b/targets/hal/TARGET_Freescale/TARGET_KL25Z/serial_api.c	Mon Jan 13 10:45:05 2014 +0000
@@ -23,6 +23,7 @@
 #include "cmsis.h"
 #include "pinmap.h"
 #include "error.h"
+#include "clk_freqs.h"
 
 /******************************************************************************
  * INITIALIZATION
@@ -70,7 +71,10 @@
     obj->uart = (UARTLP_Type *)uart;
     // enable clk
     switch (uart) {
-        case UART_0: SIM->SOPT2 |= SIM_SOPT2_PLLFLLSEL_MASK | (1<<SIM_SOPT2_UART0SRC_SHIFT);
+        case UART_0: if ((MCG->C1 & MCG_C1_CLKS_MASK) == MCG_C1_CLKS(0))   //PLL/FLL is selected
+                        SIM->SOPT2 |= SIM_SOPT2_PLLFLLSEL_MASK | (1<<SIM_SOPT2_UART0SRC_SHIFT);
+                     else
+                        SIM->SOPT2 |= (2<<SIM_SOPT2_UART0SRC_SHIFT);
                      SIM->SCGC5 |= SIM_SCGC5_PORTA_MASK; SIM->SCGC4 |= SIM_SCGC4_UART0_MASK; break;
         case UART_1: SIM->SCGC5 |= SIM_SCGC5_PORTC_MASK; SIM->SCGC4 |= SIM_SCGC4_UART1_MASK; break;
         case UART_2: SIM->SCGC5 |= SIM_SCGC5_PORTD_MASK; SIM->SCGC4 |= SIM_SCGC4_UART2_MASK; break;
@@ -111,16 +115,6 @@
 // serial_baud
 //
 // set the baud rate, taking in to account the current SystemFrequency
-//
-// The LPC2300 and LPC1700 have a divider and a fractional divider to control the
-// baud rate. The formula is:
-//
-// Baudrate = (1 / PCLK) * 16 * DL * (1 + DivAddVal / MulVal)
-//   where:
-//     1 < MulVal <= 15
-//     0 <= DivAddVal < 14
-//     DivAddVal < MulVal
-//
 void serial_baud(serial_t *obj, int baudrate) {
     
     // save C2 state
@@ -129,8 +123,7 @@
     // Disable UART before changing registers
     obj->uart->C2 &= ~(UART_C2_RE_MASK | UART_C2_TE_MASK);
     
-    // [TODO] not hardcode this value
-    uint32_t PCLK = (obj->uart == UART0) ? 48000000u : 24000000u;
+    uint32_t PCLK = (obj->uart == UART0) ? SystemCoreClock : bus_frequency();
 
     // First we check to see if the basic divide with no DivAddVal/MulVal
     // ratio gives us an integer result. If it does, we set DivAddVal = 0,
--- a/targets/hal/TARGET_Freescale/TARGET_KL25Z/spi_api.c	Thu Jan 09 09:00:05 2014 +0000
+++ b/targets/hal/TARGET_Freescale/TARGET_KL25Z/spi_api.c	Mon Jan 13 10:45:05 2014 +0000
@@ -20,6 +20,7 @@
 #include "cmsis.h"
 #include "pinmap.h"
 #include "error.h"
+#include "clk_freqs.h"
 
 static const PinMap PinMap_SPI_SCLK[] = {
     {PTA15, SPI_0, 2},
@@ -145,7 +146,7 @@
     uint8_t  ref_prescaler = 0;
 
     // bus clk
-    uint32_t PCLK = 48000000u;
+    uint32_t PCLK = bus_frequency();
     uint8_t prescaler = 1;
     uint8_t divisor = 2;
 
--- a/targets/hal/TARGET_Freescale/TARGET_KL25Z/us_ticker.c	Thu Jan 09 09:00:05 2014 +0000
+++ b/targets/hal/TARGET_Freescale/TARGET_KL25Z/us_ticker.c	Mon Jan 13 10:45:05 2014 +0000
@@ -16,6 +16,7 @@
 #include <stddef.h>
 #include "us_ticker_api.h"
 #include "PeripheralNames.h"
+#include "clk_freqs.h"
 
 static void pit_init(void);
 static void lptmr_init(void);
@@ -43,7 +44,7 @@
     PIT->CHANNEL[1].TCTRL |= PIT_TCTRL_TEN_MASK;   // Start timer 1
     
     // Use channel 0 as a prescaler for channel 1
-    PIT->CHANNEL[0].LDVAL = 23;
+    PIT->CHANNEL[0].LDVAL = bus_frequency() / 1000000 - 1;
     PIT->CHANNEL[0].TCTRL = PIT_TCTRL_TEN_MASK;    // Start timer 0, disable interrupts
 }
 
@@ -76,8 +77,36 @@
     NVIC_EnableIRQ(LPTimer_IRQn);
     
     /* Clock at (1)MHz -> (1)tick/us */
-    LPTMR0->PSR = LPTMR_PSR_PCS(3);       // OSCERCLK -> 8MHz
-    LPTMR0->PSR |= LPTMR_PSR_PRESCALE(2); // divide by 8
+    /* Check if the external oscillator can be divided to 1MHz */
+    uint32_t extosc = extosc_frequency();
+    
+    if (extosc != 0) {                      //If external oscillator found
+        if (extosc % 1000000u == 0) {       //If it is a multiple if 1MHz
+            extosc /= 1000000;
+            if (extosc == 1)    {           //1MHz, set timerprescaler in bypass mode
+                LPTMR0->PSR = LPTMR_PSR_PCS(3) | LPTMR_PSR_PBYP_MASK;
+                return;
+            } else {                        //See if we can divide it to 1MHz
+                uint32_t divider = 0;
+                extosc >>= 1;
+                while (1) {
+                    if (extosc == 1) {
+                        LPTMR0->PSR = LPTMR_PSR_PCS(3) | LPTMR_PSR_PRESCALE(divider);
+                        return;
+                    }
+                    if (extosc % 2 != 0)    //If we can't divide by two anymore
+                        break;
+                    divider++;
+                    extosc >>= 1;
+                }
+            }
+        }
+    }
+    //No suitable external oscillator clock -> Use fast internal oscillator (4MHz)
+    MCG->C1 |= MCG_C1_IRCLKEN_MASK;
+    MCG->C2 |= MCG_C2_IRCS_MASK;
+    LPTMR0->PSR = LPTMR_PSR_PCS(0) | LPTMR_PSR_PRESCALE(1);
+    
 }
 
 void us_ticker_disable_interrupt(void) {
--- a/targets/hal/TARGET_Freescale/TARGET_KL46Z/PinNames.h	Thu Jan 09 09:00:05 2014 +0000
+++ b/targets/hal/TARGET_Freescale/TARGET_KL46Z/PinNames.h	Mon Jan 13 10:45:05 2014 +0000
@@ -197,7 +197,13 @@
     // mbed original LED naming
     LED1 = LED_GREEN,
     LED2 = LED_RED,
-
+	LED3 = LED_GREEN,
+    LED4 = LED_RED,
+    
+    //Push buttons
+    SW1 = PTC3,
+    SW3 = PTC12,
+	
     // USB Pins
     USBTX = PTA2,
     USBRX = PTA1,
--- a/targets/hal/TARGET_Freescale/TARGET_KL46Z/device.h	Thu Jan 09 09:00:05 2014 +0000
+++ b/targets/hal/TARGET_Freescale/TARGET_KL46Z/device.h	Mon Jan 13 10:45:05 2014 +0000
@@ -45,7 +45,7 @@
 #define DEVICE_LOCALFILESYSTEM  0
 #define DEVICE_ID_LENGTH       24
 
-#define DEVICE_SLEEP            0
+#define DEVICE_SLEEP            1
 
 #define DEVICE_DEBUG_AWARENESS  0
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/targets/hal/TARGET_Freescale/TARGET_KL46Z/sleep.c	Mon Jan 13 10:45:05 2014 +0000
@@ -0,0 +1,51 @@
+/* mbed Microcontroller Library
+ * Copyright (c) 2006-2013 ARM Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "sleep_api.h"
+#include "cmsis.h"
+
+//Normal wait mode
+void sleep(void)
+{
+    SMC->PMPROT = SMC_PMPROT_AVLLS_MASK | SMC_PMPROT_ALLS_MASK | SMC_PMPROT_AVLP_MASK;
+
+    //Normal sleep mode for ARM core:
+    SCB->SCR = 0;
+    __WFI();
+}
+
+//Very low-power stop mode
+void deepsleep(void)
+{
+    //Check if PLL/FLL is enabled:
+    uint32_t PLL_FLL_en = (MCG->C1 & MCG_C1_CLKS_MASK) == MCG_C1_CLKS(0);
+    
+    SMC->PMPROT = SMC_PMPROT_AVLLS_MASK | SMC_PMPROT_ALLS_MASK | SMC_PMPROT_AVLP_MASK;
+    SMC->PMCTRL = SMC_PMCTRL_STOPM(2);
+
+    //Deep sleep for ARM core:
+    SCB->SCR = 1<<SCB_SCR_SLEEPDEEP_Pos;
+
+    __WFI();
+
+    //Switch back to PLL as clock source if needed
+    //The interrupt that woke up the device will run at reduced speed
+    if (PLL_FLL_en) {
+        if (MCG->C6 & (1<<MCG_C6_PLLS_SHIFT) != 0) /* If PLL */
+            while((MCG->S & MCG_S_LOCK0_MASK) == 0x00U); /* Wait until locked */
+        MCG->C1 &= ~MCG_C1_CLKS_MASK;
+    }
+
+}
--- a/targets/hal/TARGET_Freescale/TARGET_KL46Z/spi_api.c	Thu Jan 09 09:00:05 2014 +0000
+++ b/targets/hal/TARGET_Freescale/TARGET_KL46Z/spi_api.c	Mon Jan 13 10:45:05 2014 +0000
@@ -158,7 +158,7 @@
     uint8_t  ref_prescaler = 0;
 
     // bus clk
-    uint32_t PCLK = 48000000u;
+    uint32_t PCLK = SystemCoreClock / (((SIM->CLKDIV1 & SIM_CLKDIV1_OUTDIV4_MASK) >> SIM_CLKDIV1_OUTDIV4_SHIFT) + 1);
     uint8_t prescaler = 1;
     uint8_t divisor = 2;