C6748对EDMA的操作和通过EMIFA与FPGA传输数据

EDMA的PSC初始化

PSC即power and sleep controller

void PSCInit(void)
{
    // 使能 EDMA3CC_0
    PSCModuleControl(SOC_PSC_0_REGS, 0, 0, PSC_MDCTL_NEXT_ENABLE);
    //可以在psc.c文件中找到函数的原型,0x01C10000是Peripheral Revision and Class Information Register的psc0基地址,

    // 使能 EDMA3TC_0
    PSCModuleControl(SOC_PSC_0_REGS, 1, 0, PSC_MDCTL_NEXT_ENABLE);
    // 使能 GPIO 模块
    // 对相应外设模块的使能也可以在 BootLoader 中完成
    PSCModuleControl(SOC_PSC_1_REGS, HW_PSC_GPIO, PSC_POWERDOMAIN_ALWAYS_ON,
                PSC_MDCTL_NEXT_ENABLE);
    /* 使能EMIFA模块 */
    PSCModuleControl(SOC_PSC_0_REGS, HW_PSC_EMIFA, PSC_POWERDOMAIN_ALWAYS_ON,
                     PSC_MDCTL_NEXT_ENABLE);
}
/****************************************************************************/
/*                                                                          */
/*              EMIFA 初始化                                                  */
/*                                                                          */
/****************************************************************************/
void JBSP_OMAPL138_EMIFA_Init(void)
{

    EMIFAPinMuxSetup();

    /*配置数据总线16bit*/
    EMIFAAsyncDevDataBusWidthSelect(SOC_EMIFA_0_REGS,EMIFA_CHIP_SELECT_2,
                                    EMIFA_DATA_BUSWITTH_16BIT);

    /*选着Normal模式*/
    EMIFAAsyncDevOpModeSelect(SOC_EMIFA_0_REGS,EMIFA_CHIP_SELECT_2,
                               EMIFA_ASYNC_INTERFACE_NORMAL_MODE);

    /*禁止WAIT引脚*/
    EMIFAExtendedWaitConfig(SOC_EMIFA_0_REGS,EMIFA_CHIP_SELECT_2,
                             EMIFA_EXTENDED_WAIT_DISABLE);

    /*配置W_SETUP/R_SETUP   W_STROBE/R_STROBE    W_HOLD/R_HOLD    TA等参数*/
    EMIFAWaitTimingConfig(SOC_EMIFA_0_REGS,EMIFA_CHIP_SELECT_2,
                           EMIFA_ASYNC_WAITTIME_CONFIG(2, 3, 2, 2, 3, 2, 0 ));

    ((short *)SOC_EMIFA_CS2_ADDR)[0x0011] = 0x0000;
    ((short *)SOC_EMIFA_CS2_ADDR)[0x0088] = 0x0000;
}
/*************************************************************************/
先来分析一下EMIFAPinMuxSetup()这个函数,

