DMAディスクリプタを使用して1024バイトを超えるデータを受信する(LPC55S69) コミュニティの皆様、こんにちは。 DMAの最大転送サイズが1024バイトであることを考慮すると、 DMAを介して大量のデータ(2000バイト以上)をLPC55S69ボードに受信する方法を見つけるのに苦労していました。 「usart_dma_double_buffer_transfer」の例を見てみましたが、例えば以下のような機能が古くなっていました。 DMA_PrepareTransfer() は DMA_PrepareChannelTransfer() に、DMA_SubmitTransfer() は DMA_SubmitChannelTransfer() に、DMA_CreateDescriptor() は DMA_SetupDescriptor() に変更されました。SO、例には表示されなかったこれらの新しい関数の新しい入力パラメータ、特に新しいDMA_SetupDescriptor()にあるDMAの転送構成パラメータ "xfercfg" を入力するのに少し迷ってしまいました。
[[ ## completed ##]] 「dma_channel_chain」というサンプルコードも確認しましたが、新しい関数のいくつかについて別の視点を得るのに役立ちましたが、まさに私が探していたものではありませんでした。 さらに、 DMA卓球アプリケーション - NXPコミュニティという記事も見ましたが、私が使っていたLPCボードとは完全に互換性がありませんでした。 オンラインで得た情報をまとめ、キーボードに頭を打ち付けて、 ついに目的の場所にたどり着き、DMAを通じて大量のデータを受け取った。 (データはそれぞれ1024バイトの3つの異なるバッファに保存されます) SO、この 機会にコードを共有して、同じ 道を歩んでいる方の助けになれたり、指針を提供できればと思っています。また、この素晴らしいコミュニティから学んだことを少しでも還元したいと思っています。 (これは質問というわけではなく、議論の余地があるトピックであることを考えると、ここに投稿しても問題ないことを願っています。) 幸運を祈ります! #include "fsl_usart_dma.h"
#include "fsl_dma.h"
#define NUMBER_DESCRIPTORS 3
#define DESCRIPTOR_TRANSFER_SIZE 1024
#define RX_BUFFER_SIZE 1024
uint8_t g_data_buffer[RX_BUFFER_SIZE];
uint8_t g_data_1[RX_BUFFER_SIZE];
uint8_t g_data_2[RX_BUFFER_SIZE];
uint8_t g_data_3[RX_BUFFER_SIZE];
/* Custom Descriptors (Must be 16-byte aligned) */
SDK_ALIGN(dma_descriptor_t g_Desc[NUMBER_DESCRIPTORS], 16);
/* equal to writing:
__attribute__((aligned(FSL_FEATURE_DMA_LINK_DESCRIPTOR_ALIGN_SIZE))) dma_descriptor_t g_Desc[NUMBER_DESCRIPTORS] = {0};
or
DMA_ALLOCATE_LINK_DESCRIPTORS_AT_NONCACHEABLE(g_Desc, NUMBER_DESCRIPTORS);
*/
/* Function definitions
****************************************************************************/
//Initialising Rx DMA to receive data bigger than 1024 bytes.
void init_USART_DMA(void){
//Channel configuration for DMA descriptor
dma_channel_config_t channelConfig;
/* 1. System/Peripheral Level Init */
// Done in peripheral.c, initialized the functions USART_Init(), DMA_EnableChannel(), DMA_CreateHandle(), USART_TransferCreateHandleDMA().
/*I have not used the function DMA_SubmitChannelDescriptor(), by giving as input the g_ChannelTable, as it would not allow to receive data.
the g_ChannelTable variable should be initalized as follow:
//Allocates the mandatory, 512-byte aligned master table in RAM used by the hardware to manage all DMA channels
SDK_ALIGN(dma_descriptor_t g_ChannelTable[FSL_FEATURE_DMA_MAX_CHANNELS], 512);
then call the function here in the code
DMA_SubmitChannelDescriptor(FLEXCOMM5_USB_PC_RX_Handle,g_ChannelTable);
*/
/* 2. Enable USART RX DMA requests */
USART_EnableRxDMA(FLEXCOMM5_USB_PC_PERIPHERAL, true);
/* 3. Prepare the Descriptor Configuration Variable Flags */
//Intermediate Descriptors, where it jumps from one to another
/* Common XFER configuration options for intermediate descriptors (1, 2,...) */
/* reload = true (keeps the chain moving to the next descriptor) */
/* intA = false (we only want the final interrupt when everything is done) */
uint32_t intermediatexfercfg = DMA_CHANNEL_XFER(
true, /* reload: true to move to the next descriptor */
false, /* clrTrig: false */
false, /* intA: false */
false, /* intB: false */
sizeof(uint8_t), /* width: 1 byte for USART char processing */
kDMA_AddressInterleave0xWidth, /* srcInc: 0x (read from fixed USART FIFO address) */
kDMA_AddressInterleave1xWidth, /* dstInc: 1x (increment buffer pointer by 1 byte) */
DESCRIPTOR_TRANSFER_SIZE /* totalBytes: DESCRIPTOR_TRANSFER_SIZE */
);
//Final Descriptor, where it stops jumping to another descriptor
/* Final XFER configuration options for the last descriptor */
/* reload = false (this is the end of the chain) */
/* clrTrig = true (stop the DMA hardware channel) */
/* intA = true (fire the completion interrupt) */
uint32_t finalxfercfg = DMA_CHANNEL_XFER(
false, /* reload: false because this is the terminal descriptor */
true, /* clrTrig: true to clear peripheral hardware requests */
true, /* intA: true to fire our completion interrupt */
false, /* intB: false */
sizeof(uint8_t), /* width: 1 byte for USART char processing */
kDMA_AddressInterleave0xWidth, /* srcInc: 0x (read from fixed USART FIFO address) */
kDMA_AddressInterleave1xWidth, /* dstInc: 1x (increment buffer pointer by 1 byte) */
DESCRIPTOR_TRANSFER_SIZE /* totalBytes: DESCRIPTOR_TRANSFER_SIZE */
);
/* 4. Configure the Custom Descriptors structure */
//Descriptor #0
DMA_SetupDescriptor(
&g_Desc[0],
intermediatexfercfg,
(void *)&FLEXCOMM5_USB_PC_PERIPHERAL->FIFORD, /* Source address: USART FIFO Read Register */
&g_data_1[0], /* Destination address: RAM buffer */
&g_Desc[1] /* Point to next descriptor */
);
//Descriptor #1
DMA_SetupDescriptor(
&g_Desc[1],
intermediatexfercfg,
(void *)&FLEXCOMM5_USB_PC_PERIPHERAL->FIFORD, /* Source address: USART FIFO Read Register */
&g_data_2[0], /* Destination address: RAM buffer */
&g_Desc[2] /* Point to next descriptor */
);
//Descriptor #2 (final)
DMA_SetupDescriptor(
&g_Desc[2],
finalxfercfg,
(void *)&FLEXCOMM5_USB_PC_PERIPHERAL->FIFORD, /* Source address: USART FIFO Read Register */
&g_data_3[0], /* Destination address: RAM buffer */
NULL /* Final descriptor, does not move to another*/
);
/* 5. Set up Head Transfer to execute first descriptor first */
/* Point the initial hardware channel block straight to the first buffer to save data */
DMA_PrepareChannelTransfer(
&channelConfig, /* 1. Pointer to configuration structure */
(void *)&FLEXCOMM5_USB_PC_PERIPHERAL->FIFORD, /* 2. Source start address */
(void *)&g_data_1[0], /* 3. Destination start address */
DMA_CHANNEL_XFER( /* 4. Initial transfer settings bitmask */
true, /* reload: true to step into linked descriptor */
false,
false,
false,
sizeof(uint8_t),
kDMA_AddressInterleave0xWidth,
kDMA_AddressInterleave1xWidth,
DESCRIPTOR_TRANSFER_SIZE
),
kDMA_PeripheralToMemory, /* 5. Transfer type enum path */
NULL, /* 6. Hardware Trigger parameters (NULL uses default peripheral request) */
&g_Desc[1] /* 7. Address of next descriptor. (including already 2nd descriptor,
as this will already transfer all the data to begining of rxBuffer like first descriptor would have done*/
);
DMA_SubmitChannelTransfer(&FLEXCOMM5_USB_PC_RX_Handle,&channelConfig);
DMA_StartTransfer(&FLEXCOMM5_USB_PC_RX_Handle);
} LPC55xx ペリフェラル Re: Using DMA Descriptors to receive Data bigger than 1024 bytes (LPC55S69) こんにちは、
調査結果とコードを共有していただきありがとうございます。このコミュニティは発見を共有したり、質問したり、指導やサポートを提供したりするのに素晴らしい場所SO、ここに投稿していただき感謝しています。
さらにご不明な点やご要望がございましたら、お気軽にお問い合わせください。
敬具、ルイス
View full article