diff --git a/bsp/nxp/mcx/mcxa/Libraries/drivers/drv_spi.c b/bsp/nxp/mcx/mcxa/Libraries/drivers/drv_spi.c new file mode 100644 index 0000000000..6f9c5f973a --- /dev/null +++ b/bsp/nxp/mcx/mcxa/Libraries/drivers/drv_spi.c @@ -0,0 +1,206 @@ +/* + * Copyright (c) 2006-2024, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2024-08-1 hywing The first version for MCXA + */ +#include "rtdevice.h" +#include "drv_spi.h" +#include "fsl_common.h" +#include "fsl_lpspi.h" +#include "fsl_lpspi_edma.h" + +#define DMA_MAX_TRANSFER_COUNT (32767) + +enum +{ +#ifdef BSP_USING_SPI0 + SPI0_INDEX +#endif +}; + +struct lpc_spi +{ + struct rt_spi_bus parent; + LPSPI_Type *LPSPIx; + clock_attach_id_t clock_attach_id; + clock_div_name_t clock_div_name; + clock_name_t clock_name; + + DMA_Type *DMAx; + uint8_t tx_dma_chl; + uint8_t rx_dma_chl; + edma_handle_t dma_tx_handle; + edma_handle_t dma_rx_handle; + dma_request_source_t tx_dma_request; + dma_request_source_t rx_dma_request; + lpspi_master_edma_handle_t spi_dma_handle; + + rt_sem_t sem; + char *name; +}; + + +static struct lpc_spi lpc_obj[] = +{ +#ifdef BSP_USING_SPI0 + { + .LPSPIx = LPSPI0, + .clock_attach_id = kFRO12M_to_LPSPI0, + .clock_div_name = kCLOCK_DivLPSPI0, + .clock_name = kCLOCK_Fro12M, + .tx_dma_request = kDma0RequestLPSPI0Tx, + .rx_dma_request = kDma0RequestLPSPI0Rx, + .DMAx = DMA0, + .tx_dma_chl = 0, + .rx_dma_chl = 1, + .name = "spi0", + }, +#endif +}; + +struct lpc_sw_spi_cs +{ + rt_uint32_t pin; +}; + +rt_err_t rt_hw_spi_device_attach(const char *bus_name, const char *device_name, rt_uint32_t pin) +{ + rt_err_t ret = RT_EOK; + + struct rt_spi_device *spi_device = (struct rt_spi_device *)rt_malloc(sizeof(struct rt_spi_device)); + struct lpc_sw_spi_cs *cs_pin = (struct lpc_sw_spi_cs *)rt_malloc(sizeof(struct lpc_sw_spi_cs)); + + cs_pin->pin = pin; + rt_pin_mode(pin, PIN_MODE_OUTPUT); + rt_pin_write(pin, PIN_HIGH); + + ret = rt_spi_bus_attach_device(spi_device, device_name, bus_name, (void *)cs_pin); + + return ret; +} + + +static rt_err_t spi_configure(struct rt_spi_device *device, struct rt_spi_configuration *cfg) +{ + return RT_EOK; +} + + +static void LPSPI_MasterUserCallback(LPSPI_Type *base, lpspi_master_edma_handle_t *handle, status_t status, void *userData) +{ + struct lpc_spi *spi = (struct lpc_spi *)userData; + rt_sem_release(spi->sem); + +} + +static rt_ssize_t spixfer(struct rt_spi_device *device, struct rt_spi_message *message) +{ + int i; + lpspi_transfer_t transfer = {0}; + + RT_ASSERT(device != RT_NULL); + RT_ASSERT(device->bus != RT_NULL); + RT_ASSERT(device->bus->parent.user_data != RT_NULL); + + + struct lpc_spi *spi = (struct lpc_spi *)(device->bus->parent.user_data); + struct lpc_sw_spi_cs *cs = device->parent.user_data; + + if (message->cs_take) + { + rt_pin_write(cs->pin, PIN_LOW); + } + + transfer.dataSize = message->length; + transfer.rxData = (uint8_t *)(message->recv_buf); + transfer.txData = (uint8_t *)(message->send_buf); + + // if(message->length < MAX_DMA_TRANSFER_SIZE) + if (0) + { + LPSPI_MasterTransferBlocking(spi->LPSPIx, &transfer); + } + else + { + uint32_t block, remain; + block = message->length / DMA_MAX_TRANSFER_COUNT; + remain = message->length % DMA_MAX_TRANSFER_COUNT; + + for (i = 0; i < block; i++) + { + transfer.dataSize = DMA_MAX_TRANSFER_COUNT; + if (message->recv_buf) transfer.rxData = (uint8_t *)(message->recv_buf + i * DMA_MAX_TRANSFER_COUNT); + if (message->send_buf) transfer.txData = (uint8_t *)(message->send_buf + i * DMA_MAX_TRANSFER_COUNT); + + LPSPI_MasterTransferEDMA(spi->LPSPIx, &spi->spi_dma_handle, &transfer); + rt_sem_take(spi->sem, RT_WAITING_FOREVER); + } + + if (remain) + { + transfer.dataSize = remain; + if (message->recv_buf) transfer.rxData = (uint8_t *)(message->recv_buf + i * DMA_MAX_TRANSFER_COUNT); + if (message->send_buf) transfer.txData = (uint8_t *)(message->send_buf + i * DMA_MAX_TRANSFER_COUNT); + + LPSPI_MasterTransferEDMA(spi->LPSPIx, &spi->spi_dma_handle, &transfer); + rt_sem_take(spi->sem, RT_WAITING_FOREVER); + } + } + + + if (message->cs_release) + { + rt_pin_write(cs->pin, PIN_HIGH); + } + + return message->length; +} + + + +static struct rt_spi_ops lpc_spi_ops = +{ + .configure = spi_configure, + .xfer = spixfer +}; + + + +int rt_hw_spi_init(void) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(lpc_obj); i++) + { + CLOCK_SetClockDiv(lpc_obj[i].clock_div_name, 1u); + CLOCK_AttachClk(lpc_obj[i].clock_attach_id); + + lpc_obj[i].parent.parent.user_data = &lpc_obj[i]; + lpc_obj[i].sem = rt_sem_create("sem_spi", 0, RT_IPC_FLAG_FIFO); + + lpspi_master_config_t masterConfig; + LPSPI_MasterGetDefaultConfig(&masterConfig); + masterConfig.baudRate = 1 * 1000 * 1000; + masterConfig.pcsToSckDelayInNanoSec = 1000000000U / masterConfig.baudRate * 1U; + masterConfig.lastSckToPcsDelayInNanoSec = 1000000000U / masterConfig.baudRate * 1U; + masterConfig.betweenTransferDelayInNanoSec = 1000000000U / masterConfig.baudRate * 1U; + + LPSPI_MasterInit(lpc_obj[i].LPSPIx, &masterConfig, CLOCK_GetFreq(lpc_obj[i].clock_name)); + + EDMA_CreateHandle(&lpc_obj[i].dma_tx_handle, lpc_obj[i].DMAx, lpc_obj[i].tx_dma_chl); + EDMA_CreateHandle(&lpc_obj[i].dma_rx_handle, lpc_obj[i].DMAx, lpc_obj[i].rx_dma_chl); + + EDMA_SetChannelMux(lpc_obj[i].DMAx, lpc_obj[i].tx_dma_chl, lpc_obj[i].tx_dma_request); + EDMA_SetChannelMux(lpc_obj[i].DMAx, lpc_obj[i].rx_dma_chl, lpc_obj[i].rx_dma_request); + + LPSPI_MasterTransferCreateHandleEDMA(lpc_obj[i].LPSPIx, &lpc_obj[i].spi_dma_handle, LPSPI_MasterUserCallback, &lpc_obj[i], &lpc_obj[i].dma_rx_handle, &lpc_obj[i].dma_tx_handle); + + rt_spi_bus_register(&lpc_obj[i].parent, lpc_obj[i].name, &lpc_spi_ops); + } + return RT_EOK; +} +INIT_DEVICE_EXPORT(rt_hw_spi_init); diff --git a/bsp/nxp/mcx/mcxa/Libraries/drivers/drv_spi.h b/bsp/nxp/mcx/mcxa/Libraries/drivers/drv_spi.h new file mode 100644 index 0000000000..48aa96844a --- /dev/null +++ b/bsp/nxp/mcx/mcxa/Libraries/drivers/drv_spi.h @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2006-2024, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2024-03-22 Jisheng Zhang The first version for mcxn + */ + +#ifndef __DRV_SPI_H__ +#define __DRV_SPI_H__ + +#include + +rt_err_t rt_hw_spi_device_attach(const char *bus_name, const char *device_name, rt_uint32_t pin); + +int rt_hw_spi_init(void); + +#endif /*__DRV_SPI_H__ */ diff --git a/bsp/nxp/mcx/mcxa/frdm-mcxa153/board/Kconfig b/bsp/nxp/mcx/mcxa/frdm-mcxa153/board/Kconfig index 59adb4aaa6..dcb9a8e199 100644 --- a/bsp/nxp/mcx/mcxa/frdm-mcxa153/board/Kconfig +++ b/bsp/nxp/mcx/mcxa/frdm-mcxa153/board/Kconfig @@ -50,16 +50,13 @@ menu "On-chip Peripheral Drivers" config BSP_USING_SPI bool "Enable SPI" select RT_USING_SPI - default y + select BSP_USING_PIN + default n if BSP_USING_SPI - config BSP_USING_SPI3 - bool "Enable Flexcomm3 as SPI" + config BSP_USING_SPI0 + bool "Enable SPI0" default n - - config BSP_USING_SPI8 - bool "Enable Flexcomm8 as High Speed SPI" - default y endif menuconfig BSP_USING_ADC diff --git a/bsp/nxp/mcx/mcxa/frdm-mcxa153/board/MCUX_Config/board/pin_mux.c b/bsp/nxp/mcx/mcxa/frdm-mcxa153/board/MCUX_Config/board/pin_mux.c index d6f6f20b84..5445e8195a 100644 --- a/bsp/nxp/mcx/mcxa/frdm-mcxa153/board/MCUX_Config/board/pin_mux.c +++ b/bsp/nxp/mcx/mcxa/frdm-mcxa153/board/MCUX_Config/board/pin_mux.c @@ -52,7 +52,8 @@ void BOARD_InitPins(void) RESET_ReleasePeripheralReset(kLPUART2_RST_SHIFT_RSTn); RESET_ReleasePeripheralReset(kCTIMER1_RST_SHIFT_RSTn); - + RESET_ReleasePeripheralReset(kLPSPI0_RST_SHIFT_RSTn); + RESET_ReleasePeripheralReset(kPORT0_RST_SHIFT_RSTn); RESET_ReleasePeripheralReset(kPORT1_RST_SHIFT_RSTn); RESET_ReleasePeripheralReset(kPORT2_RST_SHIFT_RSTn); @@ -141,4 +142,106 @@ void BOARD_InitPins(void) /* PORT1_4 (pin 62) is configured as CT1_MAT2 */ PORT_SetPinConfig(PORT1, 4U, &port1_4_pin62_config); #endif + +#ifdef BSP_USING_SPI0 + const port_pin_config_t port1_0_pin56_config = {/* Internal pull-up/down resistor is disabled */ + kPORT_PullDisable, + /* Low internal pull resistor value is selected. */ + kPORT_LowPullResistor, + /* Fast slew rate is configured */ + kPORT_FastSlewRate, + /* Passive input filter is disabled */ + kPORT_PassiveFilterDisable, + /* Open drain output is disabled */ + kPORT_OpenDrainDisable, + /* Low drive strength is configured */ + kPORT_LowDriveStrength, + /* Normal drive strength is configured */ + kPORT_NormalDriveStrength, + /* Pin is configured as LPSPI0_SDO */ + kPORT_MuxAlt2, + /* Digital input enabled */ + kPORT_InputBufferEnable, + /* Digital input is not inverted */ + kPORT_InputNormal, + /* Pin Control Register fields [15:0] are not locked */ + kPORT_UnlockRegister}; + /* PORT1_0 (pin 56) is configured as LPSPI0_SDO */ + PORT_SetPinConfig(PORT1, 0U, &port1_0_pin56_config); + + const port_pin_config_t port1_1_pin57_config = {/* Internal pull-up/down resistor is disabled */ + kPORT_PullDisable, + /* Low internal pull resistor value is selected. */ + kPORT_LowPullResistor, + /* Fast slew rate is configured */ + kPORT_FastSlewRate, + /* Passive input filter is disabled */ + kPORT_PassiveFilterDisable, + /* Open drain output is disabled */ + kPORT_OpenDrainDisable, + /* Low drive strength is configured */ + kPORT_LowDriveStrength, + /* Normal drive strength is configured */ + kPORT_NormalDriveStrength, + /* Pin is configured as LPSPI0_SCK */ + kPORT_MuxAlt2, + /* Digital input enabled */ + kPORT_InputBufferEnable, + /* Digital input is not inverted */ + kPORT_InputNormal, + /* Pin Control Register fields [15:0] are not locked */ + kPORT_UnlockRegister}; + /* PORT1_1 (pin 57) is configured as LPSPI0_SCK */ + PORT_SetPinConfig(PORT1, 1U, &port1_1_pin57_config); + + const port_pin_config_t port1_2_pin58_config = {/* Internal pull-up/down resistor is disabled */ + kPORT_PullDisable, + /* Low internal pull resistor value is selected. */ + kPORT_LowPullResistor, + /* Fast slew rate is configured */ + kPORT_FastSlewRate, + /* Passive input filter is disabled */ + kPORT_PassiveFilterDisable, + /* Open drain output is disabled */ + kPORT_OpenDrainDisable, + /* Low drive strength is configured */ + kPORT_LowDriveStrength, + /* Normal drive strength is configured */ + kPORT_NormalDriveStrength, + /* Pin is configured as LPSPI0_SDI */ + kPORT_MuxAlt2, + /* Digital input enabled */ + kPORT_InputBufferEnable, + /* Digital input is not inverted */ + kPORT_InputNormal, + /* Pin Control Register fields [15:0] are not locked */ + kPORT_UnlockRegister}; + /* PORT1_2 (pin 58) is configured as LPSPI0_SDI */ + PORT_SetPinConfig(PORT1, 2U, &port1_2_pin58_config); + + const port_pin_config_t port1_3_pin59_config = {/* Internal pull-up/down resistor is disabled */ + kPORT_PullDisable, + /* Low internal pull resistor value is selected. */ + kPORT_LowPullResistor, + /* Fast slew rate is configured */ + kPORT_FastSlewRate, + /* Passive input filter is disabled */ + kPORT_PassiveFilterDisable, + /* Open drain output is disabled */ + kPORT_OpenDrainDisable, + /* Low drive strength is configured */ + kPORT_LowDriveStrength, + /* Normal drive strength is configured */ + kPORT_NormalDriveStrength, + /* Pin is configured as LPSPI0_PCS0 */ + kPORT_MuxAlt2, + /* Digital input enabled */ + kPORT_InputBufferEnable, + /* Digital input is not inverted */ + kPORT_InputNormal, + /* Pin Control Register fields [15:0] are not locked */ + kPORT_UnlockRegister}; + /* PORT1_3 (pin 59) is configured as LPSPI0_PCS0 */ + PORT_SetPinConfig(PORT1, 3U, &port1_3_pin59_config); +#endif } diff --git a/bsp/nxp/mcx/mcxa/frdm-mcxa153/board/board.c b/bsp/nxp/mcx/mcxa/frdm-mcxa153/board/board.c index 41b2e58f45..76716f1d4b 100644 --- a/bsp/nxp/mcx/mcxa/frdm-mcxa153/board/board.c +++ b/bsp/nxp/mcx/mcxa/frdm-mcxa153/board/board.c @@ -37,6 +37,10 @@ void SysTick_Handler(void) void rt_hw_board_init() { BOARD_InitBootPins(); + + edma_config_t userConfig = {0}; + EDMA_GetDefaultConfig(&userConfig); + EDMA_Init(DMA0, &userConfig); /* This init has finished in secure side of TF-M */ BOARD_InitBootClocks();