Browse Source

[bsp][nxp][mcxa153] add spi driver

hywing 11 months ago
parent
commit
187ce18695

+ 206 - 0
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);

+ 20 - 0
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 <rtdevice.h>
+
+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__ */

+ 4 - 7
bsp/nxp/mcx/mcxa/frdm-mcxa153/board/Kconfig

@@ -50,16 +50,13 @@ menu "On-chip Peripheral Drivers"
         config BSP_USING_SPI
         config BSP_USING_SPI
             bool "Enable SPI"
             bool "Enable SPI"
             select RT_USING_SPI
             select RT_USING_SPI
-            default y
+            select BSP_USING_PIN
+            default n
 
 
             if BSP_USING_SPI
             if BSP_USING_SPI
-                config BSP_USING_SPI3
-                    bool "Enable Flexcomm3 as SPI"
+                config BSP_USING_SPI0
+                    bool "Enable SPI0"
                     default n
                     default n
-
-                config BSP_USING_SPI8
-                    bool "Enable Flexcomm8 as High Speed SPI"
-                    default y
             endif
             endif
 
 
     menuconfig BSP_USING_ADC
     menuconfig BSP_USING_ADC

+ 104 - 1
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(kLPUART2_RST_SHIFT_RSTn);
 	
 	
 	RESET_ReleasePeripheralReset(kCTIMER1_RST_SHIFT_RSTn);
 	RESET_ReleasePeripheralReset(kCTIMER1_RST_SHIFT_RSTn);
-
+	RESET_ReleasePeripheralReset(kLPSPI0_RST_SHIFT_RSTn);
+	
     RESET_ReleasePeripheralReset(kPORT0_RST_SHIFT_RSTn);
     RESET_ReleasePeripheralReset(kPORT0_RST_SHIFT_RSTn);
     RESET_ReleasePeripheralReset(kPORT1_RST_SHIFT_RSTn);
     RESET_ReleasePeripheralReset(kPORT1_RST_SHIFT_RSTn);
     RESET_ReleasePeripheralReset(kPORT2_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 */
     /* PORT1_4 (pin 62) is configured as CT1_MAT2 */
     PORT_SetPinConfig(PORT1, 4U, &port1_4_pin62_config);
     PORT_SetPinConfig(PORT1, 4U, &port1_4_pin62_config);
 #endif
 #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
 }
 }

+ 4 - 0
bsp/nxp/mcx/mcxa/frdm-mcxa153/board/board.c

@@ -37,6 +37,10 @@ void SysTick_Handler(void)
 void rt_hw_board_init()
 void rt_hw_board_init()
 {
 {
     BOARD_InitBootPins();
     BOARD_InitBootPins();
+	
+	edma_config_t userConfig = {0};
+    EDMA_GetDefaultConfig(&userConfig);
+    EDMA_Init(DMA0, &userConfig);
 
 
     /* This init has finished in secure side of TF-M  */
     /* This init has finished in secure side of TF-M  */
     BOARD_InitBootClocks();
     BOARD_InitBootClocks();