mbed library with additional peripherals for ST F401 board
Fork of mbed-src by
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
Revision 72:248c61396e08, committed 2014-01-13
- 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
--- 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;