Skip to content

Commit

Permalink
Merge pull request #20357 from maribu/cpu/msp430/usci
Browse files Browse the repository at this point in the history
cpu/msp430/f2xx: clean up periph_uart,periph_spi
  • Loading branch information
maribu authored Mar 27, 2024
2 parents 15e2b9e + 10ee192 commit 4b3308c
Show file tree
Hide file tree
Showing 22 changed files with 662 additions and 175 deletions.
39 changes: 17 additions & 22 deletions boards/olimex-msp430-h2618/include/periph_conf.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,36 +47,31 @@ static const msp430_clock_params_t clock_params = {
* @name UART configuration
* @{
*/
#define UART_NUMOF (1U)
static const uart_conf_t uart_config[] = {
{
.uart = &usci_a1_as_uart,
},
};

#define UART0_RX_ISR USCIAB1RX_VECTOR /**< RX IRQ vector of UART 0 */

#define UART_BASE (&USCI_A1)
#define UART_IE (UC1IE)
#define UART_IF (UC1IFG)
#define UART_IE_RX_BIT (1 << 0)
#define UART_IE_TX_BIT (1 << 1)
#define UART_RX_PORT (&PORT_3)
#define UART_RX_PIN (1 << 7)
#define UART_TX_PORT (&PORT_3)
#define UART_TX_PIN (1 << 6)
#define UART_RX_ISR (USCIAB1RX_VECTOR)
#define UART_TX_ISR (USCIAB1TX_VECTOR)
#define UART_NUMOF ARRAY_SIZE(uart_config)
/** @} */

/**
* @name SPI configuration
* @{
*/
#define SPI_NUMOF (1U)
static const spi_conf_t spi_config[] = {
{
.spi = &usci_b0_as_spi,
},
{
.spi = &usci_b1_as_spi,
},
};

/* SPI configuration */
#define SPI_BASE (&USCI_B0)
#define SPI_IE (IE2)
#define SPI_IF (IFG2)
#define SPI_IE_RX_BIT (1 << 2)
#define SPI_IE_TX_BIT (1 << 3)
#define SPI_PIN_MISO GPIO_PIN(P3, 2)
#define SPI_PIN_MOSI GPIO_PIN(P3, 1)
#define SPI_PIN_CLK GPIO_PIN(P3, 3)
#define SPI_NUMOF ARRAY_SIZE(spi_config)
/** @} */

#ifdef __cplusplus
Expand Down
36 changes: 14 additions & 22 deletions boards/z1/include/periph_conf.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,36 +48,28 @@ static const msp430_clock_params_t clock_params = {
* @name UART configuration
* @{
*/
#define UART_NUMOF (1U)
static const uart_conf_t uart_config[] = {
{
.uart = &usci_a0_as_uart,
},
};

#define UART0_RX_ISR USCIAB0RX_VECTOR /**< RX IRQ vector of UART 0 */

#define UART_BASE (&USCI_A0)
#define UART_IE (IE2)
#define UART_IF (IFG2)
#define UART_IE_RX_BIT (1 << 0)
#define UART_IE_TX_BIT (1 << 1)
#define UART_RX_PORT (&PORT_3)
#define UART_RX_PIN (1 << 5)
#define UART_TX_PORT (&PORT_3)
#define UART_TX_PIN (1 << 4)
#define UART_RX_ISR (USCIAB0RX_VECTOR)
#define UART_TX_ISR (USCIAB0TX_VECTOR)
#define UART_NUMOF ARRAY_SIZE(uart_config)
/** @} */

/**
* @name SPI configuration
* @{
*/
#define SPI_NUMOF (1U)
static const spi_conf_t spi_config[] = {
{
.spi = &usci_b0_as_spi,
},
};

/* SPI configuration */
#define SPI_BASE (&USCI_B0)
#define SPI_IE (IE2)
#define SPI_IF (IFG2)
#define SPI_IE_RX_BIT (1 << 2)
#define SPI_IE_TX_BIT (1 << 3)
#define SPI_PIN_MISO GPIO_PIN(P3, 2)
#define SPI_PIN_MOSI GPIO_PIN(P3, 1)
#define SPI_PIN_CLK GPIO_PIN(P3, 3)
#define SPI_NUMOF ARRAY_SIZE(spi_config)
/** @} */

#ifdef __cplusplus
Expand Down
1 change: 1 addition & 0 deletions cpu/msp430/Makefile.features
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ CPU_CORE = msp430

ifneq (,$(filter msp430f2% msp430g2%,$(CPU_MODEL)))
CPU_FAM := msp430_f2xx_g2xx
FEATURES_PROVIDED += periph_spi_reconfigure
endif

ifneq (,$(filter msp430f1%,$(CPU_MODEL)))
Expand Down
39 changes: 35 additions & 4 deletions cpu/msp430/include/f2xx_g2xx/msp430_regs.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,31 @@
extern "C" {
#endif

/**
* @brief Offset of the USCI B registers in an USCI A peripheral
*
* USCI A peripheral contains the USCI B peripheral registers, but has a few
* USCI A specific register in front. Adding this offset to the USCI A base
* address results in the base address of the shared registers.
*
* @see MSP430_USCI_B_FROM_USCI_A
*/
#define MSP430_USCI_A_B_OFFSET 3U

/**
* @brief "Convert" an USCI A to an USCI B
*
* This returns the pointer to the part of the USCI A registers that matches
* the USCI B register layout, so that an USCI A can be treated as if it is
* an USCI B.
*
* This can be used instead of @ref msp430_usci_b_from_usci_a when needing a
* constant initializer. Otherwise @ref msp430_usci_b_from_usci_a is
* preferred as it includes type checks this macro doesn't.
*/
#define MSP430_USCI_B_FROM_USCI_A(usci_a) \
((msp430_usci_b_t *)((uintptr_t)(usci_a) + MSP430_USCI_A_B_OFFSET))

/**
* @brief Universal Serial Control Interface Type A (USCI_A) Registers
*/
Expand Down Expand Up @@ -74,6 +99,12 @@ typedef struct {
#define UCSSEL_UCLKI UCSSEL_0 /**< Clock USCI using CLKI (n/a in SPI mode) */
#define UCSSEL_ACLK UCSSEL_1 /**< Clock USCI using auxiliary clock */
#define UCSSEL_SMCLK UCSSEL_2 /**< Clock USCI using sub-system master clock */

#if (UCSSEL0 == 0x40) || DOXYGEN
# define UCSSEL_Pos 6 /**< Position of the UCSSEL field in the USCI CTL1 register */
#else
# error "USSEL field in USCI CTL1 register is at unexpected position"
#endif
/** @} */

/**
Expand All @@ -87,12 +118,12 @@ typedef struct {
#define UCBRS_MASK UCBRS_7 /**< Bitmask to retrieve the UCRBS field of the
USCI modulation control register */
#if (UCBRS_7 == 0x0E) || defined(DOXYGEN)
#define UCBRS_POS 1 /**< Position of the UCRBS field in the
# define UCBRS_Pos 1 /**< Position of the UCRBS field in the
UCAxMCTL register */
#else
/* The datasheet for the whole MCU family states the field is in bits 3-1,
* but let's better be safe than sorry here */
#error "UCBRS field in the UCAxMCTL register at unexpected position."
# error "UCBRS field in the UCAxMCTL register at unexpected position."
#endif

/** @} */
Expand Down Expand Up @@ -138,13 +169,13 @@ extern msp430_usci_a_t USCI_A1;
*
* @details Provided by linker
*/
extern msp430_usci_a_t USCI_B0;
extern msp430_usci_b_t USCI_B0;
/**
* @brief USCI_B1 register map
*
* @details Provided by linker
*/
extern msp430_usci_a_t USCI_B1;
extern msp430_usci_b_t USCI_B1;
/** @} */

#ifdef __cplusplus
Expand Down
179 changes: 179 additions & 0 deletions cpu/msp430/include/f2xx_g2xx/periph_cpu.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,185 @@ typedef enum {
#define PERIPH_SPI_NEEDS_TRANSFER_REGS /**< use shared spi_transfer_regs() */
/** @} */

/**
* @brief Identifiers for USCI instances
*
* This assigns the four USCI instances (A0, B0, A1, B1) numbers from 0 to 3.
*/
typedef enum {
#ifdef __MSP430_HAS_USCI_AB0__
MSP430_USCI_ID_A0, /**< USCI A0 */
MSP430_USCI_ID_B0, /**< USCI B0 */
#endif
#ifdef __MSP430_HAS_USCI_AB1__
MSP430_USCI_ID_A1, /**< USCI A1 */
MSP430_USCI_ID_B1, /**< USCI B1 */
#endif
MSP430_USCI_ID_NUMOF /**< Number of USCI IDs (also: number of USCI instances) */
} msp430_usci_id_t;

/**
* @brief MSP430 F2xx/G2xx USCI configuration
*
* @details This is intended to be stored in flash.
*/
typedef struct {
msp430_usci_b_t *dev; /**< The USCI device to use */

REG8 *interrupt_enable; /**< The interrupt enable register matching the USCI */
REG8 *interrupt_flag; /**< The interrupt flag register matching the USCI */
uint8_t tx_irq_mask; /**< The bitmask to enable the TX IRQ for this USCI*/
uint8_t rx_irq_mask; /**< The bitmask to enable the TX IRQ for this USCI */
msp430_usci_id_t id; /**< ID of the USCI */
} msp430_usci_params_t;

/**
* @brief MSP430 F2xx/G2xx USCI clock source
*/
typedef enum {
USCI_CLK_UCLKI = UCSSEL_UCLKI, /**< UCLKI clock source (not supported yet) */
USCI_CLK_AUX = UCSSEL_ACLK, /**< auxiliary clock source */
USCI_CLK_SUBMAIN = UCSSEL_SMCLK, /**< sub-system master clock source */
} msp430_usci_clk_t;

/**
* @brief MSP430 F2xx/G2xx USCI prescaler configuration
*/
typedef struct {
msp430_usci_clk_t clk_source; /**< Clock source to use */
uint8_t br0; /**< What to write in the BR0 register */
uint8_t br1; /**< What to write in the BR1 register */
uint8_t mctl; /**< USCI modulation control register */
} msp430_usci_prescaler_t;

/**
* @brief MSP430 F2xx/G2xx USCI configuration registers
*
* @details Unlike @ref msp430_usci_params_t this contains configuration that
* may depends on runtime settings
*/
typedef struct {
msp430_usci_prescaler_t prescaler; /**< Prescaler configuration */
uint8_t ctl0; /**< USCI control register 0 */
} msp430_usci_conf_t;

/**
* @brief MSP430 F2xx/G2xx UART configuration, CPU level
*
* The MSP430 F2xx/G2xx has two USCI peripherals which both can be operated in
* UART mode. Each is connected to a fixed GPIO for RXD and TXD, respectively.
* Hence, there is not much left for the board to configure anyway, so we just
* prepare UART configurations at CPU level for the board to refer to. The
* unused configuration(s) will be garbage collected by the linker.
*/
typedef struct {
msp430_usci_params_t usci_params; /**< The USCI params */
gpio_t rxd; /**< RXD pin */
gpio_t txd; /**< TXD pin */
} msp430_usci_uart_params_t;

/**
* @brief MSP430 F2xx/G2xx UART configuration, board level
*/
typedef struct {
const msp430_usci_uart_params_t *uart; /**< The UART configuration to use */
} uart_conf_t;

/**
* @brief MSP430 F2xx/G2xx SPI configuration, CPU level
*
* The MSP430 F2xx/G2xx has two USCI peripherals which both can be operated in
* SPI mode. Each is connected to a fixed GPIO for COPI (MOSI), CIPO (MISO),
* and SCK, respectively. Hence, there is not much left for the board to
* configure anyway, so we just prepare UART configurations at CPU level for
* the board to refer to. The unused configuration(s) will be garbage collected
* by the linker.
*/
typedef struct {
msp430_usci_params_t usci_params; /**< The USCI parameters */
gpio_t miso; /**< CIPO (MISO) pin */
gpio_t mosi; /**< COPI (MOSI) pin */
gpio_t sck; /**< SCK pin */
} msp430_usci_spi_params_t;

/**
* @brief MSP430 F2xx/G2xx SPI configuration, board level
*/
typedef struct {
const msp430_usci_spi_params_t *spi; /**< The SPI configuration to use */
} spi_conf_t;

/**
* @brief Acquire and initialize USCI for use a SPI/UART peripheral
*
* @param params Parameter identifying the USCI to use
* @param conf Configuration to initialize the USCI with
*
* @note The USCI will be acquired and configured as specified in @p conf.
* However, it will still be held in software reset and all interrupts
* will be masked and all interrupt flags be cleared.
* @warning You cannot enable IRQs while the USCI is still held under reset.
* @details As currently only for UART USCI IRQs are actually needed, the
* ISR is implemented in the UART driver. If the SPI or I2C driver
* would start to make use of IRQs (other than polling for the IRQ
* flag to be set), the ISRs would need to be moved to the USCI
* driver and call into the UART/SPI/I2C driver, depending on what
* driver has currently acquired the USCI.
*/
void msp430_usci_acquire(const msp430_usci_params_t *params,
const msp430_usci_conf_t *conf);

/**
* @brief Release an USCI, so that it can be used to provide other peripherals
*
* This will also put the USCI in low power mode.
*/
void msp430_usci_release(const msp430_usci_params_t *params);

/**
* @brief Calculate prescaler settings for the given target frequency
*
* @param target_hz The clock frequency (in Hz) to generated with the
* prescaler
*
* @return The calculated prescaler settings
*
* @note This will select the auxiliary clock source for well known UART
* symbol rates up to 9600 Bd, if that is running at 32,768 Hz.
* Otherwise the submain clock source is selected.
*/
msp430_usci_prescaler_t msp430_usci_prescale(uint32_t target_hz);

/**
* @brief MSP430 F2xx/G2xx USCI A0 in UART configuration
*/
extern const msp430_usci_uart_params_t usci_a0_as_uart;

/**
* @brief MSP430 F2xx/G2xx USCI A1 in UART configuration
*/
extern const msp430_usci_uart_params_t usci_a1_as_uart;

/**
* @brief MSP430 F2xx/G2xx USCI A0 in SPI configuration
*/
extern const msp430_usci_spi_params_t usci_a0_as_spi;

/**
* @brief MSP430 F2xx/G2xx USCI A1 in SPI configuration
*/
extern const msp430_usci_spi_params_t usci_a1_as_spi;

/**
* @brief MSP430 F2xx/G2xx USCI B0 in SPI configuration
*/
extern const msp430_usci_spi_params_t usci_b0_as_spi;

/**
* @brief MSP430 F2xx/G2xx USCI B1 in SPI configuration
*/
extern const msp430_usci_spi_params_t usci_b1_as_spi;

#ifdef __cplusplus
}
#endif
Expand Down
3 changes: 2 additions & 1 deletion cpu/msp430/periph/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,13 @@ MODULE = periph
# family it is the (incompatible) USCI.
ifeq (msp430_x1xx,$(CPU_FAM))
SERIAL_IP_BLOCK := usart
SRC += $(SERIAL_IP_BLOCK).c
endif
ifeq (msp430_f2xx_g2xx,$(CPU_FAM))
SERIAL_IP_BLOCK := usci
endif

SRC += $(SERIAL_IP_BLOCK).c

# select family specific peripheral drivers.
ifneq (,$(filter periph_uart,$(USEMODULE)))
SRC += uart_$(SERIAL_IP_BLOCK).c
Expand Down
Loading

0 comments on commit 4b3308c

Please sign in to comment.