本帖最后由 vsfopen 于 2020-4-10 23:06 编辑
M484的PDMA功能上相当强悍,可以用这个来实现一些时序,甚至硬件状态机
目前实现的测试代码里,配置完TIMER,PWM,PDMA,GPIO之后,基本只是启动4个定时器:
int main(void)
{
........
vsf_protect_t orig = vsf_protect_int();
TIMER0->CTL |= TIMER_CTL_CNTEN_Msk;
TIMER1->CTL |= TIMER_CTL_CNTEN_Msk;
TIMER2->CTL |= TIMER_CTL_CNTEN_Msk;
TIMER3->CTL |= TIMER_CTL_CNTEN_Msk;
while (1);
vsf_unprotect_int(orig);
return 0;
}
直接上波形:
蓝色是8位像素的最低位
绿色是行同步信号
黄色是场同步信号
紫色是场消隐信号
全部都是DMA自动生成的,用了比较特殊的实现方式。
可能新塘原来设计PDMA的时候,也不一定发现可以这么玩。
目前遇到一个问题,行像素输出的时候,没有递增。
用SWREQ测试的时候,可以看到DSCT里的CTL的TXCNT一直在递减,但是SA并没有递增(CTL里设置了Source递增,波形上也可以看到,像素信号高电平只有一个)。
uint8_t vga_buffer[240][320 + 1] = {
{0xFF},
};
这里需要依赖这个SA寄存器的递增,因为M484 ram不够放下640 * 480的画面,所以实际使用320 * 240,这样,一行需要输出2次。
实现原理就是通过特殊方法,用PDMA实现一个硬件状态机。
状态0的时候,读取并保存SA:
desc[1].ctl = (0 << PDMA_DSCT_CTL_TXCNT_Pos) | (2 << PDMA_DSCT_CTL_TXWIDTH_Pos) | (3 << PDMA_DSCT_CTL_DAINC_Pos) | (3 << PDMA_DSCT_CTL_SAINC_Pos) | PDMA_DSCT_CTL_TBINTDIS_Msk | (7 << PDMA_DSCT_CTL_BURSIZE_Pos) | (2 << PDMA_DSCT_CTL_OPMODE_Pos);
desc[1].src = (uint32_t)&PDMA->DSCT[9].SA;
desc[1].dest = (uint32_t)&vga.line_buffer;
状态2的时候,恢复原来的SA:
desc[1].ctl = (0 << PDMA_DSCT_CTL_TXCNT_Pos) | (2 << PDMA_DSCT_CTL_TXWIDTH_Pos) | (3 << PDMA_DSCT_CTL_DAINC_Pos) | (3 << PDMA_DSCT_CTL_SAINC_Pos) | PDMA_DSCT_CTL_TBINTDIS_Msk | (7 << PDMA_DSCT_CTL_BURSIZE_Pos) | (2 << PDMA_DSCT_CTL_OPMODE_Pos);
desc[1].src = (uint32_t)&vga.line_buffer;
desc[1].dest = (uint32_t)&PDMA->DSCT[9].SA;
但是,这个依赖SA的递增。
目前卡在这里,有官方的技术支持,可以回答一下问题不:
https://bbs.21ic.com/icview-2940368-1-1.html
|