查看: 1531|回复: 5

[求助] RT1024 输入捕获触发spi dma功能

[复制链接]

该用户从未签到

9

主题

25

帖子

0

注册会员

Rank: 2

积分
191
最后登录
2023-4-12
发表于 2022-1-5 14:58:14 | 显示全部楼层 |阅读模式
本帖最后由 fengqiluoye 于 2022-1-5 15:09 编辑

我在使用定时器输入捕获功能触发dma,并且使用小循环连接到spi的dma中,如果使用捕获功能的dma中断,波形正常,但是会丢掉一组数据。如果使用的是spi接收dma完成中断则数据不正常。不知道是哪里有问题。有人能给我点建议吗?
代码如下(调试代码有点乱):
/*
* Copyright 2017-2020 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/

/*******************************************************************************
* Includes
******************************************************************************/
#include "fsl_debug_console.h"
#include "pin_mux.h"
#include "fsl_dmamux.h"
#include "clock_config.h"
#include "board.h"
#include "fsl_qtmr.h"
#include "fsl_edma.h"
#include "fsl_lpspi.h"
#include "fsl_lpspi_edma.h"

/*******************************************************************************
* Definitions
******************************************************************************/
/* The QTMR instance/channel used for board */
#define BOARD_QTMR_BASEADDR              TMR2
#define BOARD_QTMR_INPUT_CAPTURE_CHANNEL kQTMR_Channel_0
#define BOARD_QTMR_PWM_CHANNEL           kQTMR_Channel_1
#define QTMR_CounterInputPin             kQTMR_Counter0InputPin

/* Interrupt number and interrupt handler for the QTMR instance used */
#define QTMR_IRQ_ID      TMR2_IRQn
#define QTMR_IRQ_HANDLER TMR2_IRQHandler

/* QTMR Clock source divider for Ipg clock source, the value of two macros below should be aligned. */
#define QTMR_PRIMARY_SOURCE       (kQTMR_ClockDivide_4)
#define QTMR_CLOCK_SOURCE_DIVIDER (4U)
/* The frequency of the source clock after divided. */
//CLOCK_GetFreq:125MHZ
#define QTMR_SOURCE_CLOCK (CLOCK_GetFreq(kCLOCK_IpgClk) / QTMR_CLOCK_SOURCE_DIVIDER)
/* The frequency of the PWM signal QTMR generated. */
#define QTMR_PWM_OUTPUT_FREQUENCY (500U)
/* The dutycycle of the PTM signal QTMR generated. */
#define QTMR_DUTYCYCLE_PERCENT (50U)
/*DMA base address*/
#define DMA_MUX (DMAMUX)
#define EDMA     (DMA0)
/*channel number*/
#define CAPTURE_DMA_CHANNEL (0U)
#define BUFF_LENTH                        4U
#define SPI_LENTH                        4U
#define ADC_BUFF_LENTH                        1024U

//spi
#define EXAMPLE_LPSPI_MASTER_BASEADDR   (LPSPI1)
/* Select USB1 PLL PFD0 (720 MHz) as lpspi clock source */
#define EXAMPLE_LPSPI_CLOCK_SOURCE_SELECT (1U)
/* Clock divider for master lpspi clock source */
#define EXAMPLE_LPSPI_CLOCK_SOURCE_DIVIDER (7U)
/*SPI tx edma channel*/
#define EXAMPLE_LPSPI_MASTER_DMA_TX_CHANNEL        1U
#define EXAMPLE_LPSPI_MASTER_DMA_RX_CHANNEL        2U
/* Transfer baudrate - 10M */
#define TRANSFER_BAUDRATE 10000000U
#define LPSPI_MASTER_CLK_FREQ (CLOCK_GetFreq(kCLOCK_Usb1PllPfd0Clk) / (EXAMPLE_LPSPI_CLOCK_SOURCE_DIVIDER + 1U))

#define TCD_QUEUE_SIZE     1U

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

