1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00

Merge pull request #6916 from gebart/pr/cortexm3-bitband

cpu: Add bit manipulation macros for Cortex-M
This commit is contained in:
Kaspar Schleiser 2017-06-21 12:47:41 +02:00 committed by GitHub
commit 42830d2308
13 changed files with 298 additions and 148 deletions

View File

@ -68,7 +68,6 @@ extern "C"
#define TIMER_NUMOF ((PIT_NUMOF) + (LPTMR_NUMOF))
#define PIT_BASECLOCK (CLOCK_BUSCLOCK)
#define PIT_CLOCKGATE (BITBAND_REG32(SIM->SCGC6, SIM_SCGC6_PIT_SHIFT))
#define PIT_ISR_0 isr_pit1
#define PIT_ISR_1 isr_pit3
#define LPTMR_ISR_0 isr_lptmr0
@ -82,13 +81,14 @@ extern "C"
static const uart_conf_t uart_config[] = {
{
.dev = UART0,
.clken = (volatile uint32_t*)(BITBAND_REGADDR(SIM->SCGC4, SIM_SCGC4_UART0_SHIFT)),
.freq = CLOCK_CORECLOCK,
.pin_rx = GPIO_PIN(PORT_B, 16),
.pin_tx = GPIO_PIN(PORT_B, 17),
.pcr_rx = PORT_PCR_MUX(3),
.pcr_tx = PORT_PCR_MUX(3),
.irqn = UART0_RX_TX_IRQn,
.scgc_addr = &SIM->SCGC4,
.scgc_bit = SIM_SCGC4_UART0_SHIFT,
.mode = UART_MODE_8N1
},
};

View File

@ -78,14 +78,12 @@ extern "C"
#define LPTMR_CONFIG { \
{ \
.dev = LPTMR0, \
.clk_gate = (uint32_t volatile *)BITBAND_REGADDR(SIM->SCGC5, SIM_SCGC5_LPTIMER_SHIFT), \
.index = 0, \
.irqn = LPTMR0_IRQn, \
} \
}
#define TIMER_NUMOF ((PIT_NUMOF) + (LPTMR_NUMOF))
#define PIT_BASECLOCK (CLOCK_BUSCLOCK)
#define PIT_CLOCKGATE (BITBAND_REG32(SIM->SCGC6, SIM_SCGC6_PIT_SHIFT))
#define PIT_ISR_0 isr_pit1
#define PIT_ISR_1 isr_pit3
#define LPTMR_ISR_0 isr_lptmr0
@ -99,24 +97,26 @@ extern "C"
static const uart_conf_t uart_config[] = {
{
.dev = UART0,
.clken = (volatile uint32_t*)(BITBAND_REGADDR(SIM->SCGC4, SIM_SCGC4_UART0_SHIFT)),
.freq = CLOCK_CORECLOCK,
.pin_rx = GPIO_PIN(PORT_A, 14),
.pin_tx = GPIO_PIN(PORT_A, 15),
.pcr_rx = PORT_PCR_MUX(3),
.pcr_tx = PORT_PCR_MUX(3),
.irqn = UART0_RX_TX_IRQn,
.scgc_addr = &SIM->SCGC4,
.scgc_bit = SIM_SCGC4_UART0_SHIFT,
.mode = UART_MODE_8N1
},
{
.dev = UART1,
.clken = (volatile uint32_t*)(BITBAND_REGADDR(SIM->SCGC4, SIM_SCGC4_UART1_SHIFT)),
.freq = CLOCK_CORECLOCK,
.pin_rx = GPIO_PIN(PORT_C, 3),
.pin_tx = GPIO_PIN(PORT_C, 4),
.pcr_rx = PORT_PCR_MUX(3),
.pcr_tx = PORT_PCR_MUX(3),
.irqn = UART1_RX_TX_IRQn,
.scgc_addr = &SIM->SCGC4,
.scgc_bit = SIM_SCGC4_UART1_SHIFT,
.mode = UART_MODE_8N1
},
};

View File

