This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[参考译文] RM48L952:SPI1(兼容模式)DMA

Guru**** 2513185 points
Other Parts Discussed in Thread: RM48L952, HALCOGEN, TMS570LC4357

请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1541851/rm48l952-spi1-compatibility-mode-dma

部件号:RM48L952
Thread 中讨论的其他器件: HALCOGENTMS570LC4357

工具/软件:

您好、

我正在尝试让 SPI1 用于 DMA。 到目前为止、我看不到通过 MOSI 线路使用范围传输的任何字节、测试时仅传输虚拟字节、因此应该正确配置 SPI。

我已经尝试使用以下源来适应具有 SPI1 的 RM48L952 MCU(示例使用的是 SPI3 RX):

  • 大端字节序地址: #define SPI1_TX_ADDR ((uint32_t)(&(spiREG1->DAT1))+ 2U)
  • dmaReqAssign(DMA_CH0, 1); /* Request line 1: SPI1 Transmit */

https://software-dl.ti.com/hercules/hercules_docs/latest/hercules/Examples/Examples.html#using-dma-to-transfer-data-in-spi-compatibility-mode

https://git.ti.com/cgit/hercules_examples/hercules_examples/tree/Application/TMS570_SPI_DMA/source/sys_main.c

附加我的测试代码和 HALcogen 配置:

/** @file sys_main.c 
*   @brief Application main file
*   @date 11-Dec-2018
*   @version 04.07.01
*
*   This file contains an empty main function,
*   which can be used for the application.
*/

/* 
* Copyright (C) 2009-2018 Texas Instruments Incorporated - www.ti.com 
* 
* 
*  Redistribution and use in source and binary forms, with or without 
*  modification, are permitted provided that the following conditions 
*  are met:
*
*    Redistributions of source code must retain the above copyright 
*    notice, this list of conditions and the following disclaimer.
*
*    Redistributions in binary form must reproduce the above copyright
*    notice, this list of conditions and the following disclaimer in the 
*    documentation and/or other materials provided with the   
*    distribution.
*
*    Neither the name of Texas Instruments Incorporated nor the names of
*    its contributors may be used to endorse or promote products derived
*    from this software without specific prior written permission.
*
*  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
*  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
*  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
*  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
*  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
*  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
*  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
*  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
*  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
*  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
*  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/


/* USER CODE BEGIN (0) */
#define SPI_DMA_REQ_ENA (1U << 16)  // Bit 16 enables DMA request in INT0 register
#define SPI1_TX_ADDR ((uint32_t)(&(spiREG1->DAT1)) + 2U)
/* USER CODE END */

/* Include Files */

#include "sys_common.h"

/* USER CODE BEGIN (1) */
#include "spi.h"
#include "sys_dma.h"


uint16_t spi_test_data[8] = {
    0x1111, 0x2222, 0x3333, 0x4444,
    0xAAAA, 0xBBBB, 0xCCCC, 0xDDDD
};

unsigned int SPI1_HBCFlag = 0;
unsigned int SPI1_BTCFlag = 0;

g_dmaCTRL g_dmaCTRLPKT_TX;

void dmaConfigCtrlTxPacket(uint32 sadd, uint32 dadd, uint16 dsize, uint16 BlockSize);
/* USER CODE END */

/** @fn void main(void)
*   @brief Application main function
*   @note This function is empty by default.
*
*   This function is called after startup.
*   The user can use this function to implement the application.
*/

/* USER CODE BEGIN (2) */
/* USER CODE END */