/*******************************************************************************
* Variables
******************************************************************************/
edma_handle_t g_EDMA_Handle_0;
edma_handle_t g_EDMA_Handle_1;
edma_handle_t g_EDMA_Handle_2;
volatile bool qtmrIsrFlag = false;
volatile bool g_Transfer_Done = false;
volatile bool g_Transfer_Done1 = false;
uint16_t captValue = 0;
edma_transfer_config_t transferConfig;
AT_NONCACHEABLE_SECTION_ALIGN(edma_tcd_t tcdMemoryPoolPtr[TCD_QUEUE_SIZE + 1], sizeof(edma_tcd_t));
AT_NONCACHEABLE_SECTION_ALIGN(edma_tcd_t tcdMemoryPoolPtr1[TCD_QUEUE_SIZE + 1], sizeof(edma_tcd_t));
AT_NONCACHEABLE_SECTION_ALIGN(edma_tcd_t tcdMemoryPoolPtr2[TCD_QUEUE_SIZE + 1], sizeof(edma_tcd_t));
AT_NONCACHEABLE_SECTION_INIT(lpspi_master_edma_handle_t g_m_edma_handle) = {0};
uint32_t disaddr[5*4] ={0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa};
uint32_t sendaddr[5*4] ={0};
/*******************************************************************************
* Code
******************************************************************************/

static int dma_count = 0;
lpspi_transfer_t masterXfer;
uint16_t adc_data[ADC_BUFF_LENTH] = {0};
void EDMA_Callback_0(edma_handle_t *handle, void *param, bool transferDone, uint32_t tcds)
{

        int i;
    if (transferDone)
    {
////
                            g_Transfer_Done = true;
            //                                adc_data[dma_count++] = ((sraddr[0] << 8) | sraddr[1]);
                            EDMA_InstallTCD(EDMA, CAPTURE_DMA_CHANNEL, tcdMemoryPoolPtr);
                            EDMA_InstallTCD(EDMA, EXAMPLE_LPSPI_MASTER_DMA_TX_CHANNEL, tcdMemoryPoolPtr1);
                            EDMA_InstallTCD(EDMA, EXAMPLE_LPSPI_MASTER_DMA_RX_CHANNEL, tcdMemoryPoolPtr2);
                            EDMA_EnableChannelRequest(EDMA, CAPTURE_DMA_CHANNEL);

    }
}

void EDMA_Callback_1(edma_handle_t *handle, void *param, bool transferDone, uint32_t tcds)
{

        int i;
    if (transferDone)
    {
//            PRINTF("1111\r\n");
//                g_Transfer_Done = true;
//                EDMA_InstallTCD(EDMA, CAPTURE_DMA_CHANNEL, tcdMemoryPoolPtr);
//                EDMA_InstallTCD(EDMA, EXAMPLE_LPSPI_MASTER_DMA_TX_CHANNEL, tcdMemoryPoolPtr1);
//                EDMA_InstallTCD(EDMA, EXAMPLE_LPSPI_MASTER_DMA_RX_CHANNEL, tcdMemoryPoolPtr2);
//                EDMA_EnableChannelRequest(EDMA, CAPTURE_DMA_CHANNEL);

    }
}

void EDMA_Callback_2(edma_handle_t *handle, void *param, bool transferDone, uint32_t tcds)
{

        int i;
    if (transferDone)
    {
//            PRINTF("2222\r\n");
//                g_Transfer_Done = true;
//                EDMA_InstallTCD(EDMA, CAPTURE_DMA_CHANNEL, tcdMemoryPoolPtr);
//                EDMA_InstallTCD(EDMA, EXAMPLE_LPSPI_MASTER_DMA_TX_CHANNEL, tcdMemoryPoolPtr1);
//                EDMA_InstallTCD(EDMA, EXAMPLE_LPSPI_MASTER_DMA_RX_CHANNEL, tcdMemoryPoolPtr2);
//                EDMA_EnableChannelRequest(EDMA, CAPTURE_DMA_CHANNEL);

    }
}