@ -70,7 +70,6 @@ extern "C"
#define TIMER_NUMOF ((PIT_NUMOF) + (LPTMR_NUMOF))
#define PIT_BASECLOCK (CLOCK_BUSCLOCK)
#define PIT_CLOCKGATE (BITBAND_REG32(SIM->SCGC6, SIM_SCGC6_PIT_SHIFT))
#define PIT_ISR_0 isr_pit1
#define PIT_ISR_1 isr_pit3
#define LPTMR_ISR_0 isr_lptmr0
@ -84,24 +83,26 @@ extern "C"
static const uart_conf_t uart_config[] = {
{
.dev = UART2,
.clken = (volatile uint32_t*)(BITBAND_REGADDR(SIM->SCGC4, SIM_SCGC4_UART2_SHIFT)),
.freq = CLOCK_BUSCLOCK,
.pin_rx = GPIO_PIN(PORT_D, 2),
.pin_tx = GPIO_PIN(PORT_D, 3),
.pcr_rx = PORT_PCR_MUX(3),
.pcr_tx = PORT_PCR_MUX(3),
.irqn = UART2_RX_TX_IRQn,
.scgc_addr = &SIM->SCGC4,
.scgc_bit = SIM_SCGC4_UART2_SHIFT,
.mode = UART_MODE_8N1
},
{
.dev = UART0,
.clken = (volatile uint32_t*)(BITBAND_REGADDR(SIM->SCGC4, SIM_SCGC4_UART0_SHIFT)),
.freq = CLOCK_CORECLOCK,
.pin_rx = GPIO_PIN(PORT_D, 6),
.pin_tx = GPIO_PIN(PORT_D, 7),
.pcr_rx = PORT_PCR_MUX(3),
.pcr_tx = PORT_PCR_MUX(3),
.irqn = UART0_RX_TX_IRQn,
.scgc_addr = &SIM->SCGC4,
.scgc_bit = SIM_SCGC4_UART0_SHIFT,
.mode = UART_MODE_8N1
}
};

View File

