小白尝试编写裸机下的DMA驱动
按照指导手册将描述符的地址写入到寄存器中,DMA就能获得相应的信息,但是操作后始终得不到,想请问可能的原因是什么。手册中的指导步骤中有一步 将描述符写入内存具体是什么意思呢。
有参考xboot大佬代码
struct dma_d1_desc_t {
uint32_t config;
uint32_t src;
uint32_t dst;
uint32_t count;
uint32_t para;
uint32_t link;
uint32_t reserved[2];
};
#pragma pack () /*取消指定对齐,恢复缺省对齐*/
struct dma_d1_desc_t DMA_DESCRIPTION;
uint8_t dma_init(uint8_t dmaNo)
{
virtual_addr_t addr;
uint32_t val;
write32(D1_CCU_BASE + CCU_PSI_CLK_REG, (2 << 0) | (0 << 8));
write32(D1_CCU_BASE + CCU_PSI_CLK_REG, read32(D1_CCU_BASE + CCU_PSI_CLK_REG) | (0x03 << 24));
sdelaydma(20);
/* Dma reset */
write32(D1_CCU_BASE + CCU_DMA_BGR_REG, read32(D1_CCU_BASE + CCU_DMA_BGR_REG) | (1 << 16));
sdelaydma(20);
/* Enable gating clock for dma */
write32(D1_CCU_BASE + CCU_DMA_BGR_REG, read32(D1_CCU_BASE + CCU_DMA_BGR_REG) | (1 << 0));
//判断通道是否空闲
addr = DMA_BASE+DMA_STA_REG;
val = read32(addr);
if(val & (1<<dmaNo)) //当前通道繁忙
{
return 0;
}
else
{ addr = DMA_BASE + DMA_AUTO_GATE_REG;
write32(addr,0x0);
addr = DMA_BASE+DMA_EN_REGN(dmaNo);
write32(addr,0x0);
addr = DMA_BASE+DMA_PAU_REGN(dmaNo);
write32(addr,0x1);
addr = DMA_BASE+DMA_DESC_ADDR_REGN(dmaNo);
write32(addr,0xfffff800);
addr = DMA_BASE+DMA_MODE_REFEN(dmaNo);
write32(addr,0x0);
return 1;
}
}
void dma_send(uint8_t dmaNo,uint32_t sourceaddress,uint32_t length)
{
DMA_DESCRIPTION.config = DMA_SET_CONFIG();//设置描述符中的config
DMA_DESCRIPTION.src = (uint32_t)sourceaddress; //设置描述符中的源地址为要发送的数据数组地址
DMA_DESCRIPTION.dst = (uint32_t)(UART0_BASE+UART_THR); //设置描述符中的目标地址为Uart0的数据发送寄存器地址
DMA_DESCRIPTION.count = (uint32_t)length; //设置描述符中的发送数据的长度
DMA_DESCRIPTION.para = DMA_SET_PARA(); //设置描述符中的参数
DMA_DESCRIPTION.link = 0xfffff800; //设置描述符中的连接地址
uint32_t configaddr = (uint32_t)(&DMA_DESCRIPTION);
uint32_t addr_true = (uint32_t)((configaddr <<2)|(configaddr >>30));
smp_mb();
write32(DMA_BASE + DMA_DESC_ADDR_REGN(dmaNo), (uint32_t)addr_true ****粗体字****); //将描述符地址写入描述符地址寄存器
write32(DMA_BASE + DMA_EN_REGN(dmaNo), 1); //使能对应的通道
delay_ms(3000);
write32(DMA_BASE + DMA_PAU_REGN(dmaNo), 0); //恢复通道传输
write32(DMA_BASE + DMA_EN_REGN(dmaNo), 0);
//关闭相应通道使能
}
还望大佬不吝赐教!!