123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681 |
- /**************************************************************************//**
- *
- * @copyright (C) 2020 Nuvoton Technology Corp. All rights reserved.
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Change Logs:
- * Date Author Notes
- * 2020-3-31 Philo First version
- *
- ******************************************************************************/
- #include <rtconfig.h>
- #if defined(BSP_USING_USPI)
- #define LOG_TAG "drv.uspi"
- #define DBG_ENABLE
- #define DBG_SECTION_NAME LOG_TAG
- #define DBG_LEVEL DBG_INFO
- #define DBG_COLOR
- #include <rtdbg.h>
- #include <rthw.h>
- #include <rtdevice.h>
- #include <rtdef.h>
- #include "NuMicro.h"
- #include <nu_bitutil.h>
- #if defined(BSP_USING_USPI_PDMA)
- #include <drv_pdma.h>
- #endif
- /* Private define ---------------------------------------------------------------*/
- #ifndef NU_SPI_USE_PDMA_MIN_THRESHOLD
- #define NU_SPI_USE_PDMA_MIN_THRESHOLD (128)
- #endif
- enum
- {
- USPI_START = -1,
- #if defined(BSP_USING_USPI0)
- USPI0_IDX,
- #endif
- #if defined(BSP_USING_USPI1)
- USPI1_IDX,
- #endif
- USPI_CNT
- };
- /* Private typedef --------------------------------------------------------------*/
- struct nu_uspi
- {
- struct rt_spi_bus dev;
- char *name;
- USPI_T *uspi_base;
- struct rt_spi_configuration configuration;
- uint32_t dummy;
- #if defined(BSP_USING_USPI_PDMA)
- int16_t pdma_perp_tx;
- int8_t pdma_chanid_tx;
- int16_t pdma_perp_rx;
- int8_t pdma_chanid_rx;
- rt_sem_t m_psSemBus;
- #endif
- };
- typedef struct nu_uspi *uspi_t;
- /* Private functions ------------------------------------------------------------*/
- static rt_err_t nu_uspi_bus_configure(struct rt_spi_device *device, struct rt_spi_configuration *configuration);
- static rt_uint32_t nu_uspi_bus_xfer(struct rt_spi_device *device, struct rt_spi_message *message);
- static void nu_uspi_transmission_with_poll(struct nu_uspi *uspi_bus,
- uint8_t *send_addr, uint8_t *recv_addr, int length, uint8_t bytes_per_word);
- static int nu_uspi_register_bus(struct nu_uspi *uspi_bus, const char *name);
- static void nu_uspi_drain_rxfifo(USPI_T *uspi_base);
- #if defined(BSP_USING_USPI_PDMA)
- static void nu_pdma_uspi_rx_cb(void *pvUserData, uint32_t u32EventFilter);
- static rt_err_t nu_pdma_uspi_rx_config(struct nu_uspi *uspi_bus, uint8_t *pu8Buf, int32_t i32RcvLen, uint8_t bytes_per_word);
- static rt_err_t nu_pdma_uspi_tx_config(struct nu_uspi *uspi_bus, const uint8_t *pu8Buf, int32_t i32SndLen, uint8_t bytes_per_word);
- static rt_size_t nu_uspi_pdma_transmit(struct nu_uspi *uspi_bus, const uint8_t *send_addr, uint8_t *recv_addr, int length, uint8_t bytes_per_word);
- static rt_err_t nu_hw_uspi_pdma_allocate(struct nu_uspi *uspi_bus);
- #endif
- /* Public functions -------------------------------------------------------------*/
- /* Private variables ------------------------------------------------------------*/
- static struct rt_spi_ops nu_uspi_poll_ops =
- {
- .configure = nu_uspi_bus_configure,
- .xfer = nu_uspi_bus_xfer,
- };
- static struct nu_uspi nu_uspi_arr [] =
- {
- #if defined(BSP_USING_USPI0)
- {
- .name = "uspi0",
- .uspi_base = USPI0,
- #if defined(BSP_USING_USPI_PDMA)
- #if defined(BSP_USING_USPI0_PDMA)
- .pdma_perp_tx = PDMA_USCI0_TX,
- .pdma_perp_rx = PDMA_USCI0_RX,
- #else
- .pdma_perp_tx = NU_PDMA_UNUSED,
- .pdma_perp_rx = NU_PDMA_UNUSED,
- #endif //BSP_USING_USPI0_PDMA
- #endif //BSP_USING_USPI_PDMA
- },
- #endif
- #if defined(BSP_USING_USPI1)
- {
- .name = "uspi1",
- .uspi_base = USPI1,
- #if defined(BSP_USING_USPI_PDMA)
- #if defined(BSP_USING_USPI1_PDMA)
- .pdma_perp_tx = PDMA_USCI1_TX,
- .pdma_perp_rx = PDMA_USCI1_RX,
- #else
- .pdma_perp_tx = NU_PDMA_UNUSED,
- .pdma_perp_rx = NU_PDMA_UNUSED,
- #endif //BSP_USING_USPI1_PDMA
- #endif //BSP_USING_USPI_PDMA
- },
- #endif
- {0}
- }; /* uspi nu_uspi */
- static rt_err_t nu_uspi_bus_configure(struct rt_spi_device *device,
- struct rt_spi_configuration *configuration)
- {
- struct nu_uspi *uspi_bus;
- uint32_t u32SPIMode;
- uint32_t u32BusClock;
- rt_err_t ret = RT_EOK;
- void *pvUserData;
- RT_ASSERT(device != RT_NULL);
- RT_ASSERT(configuration != RT_NULL);
- uspi_bus = (struct nu_uspi *) device->bus;
- pvUserData = device->parent.user_data;
- /* Check mode */
- switch (configuration->mode & RT_SPI_MODE_3)
- {
- case RT_SPI_MODE_0:
- u32SPIMode = USPI_MODE_0;
- break;
- case RT_SPI_MODE_1:
- u32SPIMode = USPI_MODE_1;
- break;
- case RT_SPI_MODE_2:
- u32SPIMode = USPI_MODE_2;
- break;
- case RT_SPI_MODE_3:
- u32SPIMode = USPI_MODE_3;
- break;
- default:
- ret = RT_EIO;
- goto exit_nu_uspi_bus_configure;
- }
- /* Check data width */
- if (!(configuration->data_width == 8 ||
- configuration->data_width == 16))
- {
- ret = RT_EINVAL;
- goto exit_nu_uspi_bus_configure;
- }
- /* Try to set clock and get actual uspi bus clock */
- u32BusClock = USPI_SetBusClock(uspi_bus->uspi_base, configuration->max_hz);
- if (configuration->max_hz > u32BusClock)
- {
- LOG_W("%s clock max frequency is %dHz (!= %dHz)\n", uspi_bus->name, u32BusClock, configuration->max_hz);
- configuration->max_hz = u32BusClock;
- }
- /* Need to initialize new configuration? */
- if (rt_memcmp(configuration, &uspi_bus->configuration, sizeof(*configuration)) != 0)
- {
- rt_memcpy(&uspi_bus->configuration, configuration, sizeof(*configuration));
- USPI_Open(uspi_bus->uspi_base, USPI_MASTER, u32SPIMode, configuration->data_width, u32BusClock);
- if (configuration->mode & RT_SPI_CS_HIGH)
- {
- /* Set CS pin to LOW */
- if (pvUserData != RT_NULL)
- {
- // set to LOW */
- rt_pin_write(*((rt_base_t *)pvUserData), PIN_LOW);
- }
- else
- {
- USPI_SET_SS_LOW(uspi_bus->uspi_base);
- }
- }
- else
- {
- /* Set CS pin to HIGH */
- if (pvUserData != RT_NULL)
- {
- // set to HIGH */
- rt_pin_write(*((rt_base_t *)pvUserData), PIN_HIGH);
- }
- else
- {
- /* Set CS pin to HIGH */
- USPI_SET_SS_HIGH(uspi_bus->uspi_base);
- }
- }
- if (configuration->mode & RT_SPI_MSB)
- {
- /* Set sequence to MSB first */
- USPI_SET_MSB_FIRST(uspi_bus->uspi_base);
- }
- else
- {
- /* Set sequence to LSB first */
- USPI_SET_LSB_FIRST(uspi_bus->uspi_base);
- }
- }
- /* Clear USPI RX FIFO */
- nu_uspi_drain_rxfifo(uspi_bus->uspi_base);
- exit_nu_uspi_bus_configure:
- return -(ret);
- }
- #if defined(BSP_USING_USPI_PDMA)
- static void nu_pdma_uspi_rx_cb(void *pvUserData, uint32_t u32EventFilter)
- {
- rt_err_t result;
- struct nu_uspi *uspi_bus = (struct nu_uspi *)pvUserData;
- RT_ASSERT(uspi_bus != RT_NULL);
- result = rt_sem_release(uspi_bus->m_psSemBus);
- RT_ASSERT(result == RT_EOK);
- }
- static rt_err_t nu_pdma_uspi_rx_config(struct nu_uspi *uspi_bus, uint8_t *pu8Buf, int32_t i32RcvLen, uint8_t bytes_per_word)
- {
- rt_err_t result;
- rt_uint8_t *dst_addr = NULL;
- nu_pdma_memctrl_t memctrl = eMemCtl_Undefined;
- /* Get base address of uspi register */
- USPI_T *uspi_base = uspi_bus->uspi_base;
- rt_uint8_t uspi_pdma_rx_chid = uspi_bus->pdma_chanid_rx;
- result = nu_pdma_callback_register(uspi_pdma_rx_chid,
- nu_pdma_uspi_rx_cb,
- (void *)uspi_bus,
- NU_PDMA_EVENT_TRANSFER_DONE);
- if (result != RT_EOK)
- {
- goto exit_nu_pdma_uspi_rx_config;
- }
- if (pu8Buf == RT_NULL)
- {
- memctrl = eMemCtl_SrcFix_DstFix;
- dst_addr = (rt_uint8_t *) &uspi_bus->dummy;
- }
- else
- {
- memctrl = eMemCtl_SrcFix_DstInc;
- dst_addr = pu8Buf;
- }
- result = nu_pdma_channel_memctrl_set(uspi_pdma_rx_chid, memctrl);
- if (result != RT_EOK)
- {
- goto exit_nu_pdma_uspi_rx_config;
- }
- result = nu_pdma_transfer(uspi_pdma_rx_chid,
- bytes_per_word * 8,
- (uint32_t)&uspi_base->RXDAT,
- (uint32_t)dst_addr,
- i32RcvLen / bytes_per_word,
- 0);
- exit_nu_pdma_uspi_rx_config:
- return result;
- }
- static rt_err_t nu_pdma_uspi_tx_config(struct nu_uspi *uspi_bus, const uint8_t *pu8Buf, int32_t i32SndLen, uint8_t bytes_per_word)
- {
- rt_err_t result;
- rt_uint8_t *src_addr = NULL;
- nu_pdma_memctrl_t memctrl = eMemCtl_Undefined;
- /* Get base address of uspi register */
- USPI_T *uspi_base = uspi_bus->uspi_base;
- rt_uint8_t uspi_pdma_tx_chid = uspi_bus->pdma_chanid_tx;
- if (pu8Buf == RT_NULL)
- {
- uspi_bus->dummy = 0;
- memctrl = eMemCtl_SrcFix_DstFix;
- src_addr = (rt_uint8_t *)&uspi_bus->dummy;
- }
- else
- {
- memctrl = eMemCtl_SrcInc_DstFix;
- src_addr = (rt_uint8_t *)pu8Buf;
- }
- result = nu_pdma_channel_memctrl_set(uspi_pdma_tx_chid, memctrl);
- if (result != RT_EOK)
- {
- goto exit_nu_pdma_uspi_tx_config;
- }
- result = nu_pdma_transfer(uspi_pdma_tx_chid,
- bytes_per_word * 8,
- (uint32_t)src_addr,
- (uint32_t)&uspi_base->TXDAT,
- i32SndLen / bytes_per_word,
- 0);
- exit_nu_pdma_uspi_tx_config:
- return result;
- }
- /**
- * USPI PDMA transfer
- **/
- static rt_size_t nu_uspi_pdma_transmit(struct nu_uspi *uspi_bus, const uint8_t *send_addr, uint8_t *recv_addr, int length, uint8_t bytes_per_word)
- {
- rt_err_t result = RT_EOK;
- rt_uint32_t u32Offset = 0;
- rt_uint32_t u32TransferCnt = length / bytes_per_word;
- rt_uint32_t u32TxCnt = 0;
- /* Get base address of uspi register */
- USPI_T *uspi_base = uspi_bus->uspi_base;
- do
- {
- u32TxCnt = (u32TransferCnt > NU_PDMA_MAX_TXCNT) ? NU_PDMA_MAX_TXCNT : u32TransferCnt;
- result = nu_pdma_uspi_rx_config(uspi_bus, (recv_addr == RT_NULL) ? recv_addr : &recv_addr[u32Offset], (u32TxCnt * bytes_per_word), bytes_per_word);
- RT_ASSERT(result == RT_EOK);
- result = nu_pdma_uspi_tx_config(uspi_bus, (send_addr == RT_NULL) ? send_addr : &send_addr[u32Offset], (u32TxCnt * bytes_per_word), bytes_per_word);
- RT_ASSERT(result == RT_EOK);
- /* Trigger TX/RX PDMA transfer. */
- USPI_TRIGGER_TX_RX_PDMA(uspi_base);
- /* Wait RX-PDMA transfer done */
- result = rt_sem_take(uspi_bus->m_psSemBus, RT_WAITING_FOREVER);
- RT_ASSERT(result == RT_EOK);
- /* Stop TX/RX DMA transfer. */
- USPI_DISABLE_TX_RX_PDMA(uspi_base);
- u32TransferCnt -= u32TxCnt;
- u32Offset += u32TxCnt;
- }
- while (u32TransferCnt > 0);
- return length;
- }
- static rt_err_t nu_hw_uspi_pdma_allocate(struct nu_uspi *uspi_bus)
- {
- /* Allocate USPI_TX nu_dma channel */
- if ((uspi_bus->pdma_chanid_tx = nu_pdma_channel_allocate(uspi_bus->pdma_perp_tx)) < 0)
- {
- goto exit_nu_hw_uspi_pdma_allocate;
- }
- /* Allocate USPI_RX nu_dma channel */
- else if ((uspi_bus->pdma_chanid_rx = nu_pdma_channel_allocate(uspi_bus->pdma_perp_rx)) < 0)
- {
- nu_pdma_channel_free(uspi_bus->pdma_chanid_tx);
- goto exit_nu_hw_uspi_pdma_allocate;
- }
- uspi_bus->m_psSemBus = rt_sem_create("uspibus_sem", 0, RT_IPC_FLAG_FIFO);
- RT_ASSERT(uspi_bus->m_psSemBus != RT_NULL);
- return RT_EOK;
- exit_nu_hw_uspi_pdma_allocate:
- return -(RT_ERROR);
- }
- #endif
- static void nu_uspi_drain_rxfifo(USPI_T *uspi_base)
- {
- while (USPI_IS_BUSY(uspi_base));
- // Drain USPI RX FIFO, make sure RX FIFO is empty
- while (!USPI_GET_RX_EMPTY_FLAG(uspi_base))
- {
- USPI_ClearRxBuf(uspi_base);
- }
- }
- static int nu_uspi_read(USPI_T *uspi_base, uint8_t *recv_addr, uint8_t bytes_per_word)
- {
- int size = 0;
- // Read RX data
- if (!USPI_GET_RX_EMPTY_FLAG(uspi_base))
- {
- uint32_t val;
- // Read data from USPI RX FIFO
- switch (bytes_per_word)
- {
- case 2:
- val = USPI_READ_RX(uspi_base);
- nu_set16_le(recv_addr, val);
- break;
- case 1:
- *recv_addr = USPI_READ_RX(uspi_base);
- break;
- default:
- LOG_E("Data length is not supported.\n");
- break;
- }
- size = bytes_per_word;
- }
- return size;
- }
- static int nu_uspi_write(USPI_T *uspi_base, const uint8_t *send_addr, uint8_t bytes_per_word)
- {
- // Wait USPI TX send data
- while (USPI_GET_TX_FULL_FLAG(uspi_base));
- // Input data to USPI TX
- switch (bytes_per_word)
- {
- case 2:
- USPI_WRITE_TX(uspi_base, nu_get16_le(send_addr));
- break;
- case 1:
- USPI_WRITE_TX(uspi_base, *((uint8_t *)send_addr));
- break;
- default:
- LOG_E("Data length is not supported.\n");
- break;
- }
- return bytes_per_word;
- }
- /**
- * @brief USPI bus polling
- * @param dev : The pointer of the specified USPI module.
- * @param send_addr : Source address
- * @param recv_addr : Destination address
- * @param length : Data length
- */
- static void nu_uspi_transmission_with_poll(struct nu_uspi *uspi_bus,
- uint8_t *send_addr, uint8_t *recv_addr, int length, uint8_t bytes_per_word)
- {
- USPI_T *uspi_base = uspi_bus->uspi_base;
- // Write-only
- if ((send_addr != RT_NULL) && (recv_addr == RT_NULL))
- {
- while (length > 0)
- {
- send_addr += nu_uspi_write(uspi_base, send_addr, bytes_per_word);
- length -= bytes_per_word;
- }
- } // if (send_addr != RT_NULL && recv_addr == RT_NULL)
- // Read-only
- else if ((send_addr == RT_NULL) && (recv_addr != RT_NULL))
- {
- uspi_bus->dummy = 0;
- while (length > 0)
- {
- /* Input data to USPI TX FIFO */
- length -= nu_uspi_write(uspi_base, (const uint8_t *)&uspi_bus->dummy, bytes_per_word);
- /* Read data from USPI RX FIFO */
- while (USPI_GET_RX_EMPTY_FLAG(uspi_base));
- recv_addr += nu_uspi_read(uspi_base, recv_addr, bytes_per_word);
- }
- } // else if (send_addr == RT_NULL && recv_addr != RT_NULL)
- // Read&Write
- else
- {
- while (length > 0)
- {
- /* Input data to USPI TX FIFO */
- send_addr += nu_uspi_write(uspi_base, send_addr, bytes_per_word);
- length -= bytes_per_word;
- /* Read data from USPI RX FIFO */
- while (USPI_GET_RX_EMPTY_FLAG(uspi_base));
- recv_addr += nu_uspi_read(uspi_base, recv_addr, bytes_per_word);
- }
- } // else
- /* Wait USPI RX or drain USPI RX-FIFO */
- if (recv_addr)
- {
- // Wait USPI transmission done
- while (USPI_IS_BUSY(uspi_base))
- {
- while (!USPI_GET_RX_EMPTY_FLAG(uspi_base))
- {
- recv_addr += nu_uspi_read(uspi_base, recv_addr, bytes_per_word);
- }
- }
- while (!USPI_GET_RX_EMPTY_FLAG(uspi_base))
- {
- recv_addr += nu_uspi_read(uspi_base, recv_addr, bytes_per_word);
- }
- }
- else
- {
- /* Clear USPI RX FIFO */
- nu_uspi_drain_rxfifo(uspi_base);
- }
- }
- static void nu_uspi_transfer(struct nu_uspi *uspi_bus, uint8_t *tx, uint8_t *rx, int length, uint8_t bytes_per_word)
- {
- RT_ASSERT(uspi_bus != RT_NULL);
- #if defined(BSP_USING_USPI_PDMA)
- /* PDMA transfer constrains */
- if ((uspi_bus->pdma_chanid_rx >= 0) &&
- !((uint32_t)tx % bytes_per_word) &&
- !((uint32_t)rx % bytes_per_word) &&
- (length >= NU_SPI_USE_PDMA_MIN_THRESHOLD))
- nu_uspi_pdma_transmit(uspi_bus, tx, rx, length, bytes_per_word);
- else
- nu_uspi_transmission_with_poll(uspi_bus, tx, rx, length, bytes_per_word);
- #else
- nu_uspi_transmission_with_poll(uspi_bus, tx, rx, length, bytes_per_word);
- #endif
- }
- static rt_uint32_t nu_uspi_bus_xfer(struct rt_spi_device *device, struct rt_spi_message *message)
- {
- struct nu_uspi *uspi_bus;
- struct rt_spi_configuration *configuration;
- uint8_t bytes_per_word;
- void *pvUserData;
- RT_ASSERT(device != RT_NULL);
- RT_ASSERT(device->bus != RT_NULL);
- RT_ASSERT(message != RT_NULL);
- uspi_bus = (struct nu_uspi *) device->bus;
- configuration = &uspi_bus->configuration;
- bytes_per_word = configuration->data_width / 8;
- pvUserData = device->parent.user_data;
- if ((message->length % bytes_per_word) != 0)
- {
- /* Say bye. */
- LOG_E("%s: error payload length(%d%%%d != 0).\n", uspi_bus->name, message->length, bytes_per_word);
- return 0;
- }
- if (message->length > 0)
- {
- if (message->cs_take && !(configuration->mode & RT_SPI_NO_CS))
- {
- if (pvUserData != RT_NULL)
- {
- if (configuration->mode & RT_SPI_CS_HIGH)
- {
- // set to HIGH */
- rt_pin_write(*((rt_base_t *)pvUserData), PIN_HIGH);
- }
- else
- {
- // set to LOW */
- rt_pin_write(*((rt_base_t *)pvUserData), PIN_LOW);
- }
- }
- else
- {
- if (configuration->mode & RT_SPI_CS_HIGH)
- {
- USPI_SET_SS_HIGH(uspi_bus->uspi_base);
- }
- else
- {
- USPI_SET_SS_LOW(uspi_bus->uspi_base);
- }
- }
- }
- nu_uspi_transfer(uspi_bus, (uint8_t *)message->send_buf, (uint8_t *)message->recv_buf, message->length, bytes_per_word);
- if (message->cs_release && !(configuration->mode & RT_SPI_NO_CS))
- {
- if (pvUserData != RT_NULL)
- {
- if (configuration->mode & RT_SPI_CS_HIGH)
- {
- // set to LOW */
- rt_pin_write(*((rt_base_t *)pvUserData), PIN_LOW);
- }
- else
- {
- // set to HIGH */
- rt_pin_write(*((rt_base_t *)pvUserData), PIN_HIGH);
- }
- }
- else
- {
- if (configuration->mode & RT_SPI_CS_HIGH)
- {
- USPI_SET_SS_LOW(uspi_bus->uspi_base);
- }
- else
- {
- USPI_SET_SS_HIGH(uspi_bus->uspi_base);
- }
- }
- }
- }
- return message->length;
- }
- static int nu_uspi_register_bus(struct nu_uspi *uspi_bus, const char *name)
- {
- return rt_spi_bus_register(&uspi_bus->dev, name, &nu_uspi_poll_ops);
- }
- /**
- * Hardware USPI Initial
- */
- static int rt_hw_uspi_init(void)
- {
- int i;
- for (i = (USPI_START + 1); i < USPI_CNT; i++)
- {
- nu_uspi_register_bus(&nu_uspi_arr[i], nu_uspi_arr[i].name);
- #if defined(BSP_USING_USPI_PDMA)
- nu_uspi_arr[i].pdma_chanid_tx = -1;
- nu_uspi_arr[i].pdma_chanid_rx = -1;
- if ((nu_uspi_arr[i].pdma_perp_tx != NU_PDMA_UNUSED) && (nu_uspi_arr[i].pdma_perp_rx != NU_PDMA_UNUSED))
- {
- if (nu_hw_uspi_pdma_allocate(&nu_uspi_arr[i]) != RT_EOK)
- {
- LOG_E("Failed to allocate DMA channels for %s. We will use poll-mode for this bus.\n", nu_uspi_arr[i].name);
- }
- }
- #endif
- }
- return 0;
- }
- INIT_DEVICE_EXPORT(rt_hw_uspi_init);
- #endif //#if defined(BSP_USING_USPI)
|