| 本帖最后由 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:
 
 状态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)&PDMA->DSCT[9].SA;
    desc[1].dest        = (uint32_t)&vga.line_buffer;
 但是,这个依赖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;
目前卡在这里,有官方的技术支持,可以回答一下问题不:
 https://bbs.21ic.com/icview-2940368-1-1.html
 
 |