1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2025-01-18 12:52:44 +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 TIMER_NUMOF ((PIT_NUMOF) + (LPTMR_NUMOF))
#define PIT_BASECLOCK (CLOCK_BUSCLOCK) #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_0 isr_pit1
#define PIT_ISR_1 isr_pit3 #define PIT_ISR_1 isr_pit3
#define LPTMR_ISR_0 isr_lptmr0 #define LPTMR_ISR_0 isr_lptmr0
@ -82,13 +81,14 @@ extern "C"
static const uart_conf_t uart_config[] = { static const uart_conf_t uart_config[] = {
{ {
.dev = UART0, .dev = UART0,
.clken = (volatile uint32_t*)(BITBAND_REGADDR(SIM->SCGC4, SIM_SCGC4_UART0_SHIFT)),
.freq = CLOCK_CORECLOCK, .freq = CLOCK_CORECLOCK,
.pin_rx = GPIO_PIN(PORT_B, 16), .pin_rx = GPIO_PIN(PORT_B, 16),
.pin_tx = GPIO_PIN(PORT_B, 17), .pin_tx = GPIO_PIN(PORT_B, 17),
.pcr_rx = PORT_PCR_MUX(3), .pcr_rx = PORT_PCR_MUX(3),
.pcr_tx = PORT_PCR_MUX(3), .pcr_tx = PORT_PCR_MUX(3),
.irqn = UART0_RX_TX_IRQn, .irqn = UART0_RX_TX_IRQn,
.scgc_addr = &SIM->SCGC4,
.scgc_bit = SIM_SCGC4_UART0_SHIFT,
.mode = UART_MODE_8N1 .mode = UART_MODE_8N1
}, },
}; };

View File

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

View File