int main(void)
{
/* USER CODE BEGIN (3) */
    /* Enable CPU Interrupt through CPSR */
    _enable_IRQ();

    spiInit();
    spiREG1->PC0 =  0
                  | (1<<11)   //SOMI[0] as functional pin
                  | (1<<10)   //SIMO[0] as functional pin
                  | (1 << 9)  //CLK as functional pin
                  | (0);      //CS as GIO pin
    spiREG1->PC1 = 0x01;  //CS[0] as output
    spiREG1->PC3 = 0x00;  //CS[0]=0

//    spiREG1->FMT0 &= ~(0x1FU);
//    spiREG1->FMT0 |= 0x0FU;             // 16-bit data

    // Enable DMA controller
    dmaEnable();

//    dmaEnableInterrupt(DMA_CH0, FTC);
    dmaEnableInterrupt(DMA_CH0, BTC);     //Block transfer complete
    dmaEnableInterrupt(DMA_CH0, HBC);     //Half block transfer complete

    // Map SPI1 TX to DMA CH0
    /* Request line 0: SPI1 Receive */
    /* Request line 1: SPI1 Transmit */
    /* Request line 14: SPI3 Receive */
    /* Request line 15: SPI3 Transmit */
    dmaReqAssign(DMA_CH0, 1);

    /* - configuring dma TX control packets   */
    dmaConfigCtrlTxPacket((unsigned int)&spi_test_data, SPI1_TX_ADDR, 1, sizeof(spi_test_data));
    dmaSetCtrlPacket(DMA_CH0, g_dmaCTRLPKT_TX);


    // Enable DMA channel
    dmaSetChEnable(DMA_CH0, DMA_HW);

//    // Enable SPI DMA request generation
    spiREG1->GCR1 = (spiREG1->GCR1 & 0xFFFFFFFFU) | (0x1 << 24);  //Enable SPI
    spiREG1->INT0 = (0x1 << 16); //SPI_DMAREQ; Enable DMA REQ only after setting the SPIEN bit to 1.
//    spiREG1->DAT1 = 0x00;

    while( SPI1_BTCFlag == 0 ){    //DMA block complete interrupt
    }


/* USER CODE END */

    return 0;
}


/* USER CODE BEGIN (4) */
void dmaGroupANotification(dmaInterrupt_t inttype, uint32 channel)
{
    if (inttype == HBC) {
        SPI1_HBCFlag = 1;
     }
    else if (inttype == BTC){
        SPI1_BTCFlag = 1;
    }
}

void dmaConfigCtrlTxPacket(uint32 sadd, uint32 dadd, uint16 ElmntCnt, uint16 FrameCnt)
{
      g_dmaCTRLPKT_TX.SADD      = sadd;               /* source address             */
      g_dmaCTRLPKT_TX.DADD      = dadd;               /* destination  address       */
      g_dmaCTRLPKT_TX.CHCTRL    = 0;                  /* channel control            */
      g_dmaCTRLPKT_TX.FRCNT     = FrameCnt;           /* frame count                */
      g_dmaCTRLPKT_TX.ELCNT     = ElmntCnt;           /* element count              */
      g_dmaCTRLPKT_TX.ELDOFFSET = 0;                  /* element destination offset */
      g_dmaCTRLPKT_TX.ELSOFFSET = 0;                  /* element destination offset */
      g_dmaCTRLPKT_TX.FRDOFFSET = 0;                  /* frame destination offset   */
      g_dmaCTRLPKT_TX.FRSOFFSET = 0;                  /* frame destination offset   */
      g_dmaCTRLPKT_TX.PORTASGN  = 4;                  /* port b                     */
      g_dmaCTRLPKT_TX.RDSIZE    = ACCESS_16_BIT;      /* read size                  */
      g_dmaCTRLPKT_TX.WRSIZE    = ACCESS_16_BIT;      /* write size                 */
      g_dmaCTRLPKT_TX.TTYPE     = FRAME_TRANSFER;     /* transfer type              */
      g_dmaCTRLPKT_TX.ADDMODERD = ADDR_INC1;          /* address mode read          */
      g_dmaCTRLPKT_TX.ADDMODEWR = ADDR_FIXED;         /* address mode write         */
      g_dmaCTRLPKT_TX.AUTOINIT  = AUTOINIT_ON;        /* autoinit                   */
}
/* USER CODE END */

请告知:  

谢谢、