/*!
* @brief Main function
*/
int main(void)
{
        uint32_t srcClock_Hz;
        qtmr_config_t qtmrConfig;
        edma_config_t userConfig;
        lpspi_master_config_t masterConfig;
        uint16_t tmp;
        int i;
        /* Board pin, clock, debug console init */
        BOARD_ConfigMPU();
        BOARD_InitBootPins();
        BOARD_InitBootClocks();
        BOARD_InitDebugConsole();

        /*Set clock source for LPSPI*/
        CLOCK_SetMux(kCLOCK_LpspiMux, EXAMPLE_LPSPI_CLOCK_SOURCE_SELECT);
        CLOCK_SetDiv(kCLOCK_LpspiDiv, EXAMPLE_LPSPI_CLOCK_SOURCE_DIVIDER);

        /*Master config*/
        LPSPI_MasterGetDefaultConfig(&masterConfig);
        masterConfig.baudRate = TRANSFER_BAUDRATE;
        masterConfig.whichPcs = kLPSPI_Pcs0;
        masterConfig.cpha = 0;
        masterConfig.cpol = 1;
        masterConfig.direction = kLPSPI_MsbFirst;
        masterConfig.bitsPerFrame = 32;
        masterConfig.pcsActiveHighOrLow = kLPSPI_PcsActiveLow;
        srcClock_Hz = LPSPI_MASTER_CLK_FREQ;
        LPSPI_MasterInit(EXAMPLE_LPSPI_MASTER_BASEADDR, &masterConfig, srcClock_Hz);
        LPSPI_EnableDMA(EXAMPLE_LPSPI_MASTER_BASEADDR, (uint32_t)kLPSPI_TxDmaEnable|(uint32_t)kLPSPI_RxDmaEnable);
        PRINTF("\r\n****Output PWM example.****\n");
        PRINTF("\r\n*********Make sure to connect an oscilloscope.*********\n");
        PRINTF("\r\n****A 50% duty cycle PWM wave is observed on an oscilloscope.****\n");

        QTMR_GetDefaultConfig(&qtmrConfig);
        /* Initial the output channel. */
        qtmrConfig.primarySource = QTMR_PRIMARY_SOURCE;
        QTMR_Init(BOARD_QTMR_BASEADDR, BOARD_QTMR_PWM_CHANNEL, &qtmrConfig);

        /* Generate a 50Khz PWM signal with 50% dutycycle */
        QTMR_SetupPwm(BOARD_QTMR_BASEADDR, BOARD_QTMR_PWM_CHANNEL, QTMR_PWM_OUTPUT_FREQUENCY, QTMR_DUTYCYCLE_PERCENT, false,
                                 QTMR_SOURCE_CLOCK);

        PRINTF("\r\n******Init capture dma.********\n");
        QTMR_Init(BOARD_QTMR_BASEADDR, BOARD_QTMR_INPUT_CAPTURE_CHANNEL, &qtmrConfig);

        /* Setup the input capture */
        QTMR_SetupInputCapture(BOARD_QTMR_BASEADDR, BOARD_QTMR_INPUT_CAPTURE_CHANNEL, QTMR_CounterInputPin, false, true,
           kQTMR_FallingEdge);

        //   /* Enable the input edge flag DMA*/
        QTMR_EnableDma(BOARD_QTMR_BASEADDR, BOARD_QTMR_INPUT_CAPTURE_CHANNEL, kQTMR_InputEdgeFlagDmaEnable);

        DMAMUX_Init(DMA_MUX);

        /*Set dma channel 0 as input capture and enable*/
        DMAMUX_SetSource(DMA_MUX, CAPTURE_DMA_CHANNEL, kDmaRequestMuxQTIMER2CaptTimer0);
        DMAMUX_EnableChannel(DMA_MUX, CAPTURE_DMA_CHANNEL);

        /*Set dma channel 1 as spi sending and enable*/
        DMAMUX_SetSource(DMA_MUX, EXAMPLE_LPSPI_MASTER_DMA_TX_CHANNEL,kDmaRequestMuxLPSPI1Tx);
        DMAMUX_EnableChannel(DMA_MUX, EXAMPLE_LPSPI_MASTER_DMA_TX_CHANNEL);

        DMAMUX_SetSource(DMA_MUX, EXAMPLE_LPSPI_MASTER_DMA_RX_CHANNEL,kDmaRequestMuxLPSPI1Rx);
        DMAMUX_EnableChannel(DMA_MUX, EXAMPLE_LPSPI_MASTER_DMA_RX_CHANNEL);
        /* EDMA init */
        /*
        * userConfig.enableRoundRobinArbitration = false;
        * userConfig.enableHaltOnError = true;
        * userConfig.enableContinuousLinkMode = false;
        * userConfig.enableDebugMode = false;
        */
        EDMA_GetDefaultConfig(&userConfig);
        EDMA_Init(EDMA, &userConfig);
        EDMA_CreateHandle(&g_EDMA_Handle_0, EDMA,CAPTURE_DMA_CHANNEL);
        EDMA_SetCallback(&g_EDMA_Handle_0, EDMA_Callback_0, NULL);
        EDMA_ResetChannel(g_EDMA_Handle_0.base, g_EDMA_Handle_0.channel);

        /*Configure dma channel 0*/
        EDMA_PrepareTransfer(&transferConfig,
                                   (uint16_t *)&BOARD_QTMR_BASEADDR->CHANNEL[0].CAPT, 2,
                                   &tmp, 2, 2, BUFF_LENTH*2, kEDMA_PeripheralToMemory);
        EDMA_TcdSetTransferConfig(tcdMemoryPoolPtr, &transferConfig, NULL);
        EDMA_TcdSetChannelLink(tcdMemoryPoolPtr, kEDMA_MinorLink, EXAMPLE_LPSPI_MASTER_DMA_TX_CHANNEL);
        EDMA_TcdEnableInterrupts(tcdMemoryPoolPtr, kEDMA_MajorInterruptEnable);
//        EDMA_TcdEnableAutoStopRequest(tcdMemoryPoolPtr, true);
        EDMA_InstallTCD(EDMA, CAPTURE_DMA_CHANNEL, tcdMemoryPoolPtr);

        /*Configure dma channel 1*/
    memset(&tcdMemoryPoolPtr1, 0, sizeof(edma_tcd_t));


    EDMA_CreateHandle(&g_EDMA_Handle_1, EDMA,EXAMPLE_LPSPI_MASTER_DMA_TX_CHANNEL);
    EDMA_SetCallback(&g_EDMA_Handle_1, EDMA_Callback_1, NULL);
    EDMA_ResetChannel(g_EDMA_Handle_1.base, g_EDMA_Handle_1.channel);

        EDMA_PrepareTransfer(&transferConfig,
                                   disaddr, 4,
                                   (uint32_t *)&EXAMPLE_LPSPI_MASTER_BASEADDR->TDR, 4, 4*5, BUFF_LENTH*4*5, kEDMA_MemoryToPeripheral);
        EDMA_TcdSetTransferConfig(tcdMemoryPoolPtr1, &transferConfig, NULL);
        EDMA_TcdSetChannelLink(tcdMemoryPoolPtr1, kEDMA_MinorLink, 2);
//        EDMA_TcdEnableInterrupts(tcdMemoryPoolPtr1, kEDMA_MajorInterruptEnable);
        EDMA_InstallTCD(EDMA, EXAMPLE_LPSPI_MASTER_DMA_TX_CHANNEL, tcdMemoryPoolPtr1);


    EDMA_CreateHandle(&g_EDMA_Handle_2, EDMA,EXAMPLE_LPSPI_MASTER_DMA_RX_CHANNEL);
    EDMA_SetCallback(&g_EDMA_Handle_2, EDMA_Callback_2, NULL);
    EDMA_ResetChannel(g_EDMA_Handle_2.base, g_EDMA_Handle_2.channel);
        EDMA_PrepareTransfer(&transferConfig,
                                        (uint32_t *)&EXAMPLE_LPSPI_MASTER_BASEADDR->RDR, 4,
                                        sendaddr, 4, 4*5, BUFF_LENTH*4*5, kEDMA_PeripheralToMemory);
        EDMA_TcdSetTransferConfig(tcdMemoryPoolPtr2, &transferConfig, NULL);
//        EDMA_TcdSetChannelLink(tcdMemoryPoolPtr2, kEDMA_MinorLink, 1);
//        EDMA_TcdEnableInterrupts(tcdMemoryPoolPtr2, kEDMA_MajorInterruptEnable);
//        EDMA_TcdEnableAutoStopRequest(tcdMemoryPoolPtr2, true);
        EDMA_InstallTCD(EDMA, EXAMPLE_LPSPI_MASTER_DMA_RX_CHANNEL, tcdMemoryPoolPtr2);


        /* Start the input capture channel to count on rising edge of the primary source clock */
        QTMR_StartTimer(BOARD_QTMR_BASEADDR, BOARD_QTMR_INPUT_CAPTURE_CHANNEL, kQTMR_PriSrcRiseEdge);
        EDMA_EnableChannelRequest(EDMA, CAPTURE_DMA_CHANNEL);
//        EDMA_EnableChannelRequest(EDMA, EXAMPLE_LPSPI_MASTER_DMA_TX_CHANNEL);
//        EDMA_EnableChannelRequest(EDMA, EXAMPLE_LPSPI_MASTER_DMA_RX_CHANNEL);
        //        /* Start the counter */
        QTMR_StartTimer(BOARD_QTMR_BASEADDR, BOARD_QTMR_PWM_CHANNEL, kQTMR_PriSrcRiseEdge);
    while (1)
    {
//            PRINTF("RDR:%d\r\n", EXAMPLE_LPSPI_MASTER_BASEADDR->RDR);
               /* Wait for EDMA transfer finish */
               while (g_Transfer_Done != true)
               {
               }
               g_Transfer_Done = false;
//               PRINTF("111\r\n");
//               PRINTF("RDR:%d\r\n", EXAMPLE_LPSPI_MASTER_BASEADDR->RDR);
//               for(i = 0; i < 4; i++)
//               {
//                       PRINTF("\r\n%d:%x\n", i, sendaddr);
//               }
//               for(i = 0; i < BUFF_LENTH; i++)
//               {
//                       sraddr = 0;
//               }
//               PRINTF("count:%d\r\n", dma_count);
//               for(i = 0; i < ADC_BUFF_LENTH; i++)
//               {
//                       PRINTF("%d\r\n", adc_data);
//               }
    }
}