@ -0,0 +1,231 @@
/*
* Copyright (C) 2017 Eistec AB
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @ingroup cpu_cortexm_common
* @{
*
* @file
* @brief Bit access macros for Cortex-M based CPUs
*
* @author Joakim Nohlgård <joakim.nohlgard@eistec.se>
*/
#ifndef BIT_H
#define BIT_H
#include <stdint.h>
#include "cpu.h"
#ifdef __cplusplus
extern "C" {
#endif
/* Define BITBAND_FUNCTIONS_PROVIDED 1 if the CPU provides its own
* implementations for bit manipulation */
#if !BITBAND_FUNCTIONS_PROVIDED
#if DOXYGEN
/** @brief Flag for telling if the CPU has hardware bit band support */
#define CPU_HAS_BITBAND 1 || 0 (1 for Cortex-M3 and up, 0 for Cortex-M0)
#endif
#ifndef CPU_HAS_BITBAND
#if (__CORTEX_M >= 3)
#define CPU_HAS_BITBAND 1
#else
#define CPU_HAS_BITBAND 0
#endif
#endif
#if CPU_HAS_BITBAND || DOXYGEN
/* Cortex-M3 and higher provide a bitband address space for atomically accessing
* single bits of peripheral registers, and sometimes for RAM as well */
/**
* @name Bit manipulation functions
* @{
*/
/* Generic bit band conversion routine */
/**
* @brief Convert bit band region address and bit number to bit band alias address
*
* @param[in] ptr base address in non bit banded memory
* @param[in] bit bit number within the word
*
* @return Address of the bit within the bit band memory region
*/
static inline volatile void *bitband_addr(volatile void *ptr, uintptr_t bit)
{
return (volatile void *)((((uintptr_t)ptr) & 0xF0000000ul) + 0x2000000ul +
((((uintptr_t)ptr) & 0xFFFFFul) << 5) + (bit << 2));
}
/**
* @brief Set a single bit in the 32 bit word pointed to by @p ptr
*
* The effect is the same as for the following snippet:
*
* @code{c}
* *ptr |= (1 << bit);
* @endcode
*
* There is a read-modify-write cycle occurring within the core, but this cycle
* is atomic and can not be disrupted by IRQs
*
* @param[in] ptr pointer to target word
* @param[in] bit bit number within the word
*/
static inline void bit_set32(volatile uint32_t *ptr, uint8_t bit)
{
*((volatile uint32_t *)bitband_addr(ptr, bit)) = 1;
}
/**
* @brief Set a single bit in the 16 bit word pointed to by @p ptr
*
* The effect is the same as for the following snippet:
*
* @code{c}
* *ptr |= (1 << bit);
* @endcode
*
* There is a read-modify-write cycle occurring within the core, but this cycle
* is atomic and can not be disrupted by IRQs
*
* @param[in] ptr pointer to target word
* @param[in] bit bit number within the word
*/
static inline void bit_set16(volatile uint16_t *ptr, uint8_t bit)
{
*((volatile uint16_t *)bitband_addr(ptr, bit)) = 1;
}
/**
* @brief Set a single bit in the 8 bit byte pointed to by @p ptr
*
* The effect is the same as for the following snippet:
*
* @code{c}
* *ptr |= (1 << bit);
* @endcode
*
* There is a read-modify-write cycle occurring within the core, but this cycle
* is atomic and can not be disrupted by IRQs
*
* @param[in] ptr pointer to target byte
* @param[in] bit bit number within the byte
*/
static inline void bit_set8(volatile uint8_t *ptr, uint8_t bit)
{
*((volatile uint8_t *)bitband_addr(ptr, bit)) = 1;
}
/**
* @brief Clear a single bit in the 32 bit word pointed to by @p ptr
*
* The effect is the same as for the following snippet:
*
* @code{c}
* *ptr &= ~(1 << bit);
* @endcode
*
* There is a read-modify-write cycle occurring within the core, but this cycle
* is atomic and can not be disrupted by IRQs
*
* @param[in] ptr pointer to target word
* @param[in] bit bit number within the word
*/
static inline void bit_clear32(volatile uint32_t *ptr, uint8_t bit)
{
*((volatile uint32_t *)bitband_addr(ptr, bit)) = 0;
}
/**
* @brief Clear a single bit in the 16 bit word pointed to by @p ptr
*
* The effect is the same as for the following snippet:
*
* @code{c}
* *ptr &= ~(1 << bit);
* @endcode
*
* There is a read-modify-write cycle occurring within the core, but this cycle
* is atomic and can not be disrupted by IRQs
*
* @param[in] ptr pointer to target word
* @param[in] bit bit number within the word
*/
static inline void bit_clear16(volatile uint16_t *ptr, uint8_t bit)
{
*((volatile uint16_t *)bitband_addr(ptr, bit)) = 0;
}
/**
* @brief Clear a single bit in the 8 bit byte pointed to by @p ptr
*
* The effect is the same as for the following snippet:
*
* @code{c}
* *ptr &= ~(1 << bit);
* @endcode
*
* There is a read-modify-write cycle occurring within the core, but this cycle
* is atomic and can not be disrupted by IRQs
*
* @param[in] ptr pointer to target byte
* @param[in] bit bit number within the byte
*/
static inline void bit_clear8(volatile uint8_t *ptr, uint8_t bit)
{
*((volatile uint8_t *)bitband_addr(ptr, bit)) = 0;
}
/** @} */
#else /* CPU_HAS_BITBAND */
/* CPU does not have bitbanding, fall back to plain C */
static inline void bit_set32(volatile uint32_t *ptr, uint8_t bit)
{
*ptr |= (1 << (bit));
}
static inline void bit_set16(volatile uint16_t *ptr, uint8_t bit)
{
*ptr |= (1 << (bit));
}
static inline void bit_set8(volatile uint8_t *ptr, uint8_t bit)
{
*ptr |= (1 << (bit));
}
static inline void bit_clear32(volatile uint32_t *ptr, uint8_t bit)
{
*ptr &= ~(1 << (bit));
}
static inline void bit_clear16(volatile uint16_t *ptr, uint8_t bit)
{
*ptr &= ~(1 << (bit));
}
static inline void bit_clear8(volatile uint8_t *ptr, uint8_t bit)
{
*ptr &= ~(1 << (bit));
}
#endif /* CPU_HAS_BITBAND */
#endif /* !BITBAND_FUNCTIONS_PROVIDED */
#ifdef __cplusplus
}
#endif
#endif /* BIT_H */
/** @} */