Ofir

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Ofir:

    我们在以下主题中提供了几个经过测试并可正常运行的 SPI DMA 示例:

    (+)【常见问题解答】TMS570LC4357:适用于 Hercules 控制器的示例和演示(例如 TMS570x、RM57x 和 RM46x 等)-基于 Arm 的微控制器论坛 — 基于 Arm 的微控制器 — TI E2E 支持论坛

    那么、您能否将它们作为参考、并将您的配置和代码与它们进行比较?

    --
    此致、
    Jagadish。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的  Jagadish:

    5140.SPI_DMA_TEST_LC4357.zip 和 8611.SPI_DMA_TEST_LC4357 (2)。zip 示例与我在此处引用的演示非常相似:

    https://git.ti.com/cgit/hercules_examples/hercules_examples/tree/Application/TMS570_SPI_DMA

    主要区别在于 TMS570LC4357 是大端字节序、RM48L952 是小端字节序、但这两个选项对我都不起作用:

    #define SPI1_TX_ADDR ((uint32_t)(&(spiREG1->DAT1))+ 2U)//对于大端字节序

    #define SPI1_TX_ADDR ((uint32_t)(&(spiREG1->DAT1))//(对于小端字节序)

    另一个区别是、  根据 TRM、RM48L952 中的 DMA 具有单个端口 B (4)、因此行:

    G_dmaCTRLPKT_TX.PORTASGN = 4;/*端口 b */
     

    谢谢、

    Ofir

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、  

    已重试:

    #define SPI1_TX_ADDR ((uint32_t)(&(spiREG1->DAT1))//(对于小端字节序)

    现在它可以正常工作。

    附加代码以防将来有人需要:

    /** @file sys_main.c 
    *   @brief Application main file
    *   @date 11-Dec-2018
    *   @version 04.07.01
    *
    *   This file contains an empty main function,
    *   which can be used for the application.
    */
    
    /* 
    * Copyright (C) 2009-2018 Texas Instruments Incorporated - www.ti.com 
    * 
    * 
    *  Redistribution and use in source and binary forms, with or without 
    *  modification, are permitted provided that the following conditions 
    *  are met:
    *
    *    Redistributions of source code must retain the above copyright 
    *    notice, this list of conditions and the following disclaimer.
    *
    *    Redistributions in binary form must reproduce the above copyright
    *    notice, this list of conditions and the following disclaimer in the 
    *    documentation and/or other materials provided with the   
    *    distribution.
    *
    *    Neither the name of Texas Instruments Incorporated nor the names of
    *    its contributors may be used to endorse or promote products derived
    *    from this software without specific prior written permission.
    *
    *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
    *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
    *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
    *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
    *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
    *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
    *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
    *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    *
    */
    
    
    /* USER CODE BEGIN (0) */
    #define SPI_DMA_REQ_ENA (1U << 16)  // Bit 16 enables DMA request in INT0 register
    //#define SPI1_TX_ADDR ((uint32_t)(&(spiREG1->DAT1)) + 2U)
    #define SPI1_TX_ADDR ((uint32_t)(&spiREG1->DAT1))
    /* USER CODE END */
    
    /* Include Files */
    
    #include "sys_common.h"
    
    /* USER CODE BEGIN (1) */
    #include "spi.h"
    #include "sys_dma.h"
    
    
    uint16_t spi_test_data[8] = {
        0x1111, 0x2222, 0x3333, 0x4444,
        0xAAAA, 0xBBBB, 0xCCCC, 0xDDDD
    };
    
    unsigned int SPI1_HBCFlag = 0;
    unsigned int SPI1_BTCFlag = 0;
    unsigned int SPI1_FTCFlag = 0;
    
    g_dmaCTRL g_dmaCTRLPKT_TX;
    
    void dmaConfigCtrlTxPacket(uint32 sadd, uint32 dadd, uint16 dsize, uint16 BlockSize);
    /* USER CODE END */
    
    /** @fn void main(void)
    *   @brief Application main function
    *   @note This function is empty by default.
    *
    *   This function is called after startup.
    *   The user can use this function to implement the application.
    */
    
    /* USER CODE BEGIN (2) */
    /* USER CODE END */
    
    int main(void)
    {
    /* USER CODE BEGIN (3) */
        /* Enable CPU Interrupt through CPSR */
        _enable_IRQ();
    
        spiInit();
        spiREG1->PC0 =  0
                      | (1<<11)   //SOMI[0] as functional pin
                      | (1<<10)   //SIMO[0] as functional pin
                      | (1 << 9)  //CLK as functional pin
                      | (0);      //CS as GIO pin
        spiREG1->PC1 = 0x01;  //CS[0] as output
        spiREG1->PC3 = 0x00;  //CS[0]=0
    
    //    spiREG1->FMT0 &= ~(0x1FU);
    //    spiREG1->FMT0 |= 0x0FU;             // 16-bit data
    
        // Enable DMA controller
        dmaEnable();
    
        dmaEnableInterrupt(DMA_CH0, FTC);
        dmaEnableInterrupt(DMA_CH0, BTC);     //Block transfer complete
        dmaEnableInterrupt(DMA_CH0, HBC);     //Half block transfer complete
    
        // Map SPI1 TX to DMA CH0
        /* Request line 0: SPI1 Receive */
        /* Request line 1: SPI1 Transmit */
        /* Request line 14: SPI3 Receive */
        /* Request line 15: SPI3 Transmit */
        dmaReqAssign(DMA_CH0, 1);
    
        /* - configuring dma TX control packets   */
        dmaConfigCtrlTxPacket((unsigned int)&spi_test_data, SPI1_TX_ADDR, 1, sizeof(spi_test_data));
        dmaSetCtrlPacket(DMA_CH0, g_dmaCTRLPKT_TX);
    
    
        // Enable DMA channel
        dmaSetChEnable(DMA_CH0, DMA_HW);
    
    //    // Enable SPI DMA request generation
        spiREG1->GCR1 |= (0x1 << 24);  //Enable SPI
        spiREG1->INT0 = (0x1 << 16); //SPI_DMAREQ; Enable DMA REQ only after setting the SPIEN bit to 1.
    //    spiREG1->DAT1 = 0x00;
    
        while (1);
    
    /* USER CODE END */
    
        return 0;
    }
    
    
    /* USER CODE BEGIN (4) */
    void dmaGroupANotification(dmaInterrupt_t inttype, uint32 channel)
    {
        if (inttype == HBC) {
            SPI1_HBCFlag = 1;
         }
        else if (inttype == BTC){
            SPI1_BTCFlag = 1;
        }
        else if (inttype == FTC){
            SPI1_FTCFlag = 1;
        }
    }
    
    void dmaConfigCtrlTxPacket(uint32 sadd, uint32 dadd, uint16 ElmntCnt, uint16 FrameCnt)
    {
          g_dmaCTRLPKT_TX.SADD      = sadd;               /* source address             */
          g_dmaCTRLPKT_TX.DADD      = dadd;               /* destination  address       */
          g_dmaCTRLPKT_TX.CHCTRL    = 0;                  /* channel control            */
          g_dmaCTRLPKT_TX.FRCNT     = FrameCnt;           /* frame count                */
          g_dmaCTRLPKT_TX.ELCNT     = ElmntCnt;           /* element count              */
          g_dmaCTRLPKT_TX.ELDOFFSET = 0;                  /* element destination offset */
          g_dmaCTRLPKT_TX.ELSOFFSET = 0;                  /* element destination offset */
          g_dmaCTRLPKT_TX.FRDOFFSET = 0;                  /* frame destination offset   */
          g_dmaCTRLPKT_TX.FRSOFFSET = 0;                  /* frame destination offset   */
          g_dmaCTRLPKT_TX.PORTASGN  = 4;                  /* port b                     */
          g_dmaCTRLPKT_TX.RDSIZE    = ACCESS_16_BIT;      /* read size                  */
          g_dmaCTRLPKT_TX.WRSIZE    = ACCESS_16_BIT;      /* write size                 */
          g_dmaCTRLPKT_TX.TTYPE     = FRAME_TRANSFER;     /* transfer type              */
          g_dmaCTRLPKT_TX.ADDMODERD = ADDR_INC1;          /* address mode read          */
          g_dmaCTRLPKT_TX.ADDMODEWR = ADDR_FIXED;         /* address mode write         */
          g_dmaCTRLPKT_TX.AUTOINIT  = AUTOINIT_OFF;        /* autoinit                   */
    }
    /* USER CODE END */
    

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    现在可以正常工作了。

    做得很好!

    附加代码、以防将来有人需要:

    非常感谢您的分享。