@ -70,7 +70,6 @@ extern "C"
#define TIMER_NUMOF ((PIT_NUMOF) + (LPTMR_NUMOF)) #define TIMER_NUMOF ((PIT_NUMOF) + (LPTMR_NUMOF))
#define PIT_BASECLOCK (CLOCK_BUSCLOCK) #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_0 isr_pit1
#define PIT_ISR_1 isr_pit3 #define PIT_ISR_1 isr_pit3
#define LPTMR_ISR_0 isr_lptmr0 #define LPTMR_ISR_0 isr_lptmr0
@ -84,24 +83,26 @@ extern "C"
static const uart_conf_t uart_config[] = { static const uart_conf_t uart_config[] = {
{ {
.dev = UART2, .dev = UART2,
.clken = (volatile uint32_t*)(BITBAND_REGADDR(SIM->SCGC4, SIM_SCGC4_UART2_SHIFT)),
.freq = CLOCK_BUSCLOCK, .freq = CLOCK_BUSCLOCK,
.pin_rx = GPIO_PIN(PORT_D, 2), .pin_rx = GPIO_PIN(PORT_D, 2),
.pin_tx = GPIO_PIN(PORT_D, 3), .pin_tx = GPIO_PIN(PORT_D, 3),
.pcr_rx = PORT_PCR_MUX(3), .pcr_rx = PORT_PCR_MUX(3),
.pcr_tx = PORT_PCR_MUX(3), .pcr_tx = PORT_PCR_MUX(3),
.irqn = UART2_RX_TX_IRQn, .irqn = UART2_RX_TX_IRQn,
.scgc_addr = &SIM->SCGC4,
.scgc_bit = SIM_SCGC4_UART2_SHIFT,
.mode = UART_MODE_8N1 .mode = UART_MODE_8N1
}, },
{ {
.dev = UART0, .dev = UART0,
.clken = (volatile uint32_t*)(BITBAND_REGADDR(SIM->SCGC4, SIM_SCGC4_UART0_SHIFT)),
.freq = CLOCK_CORECLOCK, .freq = CLOCK_CORECLOCK,
.pin_rx = GPIO_PIN(PORT_D, 6), .pin_rx = GPIO_PIN(PORT_D, 6),
.pin_tx = GPIO_PIN(PORT_D, 7), .pin_tx = GPIO_PIN(PORT_D, 7),
.pcr_rx = PORT_PCR_MUX(3), .pcr_rx = PORT_PCR_MUX(3),
.pcr_tx = PORT_PCR_MUX(3), .pcr_tx = PORT_PCR_MUX(3),
.irqn = UART0_RX_TX_IRQn, .irqn = UART0_RX_TX_IRQn,
.scgc_addr = &SIM->SCGC4,
.scgc_bit = SIM_SCGC4_UART0_SHIFT,
.mode = UART_MODE_8N1 .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 #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 LPTMR_CLKEN() (bit_set32(&SIM->SCGC5, SIM_SCGC5_LPTMR_SHIFT)) /**< Enable LPTMR0 clock gate */
#define LPTIMER_CLKDIS() (BITBAND_REG32(SIM->SCGC5, SIM_SCGC5_LPTIMER_SHIFT) = 0) /**< Disable LPTMR0 clock gate */ #define PIT_CLKEN() (bit_set32(&SIM->SCGC6, SIM_SCGC6_PIT_SHIFT)) /**< Enable PIT 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
/** @} */ /** @} */
/** /**
@ -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 #ifdef __cplusplus
} }
#endif #endif

View File

@ -62,22 +62,13 @@ extern "C"
#define PIN_INTERRUPT_EDGE 0b1011 #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 LPTMR_CLKEN() (bit_set32(&SIM->SCGC5, SIM_SCGC5_LPTMR_SHIFT)) /**< Enable LPTMR0 clock gate */
#define LPTIMER_CLKEN() (SIM->SCGC5 |= SIM_SCGC5_LPTMR_MASK) /**< Enable LPTMR0 clock gate */ #define PIT_CLKEN() (bit_set32(&SIM->SCGC6, SIM_SCGC6_PIT_SHIFT)) /**< Enable PIT clock gate */
#define LPTIMER_CLKDIS() (SIM->SCGC5 &= ~SIM_SCGC5_PTMR_MASK) /**< Disable LPTMR0 clock gate */ /** @} */
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

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

View File

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

View File

@ -25,6 +25,7 @@
#include <stdint.h> #include <stdint.h>
#include "cpu.h" #include "cpu.h"
#include "bit.h"
#include "periph/dac.h" #include "periph/dac.h"
#include "periph_conf.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; 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) void dac_poweron(dac_t line)

View File

@ -27,6 +27,7 @@
#include <stddef.h> #include <stddef.h>
#include <stdint.h> #include <stdint.h>
#include "cpu.h" #include "cpu.h"
#include "bit.h"
#include "periph/gpio.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) 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 <stdlib.h>
#include "cpu.h" #include "cpu.h"
#include "bit.h"
#include "board.h" #include "board.h"
#include "periph_conf.h" #include "periph_conf.h"
#include "periph/timer.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 pit_t pit[PIT_NUMOF];
static lptmr_t lptmr[LPTMR_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 * @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) 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 */ /* Completely disable the module before messing with the settings */
PIT->MCR = PIT_MCR_MDIS_MASK; 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; pit[dev].tctrl = PIT_TCTRL_TIE_MASK | PIT_TCTRL_CHN_MASK | PIT_TCTRL_TEN_MASK;
/* Add the new timeout offset to the up-counter */ /* Add the new timeout offset to the up-counter */
pit[dev].count += timeout; pit[dev].count += timeout;
if (PIT_BITBAND_TEN(ch) != 0) { if ((PIT->CHANNEL[ch].TCTRL & PIT_TCTRL_TEN_MASK) != 0) {
/* Timer is currently running */ /* Timer is currently running */
uint32_t cval = PIT->CHANNEL[ch].CVAL; uint32_t cval = PIT->CHANNEL[ch].CVAL;
/* Subtract if there was anything left on the counter */ /* 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; pit[dev].tctrl = PIT_TCTRL_TIE_MASK | PIT_TCTRL_CHN_MASK | PIT_TCTRL_TEN_MASK;
/* Set the new target time in the up-counter */ /* Set the new target time in the up-counter */
pit[dev].count = target; pit[dev].count = target;
if (PIT_BITBAND_TEN(ch) != 0) { if ((PIT->CHANNEL[ch].TCTRL & PIT_TCTRL_TEN_MASK) != 0) {
_pit_set_counter(dev); _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].tctrl = PIT_TCTRL_CHN_MASK | PIT_TCTRL_TEN_MASK;
/* pit[dev].count += PIT_MAX_VALUE + 1; */ /* == 0 (mod 2**32) */ /* 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 */ /* Timer is currently running */
uint32_t cval = PIT->CHANNEL[ch].CVAL; uint32_t cval = PIT->CHANNEL[ch].CVAL;
/* Subtract if there was anything left on the counter */ /* 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) inline static uint32_t pit_read(uint8_t dev)
{ {
uint8_t ch = pit_config[dev].count_ch; 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 */ /* Timer running */
return pit[dev].count - PIT->CHANNEL[ch].CVAL; 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) inline static void pit_start(uint8_t dev)
{ {
uint8_t ch = pit_config[dev].count_ch; 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 */ /* Already running */
return; return;
} }
@ -296,7 +293,7 @@ inline static void pit_start(uint8_t dev)
inline static void pit_stop(uint8_t dev) inline static void pit_stop(uint8_t dev)
{ {
uint8_t ch = pit_config[dev].count_ch; 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 */ /* Already stopped */
return; 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(); unsigned int mask = irq_disable();
/* Turn on module clock */ /* Turn on module clock */
*lptmr_config[dev].clk_gate = 1; LPTMR_CLKEN();
/* Completely disable the module before messing with the settings */ /* Completely disable the module before messing with the settings */
hw->CSR = 0; hw->CSR = 0;
/* select ERCLK32K as clock source for LPTMR */ /* 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 */ /* Clear IRQ flag in case it was already set */
hw->CSR = LPTMR_CSR_TCF_MASK; hw->CSR = LPTMR_CSR_TCF_MASK;
/* Enable IRQs on the counting channel */ /* Enable IRQs on the counting channel */
/* Refactor the below lines if there are any CPUs where the LPTMR IRQs are not sequential */ NVIC_ClearPendingIRQ(lptmr_config[dev].irqn);
NVIC_ClearPendingIRQ(LPTMR0_IRQn + lptmr_config[dev].index); NVIC_EnableIRQ(lptmr_config[dev].irqn);
NVIC_EnableIRQ(LPTMR0_IRQn + lptmr_config[dev].index);
_lptmr_set_cb_config(dev, cb, arg); _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 */ /* Disable counter and clear interrupt flag */
hw->CSR = LPTMR_CSR_TCF_MASK; hw->CSR = LPTMR_CSR_TCF_MASK;
/* Clear any pending IRQ */ /* Clear any pending IRQ */
NVIC_ClearPendingIRQ(LPTMR0_IRQn + lptmr_config[dev].index); NVIC_ClearPendingIRQ(lptmr_config[dev].irqn);
irq_restore(mask); irq_restore(mask);
} }
@ -566,7 +562,7 @@ inline static void lptmr_irq_handler(tim_t tim)
} }
/* Clear interrupt flag */ /* Clear interrupt flag */
BITBAND_REG32(hw->CSR, LPTMR_CSR_TCF_SHIFT) = 1; bit_set32(&hw->CSR, LPTMR_CSR_TCF_SHIFT);
cortexm_isr_end(); cortexm_isr_end();
} }

View File

@ -26,6 +26,7 @@
#include <math.h> #include <math.h>
#include "cpu.h" #include "cpu.h"
#include "bit.h"
#include "periph_conf.h" #include "periph_conf.h"
#include "periph/uart.h" #include "periph/uart.h"
@ -93,7 +94,7 @@ static int init_base(uart_t uart, uint32_t baudrate)
} }
/* Turn on module clock gate */ /* 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 */ /* disable transmitter and receiver */
dev->C2 &= ~(UART_C2_TE_MASK | UART_C2_RE_MASK); 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 LPTMR_CLKEN() (bit_set32(&SIM->SCGC5, SIM_SCGC5_LPTMR_SHIFT)) /**< Enable LPTMR0 clock gate */
#define LPTIMER_CLKEN() (SIM->SCGC5 |= SIM_SCGC5_LPTMR_MASK) /**< Enable LPTMR0 clock gate */ #define PIT_CLKEN() (bit_set32(&SIM->SCGC6, SIM_SCGC6_PIT_SHIFT)) /**< Enable PIT clock gate */
#define LPTIMER_CLKDIS() (SIM->SCGC5 &= ~SIM_SCGC5_PTMR_MASK) /**< Disable LPTMR0 clock gate */ /** @} */
/** /**
* @name KW2XD SiP internal interconnects between MCU and Modem. * @name KW2XD SiP internal interconnects between MCU and Modem.