基于STM32的SDIO用4位总线24MHZDMA模式操作SHDC卡

出处:eefocus 发布于:2018-07-20 13:38:00

  发现网上很多所谓的SDIO操作SHDC无意例外都是的那个烂玩意,完全没有修改过,所以很多时候根本无法初始化SHDC,我也在网上看到很多人关于这部分的疑问,虽然STM32的SDIO的确是可以这样操作。但是很佩服那群人,什么都没改就发上来,把哥我害惨了。。。。

  经过查资料,追踪,运气可佳。我发现自己的金士顿4GSD卡(class4)不能初始化跟用4位总线dma操作的原因。。各位也可以上网去找别人的试试,很多人都说不能用4位总线操作,而且用1位总线也只能是在低速率以及开启流控的情况下。而且经常出错。而4位总线总是提示没有检测到起始位。

  但是他们都只会问,都没有去想象为什么,我也是。。但是后来发现。STM32的SDIO是完全没问题的,可以读写SHDC,用4位总线24MHZ工作在DMA模式,大家看我修改出来的例程就知道了。看我改过的地方,对比下的。

  首先:

  在配置的时候, 一开始的时候sd卡需要有至少发74个时钟使它自己初始话,这是2.0规范要求的,但是你们自己看看的,完全没有这个,我一直追踪,发先在电源初始化那里就已经卡住了- -|||。

  于是我在那里面加入了一个发送74个时钟的小代码。

  SD_Error SD_PowerON(void)

  {

  SD_Error errorstatus = SD_OK;

  uint32_t response = 0, count = 0;

  bool validvoltage = FALSE;

  uint32_t SDType = SD_STD_CAPACITY;

  int16_t i = 0;

  /* Power ON Sequence -------------------------------------------------------*/

  /* Configure the SDIO peripheral */

  SDIO_InitStructure.SDIO_ClockDiv = SDIO_INIT_CLK_DIV; /* HCLK = 72MHz, SDIOCLK = 72MHz, SDIO_CK = HCLK/(178 + 2) = 400 KHz */

  SDIO_InitStructure.SDIO_ClockEdge = SDIO_ClockEdge_Rising;

  SDIO_InitStructure.SDIO_ClockBypass = SDIO_ClockBypass_Disable;

  SDIO_InitStructure.SDIO_ClockPowerSave = SDIO_ClockPowerSave_Disable;

  SDIO_InitStructure.SDIO_BusWide = SDIO_BusWide_1b;

  SDIO_InitStructure.SDIO_HardwareFlowControl = SDIO_HardwareFlowControl_Disable;

  SDIO_Init(&SDIO_InitStructure);

  /* Set Power State to ON */

  SDIO_SetPowerState(SDIO_PowerState_ON);

  /* Enable SDIO Clock */

  SDIO_ClockCmd(ENABLE);

  /* CMD0: GO_IDLE_STATE -------------------------------------------------------*/

  /* No CMD response required */

  SDIO_CmdInitStructure.SDIO_Argument = 0x0;

  SDIO_CmdInitStructure.SDIO_CmdIndex = SDIO_GO_IDLE_STATE;

  SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_No;

  SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No;

  SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable;

  for(;i < 74; i++)

  {

  SDIO_SendCommand(&SDIO_CmdInitStructure);

  CmdError();

  }

  看到没有,就是画线的那个,这个用37也可以了。但是规范点用74、

  接下来,自己初始化可以通过了,因为上电正确一般是可以初始化正常的,这个没什么问题,到了这个函数就开始有问题了。

  status = SD_SelectDeselect((u32) (SDCardInfo.RCA << 16));

  if (status != SD_OK)

  {

  rt_kprintf("SD_SelectDeselect is  error./n");

  goto __return;

  }

  rt_kprintf("SD set to transfer mode./n");

  status = SD_EnableWideBusOperATIon(SDIO_BusWide_4b);

  就是这个函数,使能四位总线模式的函数。事实上,在经过上的操作后,配置总线的时候我是这么配置的:

  SDIO_InitStructure.SDIO_ClockDiv = SDIO_TRANSFER_CLK_DIV +5 ;

  SDIO_InitStructure.SDIO_ClockEdge = SDIO_ClockEdge_Rising;

  SDIO_InitStructure.SDIO_ClockBypass = SDIO_ClockBypass_Disable;

  SDIO_InitStructure.SDIO_ClockPowerSave = SDIO_ClockPowerSave_Disable;

  SDIO_InitStructure.SDIO_BusWide = SDIO_BusWide_1b;

  SDIO_InitStructure.SDIO_HardwareFlowControl = SDIO_HardwareFlowControl_Enable;

  SDIO_Init(&SDIO_InitStructure);

  我发现加入流控是必须 的,避免出现数据出错,因为这个模式很不稳定,很多时候会出现overrun的错误,或者crc错误。这时候我们可以先不要调用SD_EnableWideBusOperation(SDIO_BusWide_4b);

  这样的话,其实我们是可以直接操作读写SHDC的,但是会发现不仅速度低,而且经常出错。这就是我为什么拼命要搞出四位总线的原因。

  所以首先要SD_SelectDeselect((u32) (SDCardInfo.RCA << 16));命令选择SD为传送模式后,要再调用SD_EnableWideBusOperation(SDIO_BusWide_4b)配置总线为四位总线模式;这是为了能够以更快的速度读取SHDC卡。事实上这个函数是有问题的。传送是命令是没有问题的,但是判断依据问题不小。

  大家看我的代码

  SD_Error SD_EnableWideBusOperation(u32 WideMode)

  {

  SD_Error errorstatus = SD_OK;

  /* MMC Card doesn't support this feature */

  if (SDIO_MULTIMEDIA_CARD == CardType)

  {

  errorstatus = SD_UNSUPPORTED_FEATURE;

  rt_kprintf("SD unsupported feature./n");

  return(errorstatus);

  }

  else if ((SDIO_STD_CAPACITY_SD_CARD_V1_1 == CardType) || (SDIO_STD_CAPACITY_SD_CARD_V2_0 == CardType) || (SDIO_HIGH_CAPACITY_SD_CARD == CardType))

  {

  if (SDIO_BusWide_8b == WideMode)

  {

  errorstatus = SD_UNSUPPORTED_FEATURE;

  rt_kprintf("SD unsupported feature./n");

  return(errorstatus);

  }

  else if (SDIO_BusWide_4b == WideMode)

  {

  errorstatus = SDEnWideBus(ENABLE);

  if (SD_OK == errorstatus)

  {

  /* Configure the SDIO peripheral */

  SDIO_InitStructure.SDIO_ClockDiv = SDIO_TRANSFER_CLK_DIV;

  SDIO_InitStructure.SDIO_ClockEdge = SDIO_ClockEdge_Rising;

  SDIO_InitStructure.SDIO_ClockBypass = SDIO_ClockBypass_Disable;

  SDIO_InitStructure.SDIO_ClockPowerSave = SDIO_ClockPowerSave_Disable;

  SDIO_InitStructure.SDIO_BusWide = SDIO_BusWide_4b;

  SDIO_InitStructure.SDIO_HardwareFlowControl = SDIO_HardwareFlowControl_Disable;

  SDIO_Init(&SDIO_InitStructure);

  }

  else

  rt_kprintf("SD enable wide bus fail./n");

  }

  else

  {

  errorstatus = SDEnWideBus(DISABLE);

  if (SD_OK == errorstatus)

  {

  /* Configure the SDIO peripheral */

  SDIO_InitStructure.SDIO_ClockDiv = SDIO_TRANSFER_CLK_DIV;

  SDIO_InitStructure.SDIO_ClockEdge = SDIO_ClockEdge_Rising;

  SDIO_InitStructure.SDIO_ClockBypass = SDIO_ClockBypass_Disable;

  SDIO_InitStructure.SDIO_ClockPowerSave = SDIO_ClockPowerSave_Disable;

  SDIO_InitStructure.SDIO_BusWide = SDIO_BusWide_1b;

  SDIO_InitStructure.SDIO_HardwareFlowControl = SDIO_HardwareFlowControl_Disable;

  SDIO_Init(&SDIO_InitStructure);

  }

  else

  rt_kprintf("SD disable wide bus fail./n");

  }

  }

  return(errorstatus);

  }

  注意到这个函数SDEnWideBus(ENABLE);

  static SD_Error SDEnWideBus(FunctionalState NewState)

  {

  SD_Error errorstatus = SD_OK;

  uint32_t scr[2] = {0, 0};

  if (SDIO_GetResponse(SDIO_RESP1) & SD_CARD_LOCKED)

  {

  errorstatus = SD_LOCK_UNLOCK_FAILED;

  rt_kprintf("sd locke unlock faile:in line 2537./n");

  return(errorstatus);

  }

  /* Get SCR Register */

  errorstatus = FindSCR(RCA, scr);

  /*首先注意到这个函数这个函数会卡到。*/

  if (errorstatus != SD_OK)

  {

  rt_kprintf("get scr register error:in line4 2547./n");

  return(errorstatus);

  }

  /* If wide bus operation to be enabled */

  if (NewState == ENABLE)

  {

  /* If requested card supports wide bus operation */

  //  if ((scr[1] & SD_WIDE_BUS_SUPPORT) != SD_ALLZERO)

  //  {

  /* Send CMD55 APP_CMD with argument as card's RCA.*/

  SDIO_CmdInitStructure.SDIO_Argument = (uint32_t) RCA << 16;

  SDIO_CmdInitStructure.SDIO_CmdIndex = SDIO_APP_CMD;

  SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_Short;

  SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No;

  SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable;

  SDIO_SendCommand(&SDIO_CmdInitStructure);

  errorstatus = CmdResp1Error(SDIO_APP_CMD);

  if (errorstatus != SD_OK)

  {

  rt_kprintf("send card rca fail: in line 2568./n");

  return(errorstatus);

  }

  /* Send ACMD6 APP_CMD with

  /* Send ACMD6 APP_CMD with argument as 2 for wide bus mode */

  SDIO_CmdInitStructure.SDIO_Argument = 0x2;

  SDIO_CmdInitStructure.SDIO_CmdIndex = SDIO_APP_SD_SET_BUSWIDTH;

  SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_Short;

  SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No;

  SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable;

  SDIO_SendCommand(&SDIO_CmdInitStructure);

  errorstatus = CmdResp1Error(SDIO_APP_SD_SET_BUSWIDTH);

  if (errorstatus != SD_OK)

  {

  rt_kprintf("send wide bus mode fail: in line 2586./n");

  return(errorstatus);

  }

  return(errorstatus);

  // }

  //  else

  //   {

  //     errorstatus = SD_REQUEST_NOT_APPLICABLE;

  //   rt_kprintf("sd reques no applicable : in line 2592./n");

  //      return(errorstatus);

  //   }

  }   /* If wide bus operation to be disabled */

  else

  {

  /* If requested card supports 1 bit mode operation */

  if ((scr[1] & SD_SINGLE_BUS_SUPPORT) != SD_ALLZERO)

  {

  /* Send CMD55 APP_CMD with argument as card's RCA.*/

  SDIO_CmdInitStructure.SDIO_Argument = (uint32_t) RCA << 16;

  SDIO_CmdInitStructure.SDIO_CmdIndex = SDIO_APP_CMD;

  SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_Short;

  SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No;

  SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable;

  SDIO_SendCommand(&SDIO_CmdInitStructure);

  errorstatus = CmdResp1Error(SDIO_APP_CMD);

  if (errorstatus != SD_OK)

  {

  rt_kprintf("send wide bus mode fail: in line 2586./n");

  return(errorstatus);

  }

  /* Send ACMD6 APP_CMD with argument as 2 for wide bus mode */

  SDIO_CmdInitStructure.SDIO_Argument = 0x00;

  SDIO_CmdInitStructure.SDIO_CmdIndex = SDIO_APP_SD_SET_BUSWIDTH;

  SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_Short;

  SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No;

  SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable;

  SDIO_SendCommand(&SDIO_CmdInitStructure);

  errorstatus = CmdResp1Error(SDIO_APP_SD_SET_BUSWIDTH);

  if (errorstatus != SD_OK)

  {

  rt_kprintf("send wide bus mode fail: in line 2586./n");

  return(errorstatus);

  }

  return(errorstatus);

  }

  else

  {

  errorstatus = SD_REQUEST_NOT_APPLICABLE;

  rt_kprintf("sd reques no applicable : in line 2592./n");

  return(errorstatus);

  }

  }

  }

  static SD_Error FindSCR(uint16_t rca, uint32_t *pscr)

  {

  uint32_t index = 0;

  SD_Error errorstatus = SD_OK;

  uint32_t tempscr[2] = {0, 0};

  uint16_t delay_time;

  /* Set Block Size To 8 Bytes */

  /* Send CMD55 APP_CMD with argument as card's RCA */

  SDIO_CmdInitStructure.SDIO_Argument = (uint32_t)8;

  SDIO_CmdInitStructure.SDIO_CmdIndex = SDIO_SET_BLOCKLEN;

  SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_Short;

  SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No;

  SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable;

  SDIO_SendCommand(&SDIO_CmdInitStructure);

  errorstatus = CmdResp1Error(SDIO_SET_BLOCKLEN);

  if (errorstatus != SD_OK)

  {

  rt_kprintf("send card rca fail :in line 2829./n");

  return(errorstatus);

  }

  /* Send CMD55 APP_CMD with argument as card's RCA */

  SDIO_CmdInitStructure.SDIO_Argument = (uint32_t) RCA << 16;

  SDIO_CmdInitStructure.SDIO_CmdIndex = SDIO_APP_CMD;

  SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_Short;

  SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No;

  SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable;

  SDIO_SendCommand(&SDIO_CmdInitStructure);

  errorstatus = CmdResp1Error(SDIO_APP_CMD);

  if (errorstatus != SD_OK)

  {

  rt_kprintf("send rca fail:in line 2845./n");

  return(errorstatus);

  }

  SDIO_DataInitStructure.SDIO_DataTimeOut = SD_DATATIMEOUT;

  SDIO_DataInitStructure.SDIO_DataLength = 8;

  SDIO_DataInitStructure.SDIO_DataBlockSize = SDIO_DataBlockSize_8b;

  SDIO_DataInitStructure.SDIO_TransferDir = SDIO_TransferDir_ToSDIO;

  SDIO_DataInitStructure.SDIO_TransferMode = SDIO_TransferMode_Block;

  SDIO_DataInitStructure.SDIO_DPSM = SDIO_DPSM_Enable;

  SDIO_DataConfig(&SDIO_DataInitStructure);

  /*经过测试,发现原来没有反应或者出错是因为缺少必要的处理时间,我这里是慢慢调试出来的比较理想的延时。  大家可以试试不加,有的卡运气好的可能通过了,但是不好的- -肯定没有数据。。。可能是看卡的质量吧,我只试过我的SD卡,不敢定论*/

  for(delay_time = 0; delay_time < 20; delay_time++)

  __nop();

  //SDIO_ClearFlag(SDIO_FLAG_STBITERR);

  /* Send ACMD51 SD_APP_SEND_SCR with argument as 0 */

  SDIO_CmdInitStructure.SDIO_Argument = 0x0;

  SDIO_CmdInitStructure.SDIO_CmdIndex = SDIO_SD_APP_SEND_SCR;

  SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_Short;

  SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No;

  SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable;

  SDIO_SendCommand(&SDIO_CmdInitStructure);

  errorstatus = CmdResp1Error(SDIO_SD_APP_SEND_SCR);

  if (errorstatus != SD_OK)

  {

  rt_kprintf("cmd Resp1 error : in line 2870./n");

  return(errorstatus);

  }

  while (!(SDIO->STA & (SDIO_FLAG_RXOVERR | SDIO_FLAG_DCRCFAIL | SDIO_FLAG_DTIMEOUT | SDIO_FLAG_DBCKEND | SDIO_FLAG_STBITERR

  )))

  {

  if (SDIO_GetFlagStatus(SDIO_FLAG_RXDAVL) != RESET)

  {

  *(tempscr + index) = SDIO_ReadData();

  index++;

  if (index == 2)

  break;

  }

  }

  if (SDIO_GetFlagStatus(SDIO_FLAG_DTIMEOUT) != RESET)

  {

  SDIO_ClearFlag(SDIO_FLAG_DTIMEOUT);

  errorstatus = SD_DATA_TIMEOUT;

  rt_kprintf("sd data timeout : inline 2886./n");

  return(errorstatus);

  }

  else if (SDIO_GetFlagStatus(SDIO_FLAG_DCRCFAIL) != RESET)

  {

  SDIO_ClearFlag(SDIO_FLAG_DCRCFAIL);

  errorstatus = SD_DATA_CRC_FAIL;

  rt_kprintf("sd data fail : inline 2886./n");

  return(errorstatus);

  }

  else if (SDIO_GetFlagStatus(SDIO_FLAG_RXOVERR) != RESET)

  {

  SDIO_ClearFlag(SDIO_FLAG_RXOVERR);

  errorstatus = SD_RX_OVERRUN;

  rt_kprintf("sd rx overrun : inline 2886./n");

  return(errorstatus);

  }

  else if (SDIO_GetFlagStatus(SDIO_FLAG_STBITERR) != RESET)

  {

  SDIO_ClearFlag(SDIO_FLAG_STBITERR);

  errorstatus = SD_START_BIT_ERR;

  rt_kprintf("sd can't not find start bit : inline 2886./n");

  return(errorstatus);

  }

  /* Clear all the static flags */

  SDIO_ClearFlag(SDIO_STATIC_FLAGS);

  *(pscr + 1) = ((tempscr[0] & SD_0TO7BITS) << 24) | ((tempscr[0] & SD_8TO15BITS) << 8) | ((tempscr[0] & SD_16TO23BITS) >> 8) | ((tempscr[0] & SD_24TO31BITS) >> 24);

  *(pscr) = ((tempscr[1] & SD_0TO7BITS) << 24) | ((tempscr[1] & SD_8TO15BITS) << 8) | ((tempscr[1] & SD_16TO23BITS) >> 8) | ((tempscr[1] & SD_24TO31BITS) >> 24);

  return(errorstatus);

  }

  看上面这个函数的里面的彩色代码。那个是我自己添加的,正如我所说的,的SDcard文件忽视了sd卡自己处理所需要的延时问题。我在这里面发现,如果不加入我这个延时,基本上,如果不先对SDIO_FLAG_STBITER置位的话,就会报错(一开始初始化成四位总线的,),要嘛没有反应(1位总线),进入死循环。。基本上能退出这个函数就是因为出错- -。库忽略掉了这个延时,才导致这样的结果(所以BS那些只拿的东西直接忽悠我们骗点数的人)。

  再注意下下一个彩色代码

  if (index == 2)

  break;

  知道为什么要等于2就退出吗?因为定义index的时候初始值是0,但是你们自己追踪下,事实上发送这条命令只会返回两个数据, 我的返回的是两个0.而返回两个数据后基本总线就没反映了,成了死循环- -(至少我的卡是这样, 别人的卡我就不知道了,不过市面的SHDC卡大多买的都是金士顿的吧?不知道我的金士顿卡有没有代表性。)

  基

  本上这样是能正常退出的,如果你们的卡不行,试着再降低下频率,我发现我的金士顿4G(class4)只有在小于12MHZ的一位总线下才有反应。当然, 是在没有配置为4位总线前。本上这个函数就到这里,接着再返回SDEnWideBus(FunctionalState NewState)函数看下里面的以下代码

  static SD_Error SDEnWideBus(FunctionalState NewState)

  {

  SD_Error errorstatus = SD_OK;

  uint32_t scr[2] = {0, 0};

  if (SDIO_GetResponse(SDIO_RESP1) & SD_CARD_LOCKED)

  {

  errorstatus = SD_LOCK_UNLOCK_FAILED;

  rt_kprintf("sd locke unlock faile:in line 2537./n");

  return(errorstatus);

  }

  /* Get SCR Register */

  errorstatus = FindSCR(RCA, scr);

  /*首先注意到这个函数这个函数会卡到。*/

  if (errorstatus != SD_OK)

  {

  rt_kprintf("get scr register error:in line4 2547./n");

  return(errorstatus);

  }

  /* If wide bus operation to be enabled */

  if (NewState == ENABLE)

  {

  /* If requested card supports wide bus operation */

  //  if ((scr[1] & SD_WIDE_BUS_SUPPORT) != SD_ALLZERO)

  //  {

  /* Send CMD55 APP_CMD with argument as card's RCA.*/

  SDIO_CmdInitStructure.SDIO_Argument = (uint32_t) RCA << 16;

  SDIO_CmdInitStructure.SDIO_CmdIndex = SDIO_APP_CMD;

  SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_Short;

  SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No;

  SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable;

  SDIO_SendCommand(&SDIO_CmdInitStructure);

  errorstatus = CmdResp1Error(SDIO_APP_CMD);

  if (errorstatus != SD_OK)

  {

  rt_kprintf("send card rca fail: in line 2568./n");

  return(errorstatus);

  }

  /* Send ACMD6 APP_CMD with argument as 2 for wide bus mode */

  SDIO_CmdInitStructure.SDIO_Argument = 0x2;

  SDIO_CmdInitStructure.SDIO_CmdIndex = SDIO_APP_SD_SET_BUSWIDTH;

  SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_Short;

  SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No;

  SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable;

  SDIO_SendCommand(&SDIO_CmdInitStructure);

  errorstatus = CmdResp1Error(SDIO_APP_SD_SET_BUSWIDTH);

  if (errorstatus != SD_OK)

  {

  rt_kprintf("send wide bus mode fail: in line 2586./n");

  return(errorstatus);

  }

  return(errorstatus);

  // }

  //  else

  //   {

  //     errorstatus = SD_REQUEST_NOT_APPLICABLE;

  //   rt_kprintf("sd reques no applicable : in line 2592./n");

  //      return(errorstatus);

  //   }

  }   /* If wide bus operation to be disabled */

  彩色的这些都是注释掉的呵,因为,事实上, findsrc函数返回的结果本身我就不知道是否是正确的,而且在sd2.0规范里面并没有仔细说明怎么切换总线模式,z只是要求先判断是否是传输模式,接着是否是上锁,之后就可以直接用CMD6修改总线操作模式了,所以至今没发现findsrc这个函数的作用。另外在规范里面我也没有找到提及findsrc这个函数的。于是直接忽略,将判断去掉,直接就设置成四位总线24MHZ,一开始不行, 我就降低频率,出现跟原来一样的反应,再降到12MHZ,突然有数据了, 于是又慢慢调试, 升到24MHZ,可以正常读写了。基本上改的就是这两个地方。其它地方因为目前没有研究的更深入没有发现问题,暂时就不改了。

  至此,我已经可以用STM32的SDIO4位总线DMA模式读写SHDC卡了。经过测试,可以用文件系统读写文件, 创建文件夹,但是不能替换文件名- -,肯能是文件系统有问题。

  附上我用的例程是rt_thread的文件系统, 算是为它小小宣传下,可能大家会用到, 基于MDK的rt_thread.工程在目录的bsp/stm32/里面。


关键词:STM32总线

版权与免责声明

凡本网注明“出处:维库电子市场网”的所有作品,版权均属于维库电子市场网,转载请必须注明维库电子市场网,https://www.dzsc.com,违反者本网将追究相关法律责任。

本网转载并注明自其它出处的作品,目的在于传递更多信息,并不代表本网赞同其观点或证实其内容的真实性,不承担此类作品侵权行为的直接责任及连带责任。其他媒体、网站或个人从本网转载时,必须保留本网注明的作品出处,并自负版权等法律责任。

如涉及作品内容、版权等问题,请在作品发表之日起一周内与本网联系,否则视为放弃相关权利。

相关技术资料
广告
上传BOM文件: BOM文件
*公司名:
*联系人:
*手机号码:
QQ:
应用领域:

有效期:
OEM清单文件: OEM清单文件
*公司名:
*联系人:
*手机号码:
QQ:
有效期:

扫码下载APP,
一键连接广大的电子世界。

在线人工客服

买家服务:
卖家服务:

0571-85317607

客服在线时间周一至周五
9:00-17:30

关注官方微信号,
第一时间获取资讯。

建议反馈

联系人:

联系方式:

按住滑块,拖拽到最右边
>>
感谢您向阿库提出的宝贵意见,您的参与是维库提升服务的动力!意见一经采纳,将有感恩红包奉上哦!