mirror of
https://github.com/RT-Thread/rt-thread.git
synced 2026-10-01 08:27:30 +08:00
[bsp][n32] n32hxxx: bound the XSPI waits and fix I2C/SPI/NAND edge cases
- qspi: both XSPI variants poll the status flags with no bound, so an unresponsive bus hangs the caller and silently defeats the timeout it passed in. Route every wait through the timeout-carrying helpers, return -RT_ETIMEOUT and disable the controller on failure, and replace the "poll then send" loops with one bounded wait per element. - hard_i2c: the interrupt receive path programs the BYTENUM window once and never reloads it, so a longer message was truncated and still reported as success; refuse it with -RT_EINVAL (enable RX DMA for longer reads) instead of capping XferSize. Stop capping the transmit byte count at the window size as well: BYTENUM counts received bytes only, and the cap stopped feeding DAT after byte 255 while TXDATE stayed asserted. Reject RT_I2C_NO_START/RT_I2C_NO_STOP on the series without frame chaining, where they would silently become a fresh START and a STOP, and tear the DMA channel down when the address phase times out instead of leaving it armed against a buffer about to unwind. - spi: the H7xx LLI chain advanced the memory side by SPI_DMA_BLOCK_MAX bytes although BlkTfrSize counts elements, so a 16-bit transfer walked half a word early per node; advance by elements and scale both the chunk offset and the staging buffer by the data width. Propagate the DMA arm failure that was ignored. - nand: an odd data length has no halfword-only encoding on the 16-bit bus and padding would program a byte the caller never asked for, so refuse it before the command phase; issue the empty-page dummy store as a halfword there too, where 8-bit AHB writes are unsupported. - Kconfig: gate the Ethernet/SDRAM/LCD/QSPI/NAND options behind BSP_PERIPH_PIN_CFG_READY on all three boards. The peripheral clock and IO are not configured for these boards yet, so selecting one of them builds a driver whose pins stay in the reset function.
This commit is contained in:
@@ -626,6 +626,24 @@ static rt_err_t n32_i2c_master_seq_receive_it(struct n32_i2c *i2c, uint16_t DevA
|
||||
|
||||
if (i2c->transfer.state == I2C_READY)
|
||||
{
|
||||
/* A master receive fits in a single BYTENUM window: the counter is
|
||||
* loaded once below and this path never reloads it, so the BSF
|
||||
* completion ends the transfer after that many bytes. A longer message
|
||||
* would be silently truncated yet still reported as success; refuse it
|
||||
* instead. BYTENUM is 8 bits (the SDK's own setter takes a uint8_t), so
|
||||
* the count cannot be widened either. Only the DMA path reloads the
|
||||
* window as it drains.
|
||||
*
|
||||
* n32_i2c_master_xfer screens the same condition before dispatching, so
|
||||
* the caller gets an errno; this check keeps the invariant stated where
|
||||
* the window is actually programmed.
|
||||
*/
|
||||
if (Size > MAX_NBYTE_SIZE)
|
||||
{
|
||||
LOG_E("I2C IT receive of %u bytes exceeds the %u-byte BYTENUM window, enable RX DMA for longer reads", (unsigned int)Size, (unsigned int)MAX_NBYTE_SIZE);
|
||||
return -RT_EINVAL;
|
||||
}
|
||||
|
||||
/* Set transfer parameters */
|
||||
i2c->transfer.state = I2C_BUSY_RX;
|
||||
i2c->transfer.pBuffPtr = pData;
|
||||
@@ -633,16 +651,8 @@ static rt_err_t n32_i2c_master_seq_receive_it(struct n32_i2c *i2c, uint16_t DevA
|
||||
i2c->transfer.XferOptions = XferOptions;
|
||||
i2c->i2c_isr_callback = i2c_master_ev_isr_handler_it;
|
||||
|
||||
/* If Size > MAX_NBYTE_SIZE, use reload mode */
|
||||
if (Size > MAX_NBYTE_SIZE)
|
||||
{
|
||||
i2c->transfer.XferSize = MAX_NBYTE_SIZE;
|
||||
}
|
||||
else
|
||||
{
|
||||
i2c->transfer.XferSize = i2c->transfer.XferCount;
|
||||
}
|
||||
|
||||
/* One window covers the whole transfer - see the size check above */
|
||||
i2c->transfer.XferSize = i2c->transfer.XferCount;
|
||||
|
||||
#if defined(SOC_SERIES_N32H49x)
|
||||
I2C_EnableByteNum(i2c->config->Instance, ENABLE);
|
||||
@@ -769,15 +779,14 @@ static rt_err_t n32_i2c_master_seq_send_it(struct n32_i2c *i2c, uint16_t DevAddr
|
||||
i2c->transfer.XferOptions = XferOptions;
|
||||
i2c->i2c_isr_callback = i2c_master_ev_isr_handler_it;
|
||||
|
||||
/* If Size > MAX_NBYTE_SIZE, use reload mode */
|
||||
if (Size > MAX_NBYTE_SIZE)
|
||||
{
|
||||
i2c->transfer.XferSize = MAX_NBYTE_SIZE;
|
||||
}
|
||||
else
|
||||
{
|
||||
i2c->transfer.XferSize = i2c->transfer.XferCount;
|
||||
}
|
||||
/* No 255-byte window here: BYTENUM counts received bytes only, and this
|
||||
* ISR feeds DAT one byte per TXDATE interrupt, so XferSize is nothing
|
||||
* more than the remaining byte count. Capping it at MAX_NBYTE_SIZE made
|
||||
* the TXDATE branch stop feeding after the 255th byte of a longer
|
||||
* message - the tail was never sent while TXDATE stayed asserted and
|
||||
* stormed this handler until the caller timed out.
|
||||
*/
|
||||
i2c->transfer.XferSize = i2c->transfer.XferCount;
|
||||
|
||||
/* Wait for the previous STOP to complete. Toggling PE here would not
|
||||
* reset the state machine while BUSY is set, and could hold the lines.
|
||||
@@ -904,7 +913,14 @@ static rt_err_t n32_i2c_master_seq_receive_dma(struct n32_i2c *i2c, uint16_t Dev
|
||||
rt_err_t start_ret = n32_i2c_master_start_addr(i2c, (uint8_t)DevAddress, I2C_DIRECTION_RECV);
|
||||
if (start_ret != RT_EOK)
|
||||
{
|
||||
i2c->transfer.state = I2C_READY;
|
||||
/* The DMA request and the BUF/ERR interrupts are armed by
|
||||
* now and the DMA channel still targets the caller's
|
||||
* buffer, so resetting only the state would let a late
|
||||
* byte write through a stack frame that is about to
|
||||
* unwind. The timeout paths of n32_i2c_master_start_addr
|
||||
* raise no error interrupt that could tear this down, so
|
||||
* do it here. */
|
||||
I2C_ABORT_ON_TIMEOUT(i2c);
|
||||
return start_ret;
|
||||
}
|
||||
}
|
||||
@@ -1010,7 +1026,14 @@ static rt_err_t n32_i2c_master_seq_send_dma(struct n32_i2c *i2c, uint16_t DevAdd
|
||||
rt_err_t start_ret = n32_i2c_master_start_addr(i2c, (uint8_t)DevAddress, I2C_DIRECTION_SEND);
|
||||
if (start_ret != RT_EOK)
|
||||
{
|
||||
i2c->transfer.state = I2C_READY;
|
||||
/* The DMA request and the BUF/ERR interrupts are armed by
|
||||
* now and the DMA channel still targets the caller's
|
||||
* buffer, so resetting only the state would let a late
|
||||
* byte write through a stack frame that is about to
|
||||
* unwind. The timeout paths of n32_i2c_master_start_addr
|
||||
* raise no error interrupt that could tear this down, so
|
||||
* do it here. */
|
||||
I2C_ABORT_ON_TIMEOUT(i2c);
|
||||
return start_ret;
|
||||
}
|
||||
}
|
||||
@@ -1075,6 +1098,51 @@ static rt_ssize_t n32_i2c_master_xfer(struct rt_i2c_bus_device *bus,
|
||||
i2c_obj = rt_container_of(bus, struct n32_i2c, i2c_bus);
|
||||
completion = &i2c_obj->completion;
|
||||
|
||||
#if defined(SOC_SERIES_N32H49x) || defined(SOC_SERIES_N32H47x_48x)
|
||||
/* This series cannot chain frames, so neither flag can be honoured. The
|
||||
* mode constants the translate step below derives from them are all
|
||||
* 0x00000000U on this series (see the definitions at the top of this file),
|
||||
* so XferOptions is always zero here and changes nothing in the CTRL2
|
||||
* write. Every message instead re-runs the START + 7-bit address sequence
|
||||
* in its own per-message setup, and completion always ends in a STOP
|
||||
* (STOPGEN in i2c_it_completion_done, or the BYTENUM auto-stop on the DMA
|
||||
* receive). A caller asking for RT_I2C_NO_START or RT_I2C_NO_STOP would
|
||||
* therefore silently get a fresh START and a STOP instead of a repeated
|
||||
* start -- a different bus transaction than the one requested, which some
|
||||
* slaves reject. Refuse it rather than change it behind the caller's back;
|
||||
* a repeated-start sequence needs the frame chaining this controller
|
||||
* lacks.
|
||||
*/
|
||||
for (i = 0; i < num; i++)
|
||||
{
|
||||
if (msgs[i].flags & (RT_I2C_NO_START | RT_I2C_NO_STOP))
|
||||
{
|
||||
LOG_E("I2C: RT_I2C_NO_START/RT_I2C_NO_STOP are not supported on this series (no frame chaining), msg[%d] flags=0x%x", i, msgs[i].flags);
|
||||
return -RT_ENOSYS;
|
||||
}
|
||||
|
||||
/* A receive that the interrupt path has to serve fits in one BYTENUM
|
||||
* window, and that path never reloads the counter. Screen it here as
|
||||
* well as in the receive setup below, because a rejection raised from
|
||||
* inside the transfer is reported as a message count rather than an
|
||||
* errno (see "out:"), so the caller would only see a silent short
|
||||
* read. The test mirrors this function's own DMA dispatch: the
|
||||
* interrupt path is taken when RX DMA is off or the message is too
|
||||
* short for it.
|
||||
*/
|
||||
if ((msgs[i].flags & RT_I2C_RD) && (msgs[i].len > MAX_NBYTE_SIZE))
|
||||
{
|
||||
rt_bool_t rx_dma_ready = (i2c_obj->i2c_dma_flag & I2C_USING_RX_DMA_FLAG) ? RT_TRUE : RT_FALSE;
|
||||
|
||||
if ((rx_dma_ready != RT_TRUE) || (msgs[i].len < DMA_TRANS_MIN_LEN))
|
||||
{
|
||||
LOG_E("I2C IT receive of %u bytes exceeds the %u-byte BYTENUM window, enable RX DMA for longer reads", (unsigned int)msgs[i].len, (unsigned int)MAX_NBYTE_SIZE);
|
||||
return -RT_EINVAL;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
LOG_D("xfer start %d mags", num);
|
||||
for (i = 0; i < (num - 1); i++)
|
||||
{
|
||||
@@ -1890,12 +1958,23 @@ static void i2c_master_ev_isr_handler_it(struct n32_i2c *drv_i2c)
|
||||
}
|
||||
}
|
||||
|
||||
/* Byte Sequence Finished - independent check, handles completion when XferCount == 0 */
|
||||
/* Byte Sequence Finished - only reachable with XferCount == 0, so completing
|
||||
* unconditionally is correct: the RX setup refuses sizes beyond the single
|
||||
* BYTENUM window it programs, and a master transmit is not windowed at all -
|
||||
* its last byte is fed to DAT exactly when XferCount reaches zero. A nonzero
|
||||
* XferCount here means the two setups above drifted out of sync, which is
|
||||
* worth a trace rather than silently truncating the message.
|
||||
*/
|
||||
if ((itflags & I2C_STS1_BSF) && (itsources & I2C_CTRL2_BUFINTEN))
|
||||
{
|
||||
/* Clear BSF flag */
|
||||
I2C_ClrIntPendingBit(drv_i2c->config->Instance, I2C_INT_BSF);
|
||||
|
||||
if (drv_i2c->transfer.XferCount != 0U)
|
||||
{
|
||||
LOG_W("I2C BSF with %u bytes still queued", (unsigned int)drv_i2c->transfer.XferCount);
|
||||
}
|
||||
|
||||
/* Transfer complete - BYTENUM expired (RX) or all bytes sent (TX) */
|
||||
i2c_it_completion_done(drv_i2c);
|
||||
}
|
||||
|
||||
@@ -662,6 +662,20 @@ static rt_err_t _write_page(struct rt_mtd_nand_device *device,
|
||||
uint32_t i;
|
||||
rt_err_t ret;
|
||||
|
||||
#ifdef BSP_USING_NAND_BUS_WIDTH_16B
|
||||
/* 16-bit NAND has no 8-bit store (see the data phase below), so an odd
|
||||
* data_len has no halfword-only encoding: its trailing byte could only
|
||||
* leave as an 8-bit write, and padding would program a byte the caller
|
||||
* never asked for. Refuse it before the command phase, so the chip is
|
||||
* never left in the middle of a program sequence.
|
||||
*/
|
||||
if (data_len & 1U)
|
||||
{
|
||||
LOG_E("page %d: 16-bit NAND needs an even data length, got %u", (int)page, (unsigned int)data_len);
|
||||
return -RT_EINVAL;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Command phase: WRITE_1ST + column(2x 0) + row(NAND_ROW_ADDR_CYCLES) */
|
||||
*(__IO uint8_t *)(bank | NAND_CMD_AREA) = NAND_CMD_WRITE_1ST;
|
||||
*(__IO uint8_t *)(bank | NAND_ADDR_AREA) = 0x00;
|
||||
@@ -686,7 +700,8 @@ static rt_err_t _write_page(struct rt_mtd_nand_device *device,
|
||||
* 16-bit NAND: 8-bit AHB writes are NOT supported (see FEMC manual
|
||||
* "supported memories and operations"), so data must be written as
|
||||
* 16-bit accesses. If the source buffer is not 16-bit aligned, copy
|
||||
* it into an aligned temporary buffer first.
|
||||
* it into an aligned temporary buffer first. An odd data_len was
|
||||
* refused at the top of this function.
|
||||
*/
|
||||
if (((uint32_t)data & 0x1U) == 0U)
|
||||
{
|
||||
@@ -716,11 +731,6 @@ static rt_err_t _write_page(struct rt_mtd_nand_device *device,
|
||||
}
|
||||
rt_free(tmp);
|
||||
}
|
||||
/* odd trailing byte */
|
||||
if (data_len & 1)
|
||||
{
|
||||
*(__IO uint8_t *)(bank | NAND_DATA_AREA) = data[data_len - 1];
|
||||
}
|
||||
#else
|
||||
for (i = 0; i < data_len; i++)
|
||||
{
|
||||
@@ -730,7 +740,14 @@ static rt_err_t _write_page(struct rt_mtd_nand_device *device,
|
||||
}
|
||||
else
|
||||
{
|
||||
/* No payload: one store still has to be issued so the data phase clocks
|
||||
* out. 16-bit NAND rejects 8-bit AHB writes (see the note above), so the
|
||||
* dummy element must be halfword-sized on that bus. */
|
||||
#ifdef BSP_USING_NAND_BUS_WIDTH_16B
|
||||
*(__IO uint16_t *)(bank | NAND_DATA_AREA) = 0x0000;
|
||||
#else
|
||||
*(__IO uint8_t *)(bank | NAND_DATA_AREA) = 0x00;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* spare area write not implemented yet */
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -104,9 +104,10 @@ N32_SPI_DUMMY_ALIGN32 static rt_uint8_t spi_fd_rxonly_dummy[8192];
|
||||
|
||||
|
||||
#if defined(SOC_SERIES_N32H7xx)
|
||||
/* Build an LLI chain for a 'size'-byte transfer: the memory side advances
|
||||
* 4095B per node while the peripheral (DAT) address stays fixed. Only the
|
||||
* last node has IntEn=1, so the whole chain raises a single TC interrupt. */
|
||||
/* Build an LLI chain for a 'size'-element transfer: the memory side advances
|
||||
* SPI_DMA_BLOCK_MAX elements per node while the peripheral (DAT) address
|
||||
* stays fixed. Only the last node has IntEn=1, so the whole chain raises a
|
||||
* single TC interrupt. */
|
||||
static rt_uint16_t n32_spi_lli_build(DMA_LinkListItemType *lli, const DMA_ChInitType *ch,
|
||||
rt_uint32_t periph_addr, rt_uint32_t mem_addr,
|
||||
rt_bool_t mem_is_src, rt_uint16_t size)
|
||||
@@ -121,8 +122,17 @@ static rt_uint16_t n32_spi_lli_build(DMA_LinkListItemType *lli, const DMA_ChInit
|
||||
rt_uint16_t blk = (rest > SPI_DMA_BLOCK_MAX) ? SPI_DMA_BLOCK_MAX : rest;
|
||||
rt_bool_t has_next = (i + 1U < n) ? RT_TRUE : RT_FALSE;
|
||||
|
||||
node->SrcAddr = mem_is_src ? (mem_addr + (rt_uint32_t)i * SPI_DMA_BLOCK_MAX) : periph_addr;
|
||||
node->DstAddr = mem_is_src ? periph_addr : (mem_addr + (rt_uint32_t)i * SPI_DMA_BLOCK_MAX);
|
||||
/* BlkTfrSize counts data items, so the memory side advances one block
|
||||
* worth of ELEMENTS per node: the byte stride is SPI_DMA_BLOCK_MAX
|
||||
* items times the memory-side transfer width. That width field is the
|
||||
* DMA transfer width code (0 = 8-bit, 1 = 16-bit, 2 = 32-bit), i.e.
|
||||
* 1 << width bytes -- the very value programmed into the node below,
|
||||
* so stride and width cannot disagree. Advancing by SPI_DMA_BLOCK_MAX
|
||||
* BYTES instead overlaps the nodes by half a word at 16-bit width. */
|
||||
rt_uint32_t mem_stride = (rt_uint32_t)SPI_DMA_BLOCK_MAX *
|
||||
(1UL << (mem_is_src ? ch->SrcTfrWidth : ch->DstTfrWidth));
|
||||
node->SrcAddr = mem_is_src ? (mem_addr + (rt_uint32_t)i * mem_stride) : periph_addr;
|
||||
node->DstAddr = mem_is_src ? periph_addr : (mem_addr + (rt_uint32_t)i * mem_stride);
|
||||
node->pNext = has_next ? &lli[i + 1U] : RT_NULL;
|
||||
node->IntEn = has_next ? 0U : 1U;
|
||||
node->DstTfrWidth = ch->DstTfrWidth;
|
||||
@@ -596,7 +606,10 @@ static rt_err_t SPI_DMA_Transmit(struct n32_spi *spi_drv, uint8_t *pData, uint16
|
||||
{
|
||||
#if defined(SOC_SERIES_N32H7xx)
|
||||
/* SPI TX DMA send (single block or seamless LLI chain) */
|
||||
n32_spi_dma_arm(spi_drv, RT_FALSE, RT_TRUE, pData, Size);
|
||||
if (n32_spi_dma_arm(spi_drv, RT_FALSE, RT_TRUE, pData, Size) != RT_EOK)
|
||||
{
|
||||
return -RT_ERROR;
|
||||
}
|
||||
#elif defined(SOC_SERIES_N32H49x) || defined(SOC_SERIES_N32H47x_48x)
|
||||
/* SPI TX DMA Send Data for H49X */
|
||||
DMA_EnableChannel(spi_drv->config->dma_tx->DMAChx, DISABLE);
|
||||
@@ -697,7 +710,10 @@ static rt_err_t SPI_DMA_Receive(struct n32_spi *spi_drv, uint8_t *pData, uint16_
|
||||
{
|
||||
#if defined(SOC_SERIES_N32H7xx)
|
||||
/* SPI RX DMA receive (single block or seamless LLI chain) */
|
||||
n32_spi_dma_arm(spi_drv, RT_TRUE, RT_TRUE, pData, Size);
|
||||
if (n32_spi_dma_arm(spi_drv, RT_TRUE, RT_TRUE, pData, Size) != RT_EOK)
|
||||
{
|
||||
return -RT_ERROR;
|
||||
}
|
||||
#elif defined(SOC_SERIES_N32H49x) || defined(SOC_SERIES_N32H47x_48x)
|
||||
/* SPI RX DMA Receive Data for H49X */
|
||||
DMA_EnableChannel(spi_drv->config->dma_rx->DMAChx, DISABLE);
|
||||
@@ -1840,14 +1856,19 @@ static rt_ssize_t spixfer(struct rt_spi_device *device, struct rt_spi_message *m
|
||||
* grid (see the warm re-arm note). Slaves never chunk below
|
||||
* SPI_DMA_CHAIN_MAX and ignore the flag anyway. */
|
||||
spi_drv->fd_chunk_cont = (fd_msg && (already_send_length != 0U)) ? RT_TRUE : RT_FALSE;
|
||||
/* avoid null pointer problems */
|
||||
/* avoid null pointer problems.
|
||||
* already_send_length counts elements while the buffers are byte
|
||||
* addressed, so this chunk's offset must be scaled by the data width
|
||||
* (16-bit data = 2 bytes per element). Without it every chunk after
|
||||
* the first starts one byte early per element -- half the real offset
|
||||
* -- and the DMA walks the wrong half of the buffer. */
|
||||
if (message->send_buf)
|
||||
{
|
||||
send_buf = (rt_uint8_t *)message->send_buf + already_send_length;
|
||||
send_buf = (rt_uint8_t *)message->send_buf + (already_send_length * (spi_drv->cfg->data_width / 8u));
|
||||
}
|
||||
if (message->recv_buf)
|
||||
{
|
||||
recv_buf = (rt_uint8_t *)message->recv_buf + already_send_length;
|
||||
recv_buf = (rt_uint8_t *)message->recv_buf + (already_send_length * (spi_drv->cfg->data_width / 8u));
|
||||
}
|
||||
|
||||
rt_uint32_t *dma_aligned_buffer = RT_NULL; /* TX staging buffer (copy path only) */
|
||||
@@ -1917,6 +1938,11 @@ static rt_ssize_t spixfer(struct rt_spi_device *device, struct rt_spi_message *m
|
||||
rt_hw_cpu_dcache_ops(RT_HW_CACHE_FLUSH, p_tx_buffer, send_bytes);
|
||||
}
|
||||
#else
|
||||
/* send_length counts elements: the staging buffer must be sized and
|
||||
* filled in bytes (x2 for 16-bit data). Sized in elements the
|
||||
* halfword DMA reads twice as far as the allocation and the copy
|
||||
* only carries half of the payload. */
|
||||
rt_uint32_t send_bytes = send_length * (spi_drv->cfg->data_width / 8u);
|
||||
if (RT_IS_ALIGN((rt_uint32_t)send_buf, 4) && send_buf != RT_NULL) /* aligned with 4 bytes? */
|
||||
{
|
||||
p_tx_buffer = (rt_uint32_t *)send_buf; /* send_buf aligns with 4 bytes, no more operations */
|
||||
@@ -1924,14 +1950,14 @@ static rt_ssize_t spixfer(struct rt_spi_device *device, struct rt_spi_message *m
|
||||
else
|
||||
{
|
||||
/* send_buf doesn't align with 4 bytes, so creat a cache buffer with 4 bytes aligned */
|
||||
dma_aligned_buffer = (rt_uint32_t *)rt_malloc(send_length); /* aligned with RT_ALIGN_SIZE (8 bytes by default) */
|
||||
dma_aligned_buffer = (rt_uint32_t *)rt_malloc(send_bytes); /* aligned with RT_ALIGN_SIZE (8 bytes by default) */
|
||||
if (dma_aligned_buffer == RT_NULL)
|
||||
{
|
||||
LOG_E("SPI DMA TX buffer malloc failed!");
|
||||
state = -RT_ENOMEM;
|
||||
goto spi_staging_free;
|
||||
}
|
||||
rt_memcpy(dma_aligned_buffer, send_buf, send_length);
|
||||
rt_memcpy(dma_aligned_buffer, send_buf, send_bytes);
|
||||
p_tx_buffer = dma_aligned_buffer;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -48,7 +48,7 @@ struct n32_spi_device
|
||||
#define SPI_USING_RX_DMA_FLAG (1 << 0)
|
||||
#define SPI_USING_TX_DMA_FLAG (1 << 1)
|
||||
|
||||
/* Max bytes of a single DMA block (12-bit BlkTfrSize) */
|
||||
/* Max elements (data items) of a single DMA block (12-bit BlkTfrSize) */
|
||||
#define SPI_DMA_BLOCK_MAX (4095U)
|
||||
/* Number of LLI chain nodes per DMA leg (sizes lli_tx/lli_rx) */
|
||||
#define SPI_DMA_CHAIN_NODES (16U)
|
||||
|
||||
@@ -1,10 +1,18 @@
|
||||
menu "Hardware Drivers Config"
|
||||
|
||||
config BSP_PERIPH_PIN_CFG_READY
|
||||
bool "Optional peripheral AF pins are configured on this board"
|
||||
default n
|
||||
help
|
||||
The peripheral clock and IO must be configured in
|
||||
board/Cube_Config/USER/src/n32h47x_48x_cfg.c.
|
||||
|
||||
menu "Onboard Peripheral Drivers"
|
||||
|
||||
menuconfig BSP_USING_ETH
|
||||
bool "Enable Ethernet"
|
||||
default n
|
||||
depends on BSP_PERIPH_PIN_CFG_READY
|
||||
select RT_USING_LWIP
|
||||
if BSP_USING_ETH
|
||||
choice BSP_ETH_INTERFACE_SEL
|
||||
@@ -231,6 +239,7 @@ menu "On-chip Peripheral Drivers"
|
||||
menuconfig BSP_USING_QSPI
|
||||
bool "Enable QSPI (XSPI) BUS"
|
||||
default n
|
||||
depends on BSP_PERIPH_PIN_CFG_READY
|
||||
select RT_USING_QSPI
|
||||
select RT_USING_SPI
|
||||
|
||||
@@ -683,6 +692,7 @@ menu "On-chip Peripheral Drivers"
|
||||
menuconfig BSP_USING_NAND
|
||||
bool "Enable Nand"
|
||||
default n
|
||||
depends on BSP_PERIPH_PIN_CFG_READY
|
||||
select RT_USING_MTD_NAND
|
||||
if BSP_USING_NAND
|
||||
choice BSP_NAND_BANK_SEL
|
||||
|
||||
@@ -1,10 +1,18 @@
|
||||
menu "Hardware Drivers Config"
|
||||
|
||||
config BSP_PERIPH_PIN_CFG_READY
|
||||
bool "Optional peripheral AF pins are configured on this board"
|
||||
default n
|
||||
help
|
||||
The peripheral clock and IO must be configured in
|
||||
board/Cube_Config/USER/src/n32h49x_cfg.c.
|
||||
|
||||
menu "Onboard Peripheral Drivers"
|
||||
|
||||
menuconfig BSP_USING_ETH
|
||||
bool "Enable Ethernet"
|
||||
default n
|
||||
depends on BSP_PERIPH_PIN_CFG_READY
|
||||
select RT_USING_LWIP
|
||||
if BSP_USING_ETH
|
||||
choice BSP_ETH_INTERFACE_SEL
|
||||
@@ -48,6 +56,7 @@ menu "Onboard Peripheral Drivers"
|
||||
menuconfig BSP_USING_SDRAM
|
||||
bool "Enable SDRAM"
|
||||
default n
|
||||
depends on BSP_PERIPH_PIN_CFG_READY
|
||||
if BSP_USING_SDRAM
|
||||
choice BSP_SDRAM_BANK_SEL
|
||||
prompt "Select SDRAM Bank"
|
||||
@@ -340,6 +349,7 @@ menu "On-chip Peripheral Drivers"
|
||||
menuconfig BSP_USING_QSPI
|
||||
bool "Enable QSPI (XSPI) BUS"
|
||||
default n
|
||||
depends on BSP_PERIPH_PIN_CFG_READY
|
||||
select RT_USING_QSPI
|
||||
select RT_USING_SPI
|
||||
|
||||
@@ -764,6 +774,7 @@ menu "On-chip Peripheral Drivers"
|
||||
menuconfig BSP_USING_NAND
|
||||
bool "Enable Nand"
|
||||
default n
|
||||
depends on BSP_PERIPH_PIN_CFG_READY
|
||||
select RT_USING_MTD_NAND
|
||||
if BSP_USING_NAND
|
||||
choice BSP_NAND_BANK_SEL
|
||||
|
||||
@@ -1,10 +1,18 @@
|
||||
menu "Hardware Drivers Config"
|
||||
|
||||
config BSP_PERIPH_PIN_CFG_READY
|
||||
bool "Optional peripheral AF pins are configured on this board"
|
||||
default n
|
||||
help
|
||||
The peripheral clock and IO must be configured in
|
||||
board/Cube_Config/USER/src/n32h7xx_cfg.c.
|
||||
|
||||
menu "Onboard Peripheral Drivers"
|
||||
|
||||
menuconfig BSP_USING_SDRAM
|
||||
bool "Enable SDRAM"
|
||||
default n
|
||||
depends on BSP_PERIPH_PIN_CFG_READY
|
||||
if BSP_USING_SDRAM
|
||||
choice BSP_SDRAM_BANK_SEL
|
||||
prompt "Select SDRAM Bank"
|
||||
@@ -85,6 +93,7 @@ menu "Onboard Peripheral Drivers"
|
||||
menuconfig BSP_USING_LCD
|
||||
bool "Enable LCD"
|
||||
default n
|
||||
depends on BSP_PERIPH_PIN_CFG_READY
|
||||
select BSP_USING_SDRAM
|
||||
if BSP_USING_LCD
|
||||
config BSP_BITS_PER_PIXEL
|
||||
@@ -175,6 +184,7 @@ menu "Onboard Peripheral Drivers"
|
||||
menuconfig BSP_USING_ETH
|
||||
bool "Enable Ethernet"
|
||||
default n
|
||||
depends on BSP_PERIPH_PIN_CFG_READY
|
||||
select RT_USING_LWIP
|
||||
if BSP_USING_ETH
|
||||
choice BSP_ETH_SEL
|
||||
@@ -650,6 +660,7 @@ menu "On-chip Peripheral Drivers"
|
||||
menuconfig BSP_USING_QSPI
|
||||
bool "Enable QSPI Quad SPI BUS"
|
||||
default n
|
||||
depends on BSP_PERIPH_PIN_CFG_READY
|
||||
select RT_USING_QSPI
|
||||
select RT_USING_SPI
|
||||
if BSP_USING_QSPI
|
||||
@@ -1933,6 +1944,7 @@ menu "On-chip Peripheral Drivers"
|
||||
menuconfig BSP_USING_NAND
|
||||
bool "Enable Nand"
|
||||
default n
|
||||
depends on BSP_PERIPH_PIN_CFG_READY
|
||||
select RT_USING_MTD_NAND
|
||||
if BSP_USING_NAND
|
||||
choice BSP_NAND_BANK_SEL
|
||||
|
||||
Reference in New Issue
Block a user