void EMIFAPinMuxSetup(void)
{
volatile unsigned int savePinMux = 0;

 savePinMux = HWREG(SOC_SYSCFG_0_REGS + SYSCFG0_PINMUX(12)) & \
                     ~(SYSCFG_PINMUX12_PINMUX12_31_28 | \
                       SYSCFG_PINMUX12_PINMUX12_27_24 | \
                       SYSCFG_PINMUX12_PINMUX12_23_20 | \
                       SYSCFG_PINMUX12_PINMUX12_19_16 | \
                       SYSCFG_PINMUX12_PINMUX12_15_12 | \
                       SYSCFG_PINMUX12_PINMUX12_11_8  | \
                       SYSCFG_PINMUX12_PINMUX12_7_4   | \
                       SYSCFG_PINMUX12_PINMUX12_3_0);

 HWREG(SOC_SYSCFG_0_REGS + SYSCFG0_PINMUX(12)) = \
         (PINMUX12_EMIF_A_ENABLE | savePinMux);

 savePinMux = HWREG(SOC_SYSCFG_0_REGS + SYSCFG0_PINMUX(11)) & \
                     ~(SYSCFG_PINMUX11_PINMUX11_31_28 | \
                       SYSCFG_PINMUX11_PINMUX11_27_24 | \
                       SYSCFG_PINMUX11_PINMUX11_23_20 | \
                       SYSCFG_PINMUX11_PINMUX11_19_16 | \
                       SYSCFG_PINMUX11_PINMUX11_15_12 | \
                       SYSCFG_PINMUX11_PINMUX11_11_8  | \
                       SYSCFG_PINMUX11_PINMUX11_7_4   | \
                       SYSCFG_PINMUX11_PINMUX11_3_0);

 HWREG(SOC_SYSCFG_0_REGS + SYSCFG0_PINMUX(11)) = \
         (PINMUX11_EMIF_A_ENABLE | savePinMux);

 savePinMux = HWREG(SOC_SYSCFG_0_REGS + SYSCFG0_PINMUX(9)) & \
                     ~(SYSCFG_PINMUX9_PINMUX9_31_28 | \
                       SYSCFG_PINMUX9_PINMUX9_27_24 | \
                       SYSCFG_PINMUX9_PINMUX9_23_20 | \
                       SYSCFG_PINMUX9_PINMUX9_19_16 | \
                       SYSCFG_PINMUX9_PINMUX9_15_12 | \
                       SYSCFG_PINMUX9_PINMUX9_11_8  | \
                       SYSCFG_PINMUX9_PINMUX9_7_4   | \
                       SYSCFG_PINMUX9_PINMUX9_3_0);

 HWREG(SOC_SYSCFG_0_REGS + SYSCFG0_PINMUX(9)) = \
      (PINMUX9_EMIF_D_ENABLE | savePinMux);

 savePinMux = HWREG(SOC_SYSCFG_0_REGS + SYSCFG0_PINMUX(8)) & \
                     ~(SYSCFG_PINMUX8_PINMUX8_31_28 | \
                       SYSCFG_PINMUX8_PINMUX8_27_24 | \
                       SYSCFG_PINMUX8_PINMUX8_23_20 | \
                       SYSCFG_PINMUX8_PINMUX8_19_16 | \
                       SYSCFG_PINMUX8_PINMUX8_15_12 | \
                       SYSCFG_PINMUX8_PINMUX8_11_8  | \
                       SYSCFG_PINMUX8_PINMUX8_7_4   | \
                       SYSCFG_PINMUX8_PINMUX8_3_0);

 HWREG(SOC_SYSCFG_0_REGS + SYSCFG0_PINMUX(8)) = \
      (PINMUX8_EMIF_D_ENABLE | savePinMux);

 savePinMux = HWREG(SOC_SYSCFG_0_REGS + SYSCFG0_PINMUX(5)) & \
                     ~(SYSCFG_PINMUX5_PINMUX5_31_28 | \
                       SYSCFG_PINMUX5_PINMUX5_27_24);

 HWREG(SOC_SYSCFG_0_REGS + SYSCFG0_PINMUX(5)) = \
      (PINMUX5_EMIF_BA_ENABLE | savePinMux);

 savePinMux = HWREG(SOC_SYSCFG_0_REGS + SYSCFG0_PINMUX(7)) & \
                     ~(SYSCFG_PINMUX7_PINMUX7_23_20 | \
                       SYSCFG_PINMUX7_PINMUX7_19_16 | \
                       SYSCFG_PINMUX7_PINMUX7_3_0);

 HWREG(SOC_SYSCFG_0_REGS + SYSCFG0_PINMUX(7)) = \
      (PINMUX7_EMIF_CTL_ENABLE | savePinMux);

 savePinMux = HWREG(SOC_SYSCFG_0_REGS + SYSCFG0_PINMUX(6)) & \
                     ~(SYSCFG_PINMUX6_PINMUX6_3_0);

 HWREG(SOC_SYSCFG_0_REGS + SYSCFG0_PINMUX(6)) = \
      (PINMUX6_EMA_CLK_ENABLE | savePinMux);

}
/*这里面涉及到了pinmux(12),pinmux(11),pinmux(9),pinmux(8),pinmux(5),pinmux(7),pinmux(6)这几个管脚复用。
通过查看手册SYSCFG Registers中的pin multiplexing control n register可以知道:
这些寄存器分别能够配置EMA_A[0]~EMA_A[7],EMA_A[8]~EMA_A[15],EMA_D[0]~EMA_D[7],EMA_D[8]~EMA_D[15],EMA_BA[0]~EMA_BA[1],EMA_CS2、EMA_OE、EMA_WE,EMA_CLK这些属性。
举一个例子

 volatile unsigned int savePinMux = 0;

 savePinMux = HWREG(SOC_SYSCFG_0_REGS + SYSCFG0_PINMUX(12)) & \
                     ~(SYSCFG_PINMUX12_PINMUX12_31_28 | \
                       SYSCFG_PINMUX12_PINMUX12_27_24 | \
                       SYSCFG_PINMUX12_PINMUX12_23_20 | \
                       SYSCFG_PINMUX12_PINMUX12_19_16 | \
                       SYSCFG_PINMUX12_PINMUX12_15_12 | \
                       SYSCFG_PINMUX12_PINMUX12_11_8  | \
                       SYSCFG_PINMUX12_PINMUX12_7_4   | \
                       SYSCFG_PINMUX12_PINMUX12_3_0);

 HWREG(SOC_SYSCFG_0_REGS + SYSCFG0_PINMUX(12)) = \
         (PINMUX12_EMIF_A_ENABLE | savePinMux);
/*savePinMux=0;
HWREG(SOC_SYSCFG_0_REGS + SYSCFG0_PINMUX(12))是用来指定pinmux寄存器的位置,

具体内容如下:
C6748对EDMA的操作和通过EMIFA与FPGA传输数据_第1张图片
寄存器位的含义定义如下:
C6748对EDMA的操作和通过EMIFA与FPGA传输数据_第2张图片
具体可参考OMAPL138 c6000 DSP+ARM Processor Technical Reference Manual.SYSCFG Registers一章。
(PINMUX12_EMIF_A_ENABLE | savePinMux)可以把各个寄存器配置成需要的形式。

#define PINMUX12_EMIF_A_ENABLE     (SYSCFG_PINMUX12_PINMUX12_31_28_EMA_A0 << \
                                    SYSCFG_PINMUX12_PINMUX12_31_28_SHIFT) | \
                                   (SYSCFG_PINMUX12_PINMUX12_27_24_EMA_A1 << \
                                    SYSCFG_PINMUX12_PINMUX12_27_24_SHIFT) | \
                                   (SYSCFG_PINMUX12_PINMUX12_23_20_EMA_A2 << \
                                    SYSCFG_PINMUX12_PINMUX12_23_20_SHIFT) | \
                                   (SYSCFG_PINMUX12_PINMUX12_19_16_EMA_A3 << \
                                    SYSCFG_PINMUX12_PINMUX12_19_16_SHIFT) | \
                                   (SYSCFG_PINMUX12_PINMUX12_15_12_EMA_A4 << \
                                    SYSCFG_PINMUX12_PINMUX12_15_12_SHIFT) | \
                                   (SYSCFG_PINMUX12_PINMUX12_11_8_EMA_A5 << \
                                    SYSCFG_PINMUX12_PINMUX12_11_8_SHIFT) | \
                                   (SYSCFG_PINMUX12_PINMUX12_7_4_EMA_A6 << \
                                    SYSCFG_PINMUX12_PINMUX12_7_4_SHIFT) | \
                                   (SYSCFG_PINMUX12_PINMUX12_3_0_EMA_A7 << \
                                    SYSCFG_PINMUX12_PINMUX12_3_0_SHIFT)

C6748对EDMA的操作和通过EMIFA与FPGA传输数据_第3张图片


其他几个函数类似,接下来看一下((short *)SOC_EMIFA_CS2_ADDR)[0x0011] = 0x0000;
    ((short *)SOC_EMIFA_CS2_ADDR)[0x0088] = 0x0000;
short型的地址,表示它的位数是十六位,0x0011可以看成是偏移,从/** \brief Base address of EMIFA_CS2 memory                                   */
#define SOC_EMIFA_CS2_ADDR                  (0x60000000)偏移到了0x60000011
第二是指向0x60000088这个地址。

