本帖最后由 SJPU 于 2022-9-11 21:10 编辑
IOMUX->remap6_bit.sdio2_gmux = 1;这一句改成IOMUX->remap6_bit.sdio2_gmux = 3;
#define MCU_CHIP_403A
#ifdef MCU_CHIP_403A
# undef SDIOx
# define SDIOx SDIO2
#elif (defined MCU_CHIP_407)
# undef SDIOx
# define SDIOx SDIO1
#else
#error "Unknown mcu target."
#endif
//static
void sdio_low_init(void)
{
#ifdef MCU_CHIP_403A /*for AT32F403A */
/* gpioc and gpiod periph clock enable */
crm_periph_clock_enable(CRM_GPIOA_PERIPH_CLOCK, TRUE);
crm_periph_clock_enable(CRM_IOMUX_PERIPH_CLOCK, TRUE);
/* sdio periph clock enable */
crm_periph_clock_enable(CRM_SDIO2_PERIPH_CLOCK, TRUE);
IOMUX->remap6_bit.sdio2_gmux = 3;
IOMUX->remap7_bit.swjtag_gmux = 2;
/* configure PA[7..2] */
uint32_t temp = GPIOA->cfglr & 0xff ;
temp |=
((2 << 10 ) | (2 << 8 ) /* PA2 复用推挽输出 */
|(2 << 14 ) | (2 << 12 ) /* PA3 复用推挽输出 */
|(2 << 18 ) | (2 << 16 ) /* PA4 复用推挽输出 */
|(2 << 22 ) | (2 << 20 ) /* PA5 复用推挽输出 */
|(2 << 26 ) | (2 << 24 ) /* PA6 复用推挽输出 */
|(2 << 30 ) | (2 << 28 )); /* PA7 复用推挽输出 */
GPIOA->cfglr = temp;
#elif (defined MCU_CHIP_407) /*for AT32F407 */
crm_periph_clock_enable(CRM_GPIOC_PERIPH_CLOCK, TRUE);
crm_periph_clock_enable(CRM_GPIOD_PERIPH_CLOCK, TRUE);
crm_periph_clock_enable(CRM_SDIO1_PERIPH_CLOCK, TRUE);
uint32_t temp = GPIOC->cfghr & (~0x00ffffF0);
temp |=
((2 << 6 ) | (2 << 4 ) /* PC8 复用推挽输出 */
|(2 << 10 ) | (2 << 8 ) /* PC9 复用推挽输出 */
|(2 << 14 ) | (2 << 12 ) /* PC10 复用推挽输出 */
|(2 << 18 ) | (2 << 16 ) /* PC11 复用推挽输出 */
|(2 << 22 ) | (2 << 20 )); /* PC12 复用推挽输出 */
GPIOC->cfghr = temp;
temp = GPIOD->cfglr & (~0xF00);
temp |= (2 << 10 ) | (2 << 8 ); /* PD2 复用推挽输出 */
GPIOD->cfglr = temp;
#endif
}
但是在403A上, SDIO2发送命令后SD卡一直不回应,SDIO报命令超时错误。
相同代码但在407上命令没问题,但用官方的sdio示例,写卡有问题:
sd_error_status_type sdio_command_data_send(sdio_command_struct_type *sdio_cmd_init_t, \
sdio_data_struct_type* sdio_data_init_t, uint32_t *buf)
{
.........
else if(device_mode == SD_TRANSFER_DMA_MODE)
{
if(sdio_data_init_t->transfer_direction == SDIO_DATA_TRANSFER_TO_CARD)
{
sd_dma_config(buf, length, DMA_DIR_MEMORY_TO_PERIPHERAL);
SDIOx->inten |= SDIO_INTR_STS_WRITE_MASK;
transfer_error = SD_OK;
transfer_end = 0;
sdio_dma_enable(SDIOx, TRUE);
}
while(!(SDIOx->sts & SDIOx->inten) && timeout)
{
timeout--;
if(transfer_end)
{
break;
}
}
if(timeout == 0)
{
sd_init();
return SD_DATA_TIMEOUT;
}
if(transfer_error != SD_OK)
{
status = transfer_error;
}
}
return status;
}
DMA传输写操作,DMA好像已经传输完毕了(数据传输量寄存器已经减为0,中断标志位也置1),SDIO的DTCNTR和BUFCNTR寄存器也减为0了,但SDIO却一直处于DOTX状态,然后就产生数据超时中断。不知为何。
完整的DMA代码如下:
if(device_mode == SD_TRANSFER_DMA_MODE)
{
transfer_error = SD_OK;
transfer_end = 0;
if(sdio_data_init_t->transfer_direction == SDIO_DATA_TRANSFER_TO_CONTROLLER)
{ /* 读操作 如果使用中断的话,应该使用DMA中断 */
/* sdio command config */
sdio_data_config(SDIOx, sdio_data_init_t);
/* enable dcsm */
sdio_data_state_machine_enable(SDIOx, TRUE);
sd_dma_config(buf, length, DMA_DIR_PERIPHERAL_TO_MEMORY);
SDIOx->inten |= SDIO_INTR_STS_READ_MASK;
SDIOx->inten &= ~((1 << 8) |(1 << 10)); //禁止数据完成中断
sdio_dma_enable(SDIOx, TRUE);
/* sdio command config */
sdio_command_config(SDIOx, sdio_cmd_init_t);
/* enable ccsm */
sdio_command_state_machine_enable(SDIOx, TRUE);
status = command_rsp1_error(sdio_cmd_init_t->cmd_index);
if(status != SD_OK)
{
return status;
}
}
if(sdio_data_init_t->transfer_direction == SDIO_DATA_TRANSFER_TO_CARD)
{ /* 写操作 如使用中断方式,则使用SDIO传输完成中断 */
sdio_data_config(SDIOx, sdio_data_init_t);
/* enable dcsm */
sdio_data_state_machine_enable(SDIOx, TRUE);
/* sdio command config */
sdio_command_config(SDIOx, sdio_cmd_init_t);
/* enable ccsm */
sdio_command_state_machine_enable(SDIOx, TRUE);
status = command_rsp1_error(sdio_cmd_init_t->cmd_index);
if(status != SD_OK)
{
return status;
}
sd_dma_config(buf, length, DMA_DIR_MEMORY_TO_PERIPHERAL);
SDIOx->inten |= SDIO_INTR_STS_WRITE_MASK;
sdio_dma_enable(SDIOx, TRUE);
}
OS_TASKEVENT event = OS_EVENT_GetMaskTimed(&sdio_event,
SDIO_EVENT_RECV_OK | SDIO_EVENT_SEND_OK,
20000);//200ms
if(event == 0 )
{
// sd_init();
return SD_DATA_TIMEOUT;
}
if(transfer_error != SD_OK)
{
status = transfer_error;
}
return SD_OK;
}
DMA读卡没问题,但写卡一直是这个问题。命令通道,数据通道,DMA通道 ,三者无论按什么次序配置都不好用。
希望官方有技术支持给解决一下。
改用PIO方式操作 也是读取没问题 ,写入不行。也是在数据写SDIOx->buf写完后,SDIO一直处于DOTX状态 ,然后就是数据超时中断。
|