回复

使用道具 举报

该用户从未签到

9

主题

25

帖子

0

注册会员

Rank: 2

积分
191
最后登录
2023-4-12
 楼主| 发表于 2022-1-5 15:01:28 | 显示全部楼层

这是使用的输入捕获dma的中断,第四个完成后会直接进中断,会将最后一组数据丢掉 ...

这是使用的输入捕获dma的中断,第四个完成后会直接进中断,会将最后一组数据丢掉 ...

这是使用spi接收中断的波形,mosi的发送数据都已经不对了

这是使用spi接收中断的波形,mosi的发送数据都已经不对了
回复 支持 反对

使用道具 举报

该用户从未签到

9

主题

25

帖子

0

注册会员

Rank: 2

积分
191
最后登录
2023-4-12
 楼主| 发表于 2022-1-5 15:03:21 | 显示全部楼层

黄色的是输入捕获的,绿色的是spi的mosi数据线
回复 支持 反对

使用道具 举报

  • TA的每日心情
    开心
    2024-3-26 15:16
  • 签到天数: 266 天

    [LV.8]以坛为家I

    3298

    主题

    6545

    帖子

    0

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    32018
    最后登录
    2024-4-9
    发表于 2022-1-5 15:35:27 | 显示全部楼层
    官网的SDK里面是有LPSPI DMA的例程,有没有参考下
    签到签到
    回复 支持 反对

    使用道具 举报

    该用户从未签到

    9

    主题

    25

    帖子

    0

    注册会员

    Rank: 2

    积分
    191
    最后登录
    2023-4-12
     楼主| 发表于 2022-1-5 15:38:08 | 显示全部楼层
    NXP管管 发表于 2022-1-5 15:35
    官网的SDK里面是有LPSPI DMA的例程,有没有参考下

    有,但是官方的没法使用dma的循环通道连接功能
    回复 支持 反对

    使用道具 举报

    该用户从未签到

    9

    主题

    25

    帖子

    0

    注册会员

    Rank: 2

    积分
    191
    最后登录
    2023-4-12
     楼主| 发表于 2022-1-5 15:59:03 | 显示全部楼层
    fengqiluoye 发表于 2022-1-5 15:38
    有,但是官方的没法使用dma的循环通道连接功能

    使用这个功能是想减少中断的频率
    回复 支持 反对

    使用道具 举报

    您需要登录后才可以回帖 注册/登录

    本版积分规则

    关闭

    站长推荐上一条 /4 下一条

    Archiver|手机版|小黑屋|恩智浦技术社区

    GMT+8, 2024-4-25 07:31 , Processed in 0.127120 second(s), 24 queries , MemCache On.

    Powered by Discuz! X3.4

    Copyright © 2001-2024, Tencent Cloud.

    快速回复 返回顶部 返回列表