View File

@ -68,50 +68,12 @@ extern "C"
#define PIN_INTERRUPT_EDGE 0b1011
/** @} */
/** @name PORT module clock gates */
/** @{ */
#define PORTA_CLOCK_GATE (BITBAND_REG32(SIM->SCGC5, SIM_SCGC5_PORTA_SHIFT))
#define PORTB_CLOCK_GATE (BITBAND_REG32(SIM->SCGC5, SIM_SCGC5_PORTB_SHIFT))
#define PORTC_CLOCK_GATE (BITBAND_REG32(SIM->SCGC5, SIM_SCGC5_PORTC_SHIFT))
#define PORTD_CLOCK_GATE (BITBAND_REG32(SIM->SCGC5, SIM_SCGC5_PORTD_SHIFT))
#define PORTE_CLOCK_GATE (BITBAND_REG32(SIM->SCGC5, SIM_SCGC5_PORTE_SHIFT))
/** @} */
/**
* @name Clock settings for the LPTMR0 timer
* @{
* @name Timer hardware information
*/
#define LPTIMER_DEV (LPTMR0) /**< LPTIMER hardware module */
#define LPTIMER_CLKEN() (BITBAND_REG32(SIM->SCGC5, SIM_SCGC5_LPTIMER_SHIFT) = 1) /**< Enable LPTMR0 clock gate */
#define LPTIMER_CLKDIS() (BITBAND_REG32(SIM->SCGC5, SIM_SCGC5_LPTIMER_SHIFT) = 0) /**< Disable LPTMR0 clock gate */
#define LPTIMER_CLKSRC_MCGIRCLK 0 /**< internal reference clock (4MHz) */
#define LPTIMER_CLKSRC_LPO 1 /**< PMC 1kHz output */
#define LPTIMER_CLKSRC_ERCLK32K 2 /**< RTC clock 32768Hz */
#define LPTIMER_CLKSRC_OSCERCLK 3 /**< system oscillator output, clock from RF-Part */
#ifndef LPTIMER_CLKSRC
#define LPTIMER_CLKSRC LPTIMER_CLKSRC_ERCLK32K /**< default clock source */
#endif
#if (LPTIMER_CLKSRC == LPTIMER_CLKSRC_MCGIRCLK)
#define LPTIMER_CLK_PRESCALE 1
#define LPTIMER_SPEED 1000000
#elif (LPTIMER_CLKSRC == LPTIMER_CLKSRC_OSCERCLK)
#define LPTIMER_CLK_PRESCALE 1
#define LPTIMER_SPEED 1000000
#elif (LPTIMER_CLKSRC == LPTIMER_CLKSRC_ERCLK32K)
#define LPTIMER_CLK_PRESCALE 0
#define LPTIMER_SPEED 32768
#else
#define LPTIMER_CLK_PRESCALE 0
#define LPTIMER_SPEED 1000
#endif
/** IRQ priority for hwtimer interrupts */
#define LPTIMER_IRQ_PRIO 1
/** IRQ channel for hwtimer interrupts */
#define LPTIMER_IRQ_CHAN LPTMR0_IRQn
/** @{ */
#define LPTMR_CLKEN() (bit_set32(&SIM->SCGC5, SIM_SCGC5_LPTMR_SHIFT)) /**< Enable LPTMR0 clock gate */
#define PIT_CLKEN() (bit_set32(&SIM->SCGC6, SIM_SCGC6_PIT_SHIFT)) /**< Enable PIT clock gate */
/** @} */
/**
@ -199,45 +161,6 @@ typedef enum llwu_wakeup_pin {
/** @} */
/**
* @name Bit band macros
* @{
*/
/* Generic bitband conversion routine */
/** @brief Convert bit-band region address and bit number to bit-band alias address
*
* @param[in] addr base address in non-bit-banded memory
* @param[in] bit bit number within the word
*
* @return Address of the bit within the bit-band memory region
*/
#define BITBAND_ADDR(addr, bit) ((((uint32_t) (addr)) & 0xF0000000u) + 0x2000000 + ((((uint32_t) (addr)) & 0xFFFFF) << 5) + ((bit) << 2))
/**
* @brief Bitband 32 bit access to variable stored in SRAM_U
*
* @note SRAM_L is not bit band aliased on the K60, only SRAM_U (0x20000000 and up)
* @note var must be declared 'volatile'
*/
#define BITBAND_VAR32(var, bit) (*((uint32_t volatile*) BITBAND_ADDR(&(var), (bit))))
/**
* @brief Bitband 16 bit access to variable stored in SRAM_U
*
* @note SRAM_L is not bit band aliased on the K60, only SRAM_U (0x20000000 and up)
* @note var must be declared 'volatile'
*/
#define BITBAND_VAR16(var, bit) (*((uint16_t volatile*) BITBAND_ADDR(&(var), (bit))))
/**
* @brief Bitband 8 bit access to variable stored in SRAM_U
*
* @note SRAM_L is not bit band aliased on the K60, only SRAM_U (0x20000000 and up)
* @note var must be declared 'volatile'
*/
#define BITBAND_VAR8(var, bit) (*((uint8_t volatile*) BITBAND_ADDR(&(var), (bit))))
/** @} */
#ifdef __cplusplus
}
#endif

