Skip to content

KL46Z: Added Sleep, LED3 and LED4 definitions, switches #140

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Jan 13, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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},
Expand Down Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
Expand Up @@ -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},
Expand Down Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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;
Expand Down Expand Up @@ -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);
}

Expand All @@ -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);
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include "cmsis.h"
#include "pinmap.h"
#include "error.h"
#include "clk_freqs.h"

/******************************************************************************
* INITIALIZATION
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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
Expand All @@ -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,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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},
Expand Down Expand Up @@ -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;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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
}

Expand Down Expand Up @@ -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) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
Loading