/******************************************************************/
/* */
/* GPIO 管脚初始化 */
/* */
/******************************************************************/
void GPIOBankPinInit(void)
{
// 配置 LED 对应管脚为输出管脚
// OMAPL138 及 DSP C6748 共有 144 个 GPIO
// 以下为各组 GPIO BANK 起始管脚对应值
// 范围 1-144
// GPIO0[0] 1
// GPIO1[0] 17
// GPIO2[0] 33
// GPIO3[0] 49
// GPIO4[0] 65
// GPIO5[0] 81
// GPIO6[0] 97
// GPIO7[0] 113
// GPIO8[0] 129

GPIODirModeSet(SOC_GPIO_0_REGS, 141, GPIO_DIR_INPUT);   // EMIF_Beam GPIO8[12]
GPIODirModeSet(SOC_GPIO_0_REGS, 22, GPIO_DIR_INPUT);// EMIF_Data GPIO1[5]

}

void GPIODirModeSet(unsigned int baseAdd, unsigned int pinNumber,
unsigned int pinDir)

{
unsigned int regNumber = 0;
unsigned int pinOffset = 0;

/*
** Each register contains settings for each pin of two banks. The 32 bits
** represent 16 pins each from the banks. Thus the register number must be
** calculated based on 32 pins boundary.
*/
regNumber = (pinNumber - 1)/32;

/*
** In every register the least significant bits starts with a GPIO number on
** a boundary of 32. Thus the pin offset must be calculated based on 32
** pins boundary. Ex: 'pinNumber' of 1 corresponds to bit 0 in 
** 'register_name01'.
*/
pinOffset = (pinNumber - 1) % 32;

if(GPIO_DIR_OUTPUT == pinDir)
{
    HWREG(baseAdd + GPIO_DIR(regNumber)) &= ~(1 << pinOffset);
}
else
{
    HWREG(baseAdd + GPIO_DIR(regNumber)) |= (1 << pinOffset);
}

}
从技术手册上syscfg和gpio相应章节可以判断出上述两个函数会将GPIO8[12]、GPIO1[5]管脚配置为普通的输入口。