View File

@ -62,22 +62,13 @@ extern "C"
#define PIN_INTERRUPT_EDGE 0b1011
/** @} */
/** @name PORT module clock gates */
/** @{ */
#define PORTA_CLOCK_GATE (BITBAND_REG32(SIM->SCGC5, SIM_SCGC5_PORTA_SHIFT))
#define PORTB_CLOCK_GATE (BITBAND_REG32(SIM->SCGC5, SIM_SCGC5_PORTB_SHIFT))
#define PORTC_CLOCK_GATE (BITBAND_REG32(SIM->SCGC5, SIM_SCGC5_PORTC_SHIFT))
#define PORTD_CLOCK_GATE (BITBAND_REG32(SIM->SCGC5, SIM_SCGC5_PORTD_SHIFT))
#define PORTE_CLOCK_GATE (BITBAND_REG32(SIM->SCGC5, SIM_SCGC5_PORTE_SHIFT))
/** @} */
/**
* @brief MCU specific Low Power Timer settings.
* @name Timer hardware information
*/
#define LPTIMER_CLKSRC LPTIMER_CLKSRC_LPO
#define LPTIMER_DEV (LPTMR0) /**< LPTIMER hardware module */
#define LPTIMER_CLKEN() (SIM->SCGC5 |= SIM_SCGC5_LPTMR_MASK) /**< Enable LPTMR0 clock gate */
#define LPTIMER_CLKDIS() (SIM->SCGC5 &= ~SIM_SCGC5_PTMR_MASK) /**< Disable LPTMR0 clock gate */
/** @{ */
#define LPTMR_CLKEN() (bit_set32(&SIM->SCGC5, SIM_SCGC5_LPTMR_SHIFT)) /**< Enable LPTMR0 clock gate */
#define PIT_CLKEN() (bit_set32(&SIM->SCGC6, SIM_SCGC6_PIT_SHIFT)) /**< Enable PIT clock gate */
/** @} */
#ifdef __cplusplus
}

View File

