Skip to content
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

cpu/msp430/f2xx: clean up periph_uart,periph_spi #20357

Merged
merged 2 commits into from
Mar 28, 2024
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
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
Loading