/****************************************************************************/
/*                                                                          */
/*              GPIO 管脚中断初始化                                         */
/*                                                                          */
/****************************************************************************/
void GPIOBankPinInterruptInit(void)
{

    // 配置  GPIO1[5]  为下降沿触发

    GPIOIntTypeSet(SOC_GPIO_0_REGS, 22, GPIO_INT_TYPE_FALLEDGE);
    // 使能 GPIO BANK 中断

    GPIOBankIntEnable(SOC_GPIO_0_REGS, 1);
    // 注册中断服务函数
    IntRegister(C674X_MASK_INT5, EMIFA_Data);

    // 映射中断到 DSP 可屏蔽中断
    IntEventMap(C674X_MASK_INT5, SYS_INT_GPIO_B1INT);

    // 使能 DSP 可屏蔽中断
    IntEnable(C674X_MASK_INT5);

}
下面看一下
IntEventMap(C674X_MASK_INT5, SYS_INT_GPIO_B1INT)这个函数

void IntEventMap (unsigned int cpuINT, unsigned int sysINT)
{
unsigned int dspintcREG, restoreVal;

/* Check the CPU maskable interrupt number */
ASSERT(((cpuINT >= 4) && (cpuINT <= 15)));

/* Check the system event number */
ASSERT((sysINT <= 127));

/* Get the address of the correct interrupt mux register */
dspintcREG = SOC_INTC_0_REGS + DSPINTC_INTMUX((cpuINT >> 2));

/* Disable interrupts */
restoreVal = IntGlobalDisable();

/* Clear and set INTSELx with system event number */
HWREG(dspintcREG) = (HWREG(dspintcREG) &
        ~DSPINTC_INTMUX_INTSEL(cpuINT)) |
        (sysINT << DSPINTC_INTMUX_INTSEL_SHIFT(cpuINT));

/* Clear any residual interrupt */
ICR = (1 << cpuINT);

/* Restore interrupts */
IntGlobalRestore(restoreVal);

}
dspintcREG = SOC_INTC_0_REGS + DSPINTC_INTMUX((cpuINT >> 2));得到0x01800104,查阅手册可知该位置为Interrupt mux register 1的位置。
HWREG(dspintcREG) = (HWREG(dspintcREG) &
~DSPINTC_INTMUX_INTSEL(cpuINT)) |
(sysINT << DSPINTC_INTMUX_INTSEL_SHIFT(cpuINT));

/******************************************************************/
/* */
/* 宏定义 */
/* */
/******************************************************************/

// 最大 ACOUNT
#define MAX_ACOUNT        (256*2*8u)

// 最大 BCOUNT
#define MAX_BCOUNT        (4u)

// 最大 CCOUNT
#define MAX_CCOUNT        (1u)

#define MAX_BUFFER_SIZE   (MAX_ACOUNT * MAX_BCOUNT * MAX_CCOUNT)
这里的几个宏定义含义如下:
在A类同步传输中,每个EDMA3同步事件初始化
ACOUNT个字节的一维数组或数列,BCOUNT*ACOUNT个字节构成一个帧,最大有COUNT个帧,BCOUNT*COUNT个事件构成一个参数RAM集。

数列之间的间隔取决于 SRCBIDX 和 DSTBIDX,数列 N 的起始地址等于数列 N-1 的起始地址加上源地址(SRCBIDX)或者目的地址(DSTBIDX)偏移量。

帧之间的间隔取决于 SRCCIDX 和 DSTCIDX,在 A 类传输中,当一个帧完成传输后,更新的传输地址为上一个帧最后一个数列的起始地址加上 SRCCIDX /DSTCIDX, SRCCIDX /DSTCIDX 的值是帧 1第一个数列的起始地址减去帧 0 的第三个数列的起始地址。

C6748对EDMA的操作和通过EMIFA与FPGA传输数据_第4张图片