@ -261,10 +261,8 @@ typedef struct {
typedef struct {
/** LPTMR device base pointer */
LPTMR_Type *dev;
/** Pointer to module clock gate bit in bitband region, use BITBAND_REGADDR() */
uint32_t volatile *clk_gate;
/** LPTMR device index */
uint8_t index;
/** IRQn interrupt number */
uint8_t irqn;
} lptmr_conf_t;
/**
@ -314,15 +312,16 @@ enum {
* @brief UART module configuration options
*/
typedef struct {
UART_Type *dev; /**< Pointer to module hardware registers */
volatile uint32_t *clken; /**< Clock enable bitband register address */
uint32_t freq; /**< Module clock frequency, usually CLOCK_CORECLOCK or CLOCK_BUSCLOCK */
gpio_t pin_rx; /**< RX pin, GPIO_UNDEF disables RX */
gpio_t pin_tx; /**< TX pin */
uint32_t pcr_rx; /**< Pin configuration register bits for RX */
uint32_t pcr_tx; /**< Pin configuration register bits for TX */
IRQn_Type irqn; /**< IRQ number for this module */
uint8_t mode; /**< UART mode: data bits, parity, stop bits */
UART_Type *dev; /**< Pointer to module hardware registers */
uint32_t freq; /**< Module clock frequency, usually CLOCK_CORECLOCK or CLOCK_BUSCLOCK */
gpio_t pin_rx; /**< RX pin, GPIO_UNDEF disables RX */
gpio_t pin_tx; /**< TX pin */
uint32_t pcr_rx; /**< Pin configuration register bits for RX */
uint32_t pcr_tx; /**< Pin configuration register bits for TX */
IRQn_Type irqn; /**< IRQ number for this module */
volatile uint32_t *scgc_addr; /**< Clock enable register, in SIM module */
uint8_t scgc_bit; /**< Clock enable bit, within the register */
uint8_t mode; /**< UART mode: data bits, parity, stop bits */
} uart_conf_t;
/**

View File

@ -25,6 +25,7 @@
#include <stdio.h>
#include "cpu.h"
#include "bit.h"
#include "mutex.h"
#include "periph/adc.h"
@ -65,11 +66,11 @@ static inline int dev_num(adc_t line)
static inline void prep(adc_t line)
{
if (dev(line) == ADC0) {
BITBAND_REG32(SIM->SCGC6, SIM_SCGC6_ADC0_SHIFT) = 1;
bit_set32(&SIM->SCGC6, SIM_SCGC6_ADC0_SHIFT);
}
#ifdef ADC1
else {
BITBAND_REG32(SIM->SCGC3, SIM_SCGC3_ADC1_SHIFT) = 1;
bit_set32(&SIM->SCGC3, SIM_SCGC3_ADC1_SHIFT);
}
#endif
mutex_lock(&locks[dev_num(line)]);
@ -78,11 +79,11 @@ static inline void prep(adc_t line)
static inline void done(adc_t line)
{
if (dev(line) == ADC0) {
BITBAND_REG32(SIM->SCGC6, SIM_SCGC6_ADC0_SHIFT) = 0;
bit_clear32(&SIM->SCGC6, SIM_SCGC6_ADC0_SHIFT);
}
#ifdef ADC1
else {
BITBAND_REG32(SIM->SCGC3, SIM_SCGC3_ADC1_SHIFT) = 0;
bit_clear32(&SIM->SCGC3, SIM_SCGC3_ADC1_SHIFT);
}
#endif
mutex_unlock(&locks[dev_num(line)]);

View File

@ -25,6 +25,7 @@
#include <stdint.h>
#include "cpu.h"
#include "bit.h"
#include "periph/dac.h"
#include "periph_conf.h"
@ -84,7 +85,12 @@ static inline void _dac_set_power(dac_t line, uint8_t value)
dac = dac_config[line].dev;
BITBAND_REG8(dac->C0, DAC_C0_DACEN_SHIFT) = value;
if (value) {
bit_set8(&dac->C0, DAC_C0_DACEN_SHIFT);
}
else {
bit_clear8(&dac->C0, DAC_C0_DACEN_SHIFT);
}
}
void dac_poweron(dac_t line)

View File

@ -27,6 +27,7 @@
#include <stddef.h>
#include <stdint.h>
#include "cpu.h"
#include "bit.h"
#include "periph/gpio.h"
/**
@ -129,7 +130,7 @@ static inline int pin_num(gpio_t pin)
static inline void clk_en(gpio_t pin)
{
BITBAND_REG32(SIM->SCGC5, SIM_SCGC5_PORTA_SHIFT + port_num(pin)) = 1;
bit_set32(&SIM->SCGC5, SIM_SCGC5_PORTA_SHIFT + port_num(pin));
}
/**

View File

@ -26,6 +26,7 @@
#include <stdlib.h>
#include "cpu.h"
#include "bit.h"
#include "board.h"
#include "periph_conf.h"
#include "periph/timer.h"
@ -87,11 +88,6 @@ static const lptmr_conf_t lptmr_config[LPTMR_NUMOF] = LPTMR_CONFIG;
static pit_t pit[PIT_NUMOF];
static lptmr_t lptmr[LPTMR_NUMOF];
/**
* @brief lvalue accessor for PIT channel enable bit in the bitband region
*/
#define PIT_BITBAND_TEN(ch) (BITBAND_REG32(PIT->CHANNEL[ch].TCTRL, PIT_TCTRL_TEN_SHIFT))
/**
* @brief Find out whether a given timer is a LPTMR or a PIT timer
*/
@ -174,7 +170,8 @@ inline static void _pit_set_counter(uint8_t dev)
inline static int pit_init(uint8_t dev, uint32_t freq, timer_cb_t cb, void *arg)
{
PIT_CLOCKGATE = 1;
/* Turn on module clock gate */
PIT_CLKEN();
/* Completely disable the module before messing with the settings */
PIT->MCR = PIT_MCR_MDIS_MASK;
@ -215,7 +212,7 @@ inline static int pit_set(uint8_t dev, uint32_t timeout)
pit[dev].tctrl = PIT_TCTRL_TIE_MASK | PIT_TCTRL_CHN_MASK | PIT_TCTRL_TEN_MASK;
/* Add the new timeout offset to the up-counter */
pit[dev].count += timeout;
if (PIT_BITBAND_TEN(ch) != 0) {
if ((PIT->CHANNEL[ch].TCTRL & PIT_TCTRL_TEN_MASK) != 0) {
/* Timer is currently running */
uint32_t cval = PIT->CHANNEL[ch].CVAL;
/* Subtract if there was anything left on the counter */
@ -237,7 +234,7 @@ inline static int pit_set_absolute(uint8_t dev, uint32_t target)
pit[dev].tctrl = PIT_TCTRL_TIE_MASK | PIT_TCTRL_CHN_MASK | PIT_TCTRL_TEN_MASK;
/* Set the new target time in the up-counter */
pit[dev].count = target;
if (PIT_BITBAND_TEN(ch) != 0) {
if ((PIT->CHANNEL[ch].TCTRL & PIT_TCTRL_TEN_MASK) != 0) {
_pit_set_counter(dev);
}
@ -255,7 +252,7 @@ inline static int pit_clear(uint8_t dev)
pit[dev].tctrl = PIT_TCTRL_CHN_MASK | PIT_TCTRL_TEN_MASK;
/* pit[dev].count += PIT_MAX_VALUE + 1; */ /* == 0 (mod 2**32) */
if (PIT_BITBAND_TEN(ch) != 0) {
if ((PIT->CHANNEL[ch].TCTRL & PIT_TCTRL_TEN_MASK) != 0) {
/* Timer is currently running */
uint32_t cval = PIT->CHANNEL[ch].CVAL;
/* Subtract if there was anything left on the counter */
@ -271,7 +268,7 @@ inline static int pit_clear(uint8_t dev)
inline static uint32_t pit_read(uint8_t dev)
{
uint8_t ch = pit_config[dev].count_ch;
if (PIT_BITBAND_TEN(ch) != 0) {
if ((PIT->CHANNEL[ch].TCTRL & PIT_TCTRL_TEN_MASK) != 0) {
/* Timer running */
return pit[dev].count - PIT->CHANNEL[ch].CVAL;
}
@ -284,7 +281,7 @@ inline static uint32_t pit_read(uint8_t dev)
inline static void pit_start(uint8_t dev)
{
uint8_t ch = pit_config[dev].count_ch;
if (PIT_BITBAND_TEN(ch) != 0) {
if ((PIT->CHANNEL[ch].TCTRL & PIT_TCTRL_TEN_MASK) != 0) {
/* Already running */
return;
}
@ -296,7 +293,7 @@ inline static void pit_start(uint8_t dev)
inline static void pit_stop(uint8_t dev)
{
uint8_t ch = pit_config[dev].count_ch;
if (PIT_BITBAND_TEN(ch) == 0) {
if ((PIT->CHANNEL[ch].TCTRL & PIT_TCTRL_TEN_MASK) == 0) {
/* Already stopped */
return;
}
@ -438,7 +435,7 @@ inline static int lptmr_init(uint8_t dev, uint32_t freq, timer_cb_t cb, void *ar
unsigned int mask = irq_disable();
/* Turn on module clock */
*lptmr_config[dev].clk_gate = 1;
LPTMR_CLKEN();
/* Completely disable the module before messing with the settings */
hw->CSR = 0;
/* select ERCLK32K as clock source for LPTMR */
@ -447,9 +444,8 @@ inline static int lptmr_init(uint8_t dev, uint32_t freq, timer_cb_t cb, void *ar
/* Clear IRQ flag in case it was already set */
hw->CSR = LPTMR_CSR_TCF_MASK;
/* Enable IRQs on the counting channel */
/* Refactor the below lines if there are any CPUs where the LPTMR IRQs are not sequential */
NVIC_ClearPendingIRQ(LPTMR0_IRQn + lptmr_config[dev].index);
NVIC_EnableIRQ(LPTMR0_IRQn + lptmr_config[dev].index);
NVIC_ClearPendingIRQ(lptmr_config[dev].irqn);
NVIC_EnableIRQ(lptmr_config[dev].irqn);
_lptmr_set_cb_config(dev, cb, arg);
@ -549,7 +545,7 @@ inline static void lptmr_stop(uint8_t dev)
/* Disable counter and clear interrupt flag */
hw->CSR = LPTMR_CSR_TCF_MASK;
/* Clear any pending IRQ */
NVIC_ClearPendingIRQ(LPTMR0_IRQn + lptmr_config[dev].index);
NVIC_ClearPendingIRQ(lptmr_config[dev].irqn);
irq_restore(mask);
}
@ -566,7 +562,7 @@ inline static void lptmr_irq_handler(tim_t tim)
}
/* Clear interrupt flag */
BITBAND_REG32(hw->CSR, LPTMR_CSR_TCF_SHIFT) = 1;
bit_set32(&hw->CSR, LPTMR_CSR_TCF_SHIFT);
cortexm_isr_end();
}

View File

@ -26,6 +26,7 @@
#include <math.h>
#include "cpu.h"
#include "bit.h"
#include "periph_conf.h"
#include "periph/uart.h"
@ -93,7 +94,7 @@ static int init_base(uart_t uart, uint32_t baudrate)
}
/* Turn on module clock gate */
*(uart_config[uart].clken) = 1;
bit_set32(uart_config[uart].scgc_addr, uart_config[uart].scgc_bit);
/* disable transmitter and receiver */
dev->C2 &= ~(UART_C2_TE_MASK | UART_C2_RE_MASK);

View File

@ -77,12 +77,12 @@ extern "C"
/** @} */
/**
* @brief MCU specific Low Power Timer settings.
* @name Timer hardware information
*/
#define LPTIMER_CLKSRC LPTIMER_CLKSRC_LPO
#define LPTIMER_DEV (LPTMR0) /**< LPTIMER hardware module */
#define LPTIMER_CLKEN() (SIM->SCGC5 |= SIM_SCGC5_LPTMR_MASK) /**< Enable LPTMR0 clock gate */
#define LPTIMER_CLKDIS() (SIM->SCGC5 &= ~SIM_SCGC5_PTMR_MASK) /**< Disable LPTMR0 clock gate */
/** @{ */
#define LPTMR_CLKEN() (bit_set32(&SIM->SCGC5, SIM_SCGC5_LPTMR_SHIFT)) /**< Enable LPTMR0 clock gate */
#define PIT_CLKEN() (bit_set32(&SIM->SCGC6, SIM_SCGC6_PIT_SHIFT)) /**< Enable PIT clock gate */
/** @} */
/**
* @name KW2XD SiP internal interconnects between MCU and Modem.