mirror of https://github.com/ARMmbed/mbed-os.git
Merge pull request #140 from Sissors/master
KL46Z: Added Sleep, LED3 and LED4 definitions, switchespull/144/head mbed_lib_rev76
commit
f1904ba15c
|
@ -115,7 +115,7 @@ void spi_frequency(spi_t *obj, int hz) {
|
|||
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;
|
||||
|
||||
|
|
|
@ -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 @@ void analogin_init(analogin_t *obj, PinName pin) {
|
|||
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
|
||||
|
|
|
@ -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
|
|
@ -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 @@ void i2c_frequency(i2c_t *obj, int hz) {
|
|||
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
|
||||
|
|
|
@ -64,14 +64,25 @@ static const PinMap PinMap_PWM[] = {
|
|||
{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 @@ void pwmout_init(pwmout_t* obj, PinName pin) {
|
|||
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 @@ void pwmout_period_ms(pwmout_t* obj, int ms) {
|
|||
// 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_ms(pwmout_t* obj, int ms) {
|
|||
}
|
||||
|
||||
void pwmout_pulsewidth_us(pwmout_t* obj, int us) {
|
||||
*obj->CnV = PWM_CLOCK_MHZ * us;
|
||||
*obj->CnV = (uint32_t)(pwm_clock * (float)us);
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include "cmsis.h"
|
||||
#include "pinmap.h"
|
||||
#include "error.h"
|
||||
#include "clk_freqs.h"
|
||||
|
||||
/******************************************************************************
|
||||
* INITIALIZATION
|
||||
|
@ -70,7 +71,10 @@ void serial_init(serial_t *obj, PinName tx, PinName rx) {
|
|||
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 @@ void serial_free(serial_t *obj) {
|
|||
// 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 @@ void serial_baud(serial_t *obj, int baudrate) {
|
|||
// 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,
|
||||
|
|
|
@ -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 @@ void spi_frequency(spi_t *obj, int hz) {
|
|||
uint8_t ref_prescaler = 0;
|
||||
|
||||
// bus clk
|
||||
uint32_t PCLK = 48000000u;
|
||||
uint32_t PCLK = bus_frequency();
|
||||
uint8_t prescaler = 1;
|
||||
uint8_t divisor = 2;
|
||||
|
||||
|
|
|
@ -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 @@ static void pit_init(void) {
|
|||
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 @@ static void lptmr_init(void) {
|
|||
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) {
|
||||
|
|
|
@ -197,7 +197,13 @@ typedef enum {
|
|||
// 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,
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -158,7 +158,7 @@ void spi_frequency(spi_t *obj, int hz) {
|
|||
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;
|
||||
|
||||
|
|
Loading…
Reference in New Issue