#define CHTYPE_DMA //与后面的ifdef有关
#define chipsig0addr   (0x01C14174)//和中断有关
#define EMIF_BUFFER_LENGTH 256//EMIF存放数据的长度,256个字节
#define EMIF_INIT          24//EMIF的中断号
#define SHARED_BUFFER_ADDR 0x80000000//共享内存的地址1
#define SHARED_BUFFER_ADDR1 0x80001500//共享内存的地址2
volatile int irqRaised;

// 参数
#ifdef CHTYPE_DMA
unsigned int chType     = EDMA3_CHANNEL_TYPE_DMA;//
unsigned int chNum      = 0;
unsigned int tccNum     = 0;
unsigned int edmaTC     = 0;
unsigned int syncType   = EDMA3_SYNC_A;
unsigned int trigMode   = EDMA3_TRIG_MODE_MANUAL;
unsigned int evtQ       = 0; // 使用的事件队列
#else
unsigned int chType     = EDMA3_CHANNEL_TYPE_QDMA;
unsigned int chNum      = 0;
unsigned int tccNum     = 0;
unsigned int edmaTC     = 0;
unsigned int syncType   = EDMA3_SYNC_A;
unsigned int trigMode   = EDMA3_TRIG_MODE_QDMA;
unsigned int paRAMId    = 32u;
unsigned int evtQ       = 0; // 使用的事件队列
unsigned int opt        = 0;
#endif
因为前面定义过CHTYPE_DMA,所以这里就只执行前半部分

参数RAM的配置
paramSet.srcAddr = SOC_EMIFA_CS2_ADDR + 0x1200;//FPGA的数据的第一个通道存放地址
paramSet.destAddr = 0x80004000;
paramSet.aCnt = (unsigned short)256*2;//256个点,每个点是32位的,两个字节
paramSet.bCnt = (unsigned short)12*8;
paramSet.cCnt = (unsigned short)1;
paramSet.srcBIdx = (short)0;//FPGA八个通道上的数是同时产生的,把该地址上的数搬走之后,还要继续再从那个地方搬,这样才可以取到第二个通道
paramSet.destBIdx = (short)256*2;//目的地址是需要增加的
paramSet.srcCIdx = (short)0;//当前帧和下个帧之间的间隔为0,因为只有一个帧
paramSet.destCIdx = (short)0;
paramSet.linkAddr = (unsigned short)0x0820u;//当前参数ram中的信息被加载完后,下一个参数ram的地址
paramSet.bCntReload = (unsigned short)12*8u;//BCOUNT减到零之后,重新给它赋初值BCNT 是无符号的 16 位的值,用于重载 BCNT 的值,一旦帧中的最后一个数列传输完毕后.这个域仅用于 A 类同步传输中.在该种配下,每次发送请求提交后, EDMA3CC 将 BCNT 的值减一,当 BCNT 值为 0时, EDMA3CC 将对 CCNT 做减一操作,并且用 BCNTRLD 的值来初始化 BCNT的值.
paramSet.linkAddr = (unsigned short)0x0820u;
paramSet.bCntReload = (unsigned short)12*8u;
paramSet.opt = 0u;
// Src 及 Dest 使用 INCR 模式
paramSet.opt &= 0xFFFFFFFCu;//因为DAM和SAM的分别是第零和第一位
// 编程 TCC
paramSet.opt |= ((tccNum << EDMA3CC_OPT_TCC_SHIFT) & EDMA3CC_OPT_TCC);//TCC位于第12-17位,将tccNum左移12位,并与一个12到17位置1的数做与运算
paramSet.opt &= 0xFF1FFFFF;//其他位不变,将第21,22,23位置0
paramSet.opt |= (1 << EDMA3CC_OPT_TCINTEN_SHIFT);//将第20位置1,使能传输完成中断
C6748对EDMA的操作和通过EMIFA与FPGA传输数据_第5张图片
C6748对EDMA的操作和通过EMIFA与FPGA传输数据_第6张图片
源地址模式和目的地址模式都支持递增模式,没有对齐要求、A同步传输模式、参数ram不是静止的,可以更新和再传输请求被提交后进行地址链接。FWID不设置,没有利用FIFO。TCCMODE为0,只有当数据传输完成后才视为一次传输结束了。




          if (syncType == EDMA3_SYNC_A)
        {
            paramSet.opt &= 0xFFFFFFFBu;//将第2位置零
        }
          else
        {
            // AB Sync 传输模式
            paramSet.opt |= (1 << EDMA3CC_OPT_SYNCDIM_SHIFT);
        }

“`

你可能感兴趣的:(OMAPL138)