mbed library with additional peripherals for ST F401 board

Fork of mbed-src by mbed official

This mbed LIB has additional peripherals for ST F401 board

  • UART2 : PA_3 rx, PA_2 tx
  • UART3 : PC_7 rx, PC_6 tx
  • I2C2 : PB_3 SDA, PB_10 SCL
  • I2C3 : PB_4 SDA, PA_8 SCL

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;