Setting up a linked or chained transfer that runs to SPI

取消
显示结果 
显示  仅  | 搜索替代 
您的意思是: 

Setting up a linked or chained transfer that runs to SPI

1,159 次查看
Jason-Trout
Contributor I

Hey guys. I've been experimenting with driving a SPI device (an LCD display) using the DMA engine on a LPC54S018J4M (our company's hardware, not the development board). I've successfully adapted the spi_dma_transfer demo onto our hardware and used it to drive our LCD device. The only caveat is that our LCD device requires a 2560-byte buffer to display things, which is a larger buffer than the DMA engine can service in one transfer. To that end I've been trying to figure out how to integrate either linked transfers (dma_linked_transfer sample) or chained transfers (dma_channel_chain) into the spi_dma_transfer example... so far without success.

What I've got working thus far takes two dma_handle_t objects, bundles them into a spi_dma_handle_t, and passes it to SPI_MasterTransferDMA. The spi_dma_handle_t object doesn't have any machinery for specifying a linked transfer... I've tried adding extra descriptors to the transmit dma_handle_t objects (using the code in dma_linked_transfer), before bundling them into a spi_dma_handle_t, but so far everything I've tried results in jammed DMA or SPI logic (AFAICT; the LCD screen receives the data I'm sending, but stops responding after the first frame).

1) Is doing this combination supported?

2) Is there an example I can refer to that is closer to what I want to do than the 3 I'm already familiar with? Another thing I was trying was to pull apart the SPI_MasterTransferDMA logic to figure out how to add a 2nd chained descriptor (with the deprecated functions that SPI_MasterTransferDMA uses), but there's so much going on down there, it's very slow going. 

0 项奖励
回复
1 回复

1,131 次查看
xiangjun_rong
NXP TechSupport
NXP TechSupport

Hi,

I think that the spi_dma_transfer is too complicated, I see your issue that the maximum DMA transfer number is 0x3FF or 1024 times based on XFERCFGn register, if you want to transfer 2560, you have to set three descriptor with descriptor chain.

The first descriptor transfer number is 1024, he second descriptor transfer number is 1024, the third is 2560-2048=512

I suggest you refer to ADC DMA example for LPC55S69 as the following code, the code is very simple and straightforward.

I just modified the code briefly, pls check it.

You have to pre-initialize the SPI module, the buff just save the 16 bits bitmap without saving the SPIWR control bits, so the transfer width is 16 bits. You have to enable DMA.

Hope it can help you

BR

XiangJun Rong

#define DEMO_DMA_BASE DMA0
#define DEMO_DMA_ADC_CHANNEL 21U
#define DEMO_DMA_TRANSFER_TYPE kDMA_MemoryToPeripheral
#define DMA_DESCRIPTOR_NUM 5U

/*******************************************************************************
* Prototypes
******************************************************************************/

static void DMA_Configuration(void);

/*******************************************************************************
* Variables
******************************************************************************/
uint16_t buffer0[1024];
uint16_t buffer1[1024];
uint16_t buffer2[512];

lpadc_conv_command_config_t g_LpadcCommandConfigStruct; /* Structure to configure conversion command. */
uint32_t g_AdcConvResult[1]; /* Keep the ADC conversion resulut moved from ADC data register by DMA. */
dma_handle_t g_DmaHandleStruct; /* Handler structure for using DMA. */
volatile bool g_DmaTransferDoneFlag = false; /* Flag of DMA transfer done trigger by ADC conversion. */
/* DMA descripter table used for ping-pong mode. */
SDK_ALIGN(uint32_t s_dma_table[DMA_DESCRIPTOR_NUM * sizeof(dma_descriptor_t)], FSL_FEATURE_DMA_DESCRIPTOR_ALIGN_SIZE);
const uint32_t g_XferConfig =
DMA_CHANNEL_XFER(true, /* Reload link descriptor after current exhaust, */
true, /* Clear trigger status. */
true, /* Enable interruptA. */
false, /* Not enable interruptB. */
sizeof(uint16_t), /* Dma transfer width. */
kDMA_AddressInterleave1xWidth, /* Dma source address no interleave */
kDMA_AddressInterleave1xWidth, /* Dma destination address no interleave */
1024*sizeof(uint16_t) /* Dma transfer byte. */
);
const uint32_t g_XferConfig_1 =
DMA_CHANNEL_XFER(true, /* Reload link descriptor after current exhaust, */
true, /* Clear trigger status. */
true, /* Enable interruptA. */
false, /* Not enable interruptB. */
sizeof(uint16_t), /* Dma transfer width. */
kDMA_AddressInterleave1xWidth, /* Dma source address no interleave */
kDMA_AddressInterleave1xWidth, /* Dma destination address no interleave */
512*sizeof(uint16_t) /* Dma transfer byte. */
);

static void DMA_Configuration(void)
{
dma_channel_config_t dmaChannelConfigStruct;

#if defined(DEMO_DMA_HARDWARE_TRIGGER) && DEMO_DMA_HARDWARE_TRIGGER
/* Configure INPUTMUX. */
INPUTMUX_Init(DEMO_INPUTMUX_BASE);
INPUTMUX_AttachSignal(DEMO_INPUTMUX_BASE, DEMO_DMA_ADC_CHANNEL, DEMO_DMA_ADC_CONNECTION);
#endif /* DEMO_DMA_HARDWARE_TRIGGER */

/* Configure DMA. */
DMA_Init(DEMO_DMA_BASE);
DMA_EnableChannel(DEMO_DMA_BASE, DEMO_DMA_ADC_CHANNEL);
DMA_CreateHandle(&g_DmaHandleStruct, DEMO_DMA_BASE, DEMO_DMA_ADC_CHANNEL);
DMA_SetCallback(&g_DmaHandleStruct, DEMO_DMA_Callback, NULL);

/* Prepare and submit the transfer. */
DMA_PrepareChannelTransfer(&dmaChannelConfigStruct, /* DMA channel transfer configuration structure. */
(void *)DEMO_LPADC_RESFIFO_REG_ADDR, /* DMA transfer source address. */
(void *)g_AdcConvResult, /* DMA transfer destination address. */
g_XferConfig, /* Xfer configuration */
DEMO_DMA_TRANSFER_TYPE, /* DMA transfer type. */
NULL, /* DMA channel trigger configurations. */
(dma_descriptor_t *)&(s_dma_table[0]) /* Address of next descriptor. */
);
DMA_SubmitChannelTransfer(&g_DmaHandleStruct, &dmaChannelConfigStruct);

/* Set two DMA descripters to use ping-pong mode. */
DMA_SetupDescriptor((dma_descriptor_t *)&(s_dma_table[0]), g_XferConfig, (void *)buffer0,
(void *)&SPI_FIFOWR, (dma_descriptor_t *)&(s_dma_table[4]));
DMA_SetupDescriptor((dma_descriptor_t *)&(s_dma_table[4]), g_XferConfig, (void *)buffer1,
(void *)&SPI_FIFOWR, (dma_descriptor_t *)&(s_dma_table[1]));
DMA_SetupDescriptor((dma_descriptor_t *)&(s_dma_table[1]), g_XferConfig_1, (void *)buffer2,
(void *)&SPI_FIFOWR, (dma_descriptor_t *)&(s_dma_table[0]));
}

 

 

0 项奖励
回复