STM32F103实现NandFlash做U盘,有盘符不能打开

2019-08-19 20:00发布

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

在STM32F103上使用外部的NandFlash做U盘,在原子的那个SD卡和W25Q128的基础上再加了一个盘(NandFlash)。
问题:为什么NandFlash不能像SD卡可以打开盘符,进行读写。
2.png
3.png

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1.现在NandFlash读写是没有问题的;可以正常读出NandID


2.改了几个地方:
1)mass_mal.h
/* Includes ------------------------------------------------------------------*/
#include "sys.h"

/* Exported types ------------------------------------------------------------*/
/* Exported constants --------------------------------------------------------*/
#define MAL_OK   0
#define MAL_FAIL 1
//#define MAX_LUN  1                //2个可移动磁盘 SD卡+FLASH
#define MAX_LUN  2                        //3个可移动磁盘 SD卡+FLASH+NandFlash

extern long long Mass_Memory_Size[MAX_LUN+1];
extern u32 Mass_Block_Size[MAX_LUN+1];
extern u32 Mass_Block_Count[MAX_LUN+1];

2)mass_mal.c
/**
  ******************************************************************************
  * @file    mass_mal.c
  * @author  MCD Application Team
  * @version V4.0.0
  * @date    21-January-2013
  * @brief   Medium Access Layer interface
  ******************************************************************************
  * @attention
  *
  * <h2><center>&copy; COPYRIGHT 2013 STMicroelectronics</center></h2>
  *
  * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
  * You may not use this file except in compliance with the License.
  * You may obtain a copy of the License at:
  *
  *        http://www.st.com/software_license_agreement_liberty_v2
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  *
  ******************************************************************************
  */


/* Includes ------------------------------------------------------------------*/
#include "platform_config.h"
#include "mass_mal.h"
#include "sdio_sdcard.h"
#include "w25qxx.h"
#include "fsmc_nand.h"

/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
long long Mass_Memory_Size[MAX_LUN+1];
u32 Mass_Block_Size[MAX_LUN+1];
u32 Mass_Block_Count[MAX_LUN+1];

/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/
/*******************************************************************************
* Function Name  : MAL_Init
* Description    : Initializes the Media on the STM32
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
uint16_t MAL_Init(uint8_t lun)
{
        u16 Status=MAL_OK;   
        switch (lun)
        {
                case 0:                             
                        break;                          
                case 1:                                 
                        break;
                case 2:
                        break;
                default:
                        return MAL_FAIL;
        }
        return Status;
}
/*******************************************************************************
* Function Name  : MAL_Write
* Description    : Write sectors
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
uint16_t MAL_Write(uint8_t lun, uint64_t Memory_Offset, uint32_t *Writebuff, uint16_t Transfer_Length)
{
        u8 STA;
        switch (lun)                //这里,根据lun的值确定所要操作的磁盘
        {
                case 0:                                 //磁盘0为 SPI FLASH盘       
                        STA=0;
                        W25QXX_Write((u8*)Writebuff, Memory_Offset, Transfer_Length);                     
                        break;
                case 1:                                //磁盘1为SD卡                  
                        STA=SD_WriteDisk((u8*)Writebuff, Memory_Offset>>9, Transfer_Length>>9);                     
                        break;
                case 2:
                       STA=FlashWriteOneSector(Memory_Offset, (u8*)Writebuff, Transfer_Length);
                        break;
                default:
                        return MAL_FAIL;
        }
        if(STA!=0)return MAL_FAIL;
        return MAL_OK;
}

/*******************************************************************************
* Function Name  : MAL_Read
* Description    : Read sectors
* Input          : None
* Output         : None
* Return         : Buffer pointer
*******************************************************************************/
uint16_t MAL_Read(uint8_t lun, uint64_t Memory_Offset, uint32_t *Readbuff, uint16_t Transfer_Length)
{
        u8 STA;
        switch (lun)                //这里,根据lun的值确定所要操作的磁盘
        {
                case 0:                                //磁盘0为 SPI FLASH盘         
                        STA=0;
                        W25QXX_Read((u8*)Readbuff, Memory_Offset, Transfer_Length);                     
                        break;          
                case 1:                                //磁盘1为SD卡                    
                        STA=SD_ReadDisk((u8*)Readbuff, Memory_Offset>>9, Transfer_Length>>9);          
                        break;
                case 2:
                        STA=FlashReadOneSector(Memory_Offset, (u8*)Readbuff, Transfer_Length);
                        break;
                default:
                        return MAL_FAIL;
        }
        if(STA!=0)return MAL_FAIL;
        return MAL_OK;
}

/*******************************************************************************
* Function Name  : MAL_GetStatus
* Description    : Get status
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
uint16_t MAL_GetStatus (uint8_t lun)
{
    switch(lun)
    {
                case 0:
                        return MAL_OK;
                case 1:
                        return MAL_OK;
                case 2:
                        return MAL_OK;
                default:
                        return MAL_FAIL;
    }
}

/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/


三、主程序:
extern u8 Max_Lun;        //支持的磁盘个数,0表示1个,1表示2个.

int main(void)
{         
        u8  ID_Code[5]={0,0,0,0,0};
        u8 offline_cnt=0;
        u8 tct=0;
        u8 USB_STA;
        u8 Divece_STA;             
        u8 i=0;
       
        delay_init();                             //延时函数初始化          
  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置中断优先级分组为组2:2位抢占优先级,2位响应优先级
        uart_init(115200);                 //串口初始化为115200
        usart3_init(9600);
        LED_Init();                                          //初始化与LED连接的硬件接口
        LCD_Init();                                           //初始化LCD   
        W25QXX_Init();                                //初始化W25Q128         
        FlashInit();                                  //NandFlash初始化
        my_mem_init(SRAMIN);        //初始化内部内存池
        delay_ms(1000);                                  

        POINT_COLOR=RED;//设置字体为红 {MOD}          
        LCD_ShowString(30,50,200,16,16,"WarShip STM32");       
        LCD_ShowString(30,70,200,16,16,"USB Card Reader TEST");       
        LCD_ShowString(30,90,200,16,16,"ATOM@ALIENTEK");
        LCD_ShowString(30,110,200,16,16,"2015/1/29");       
        W25QXX_Init();

        u3_printf("Start Test NandFlash ");


        //Nand Flash ID = EC,F1,00,95  Type = K9F1G08U0B
        FlashReadId(ID_Code);
        for(i=0; i <5; ++i)
        {
                        u3_printf("%2x ",ID_Code);
        }
        u3_printf(" ");

        if ((ID_Code[0] == 0xEC) && (ID_Code[1] == 0xF1)&& (ID_Code[2] == 0x00) && (ID_Code[3] == 0x95))
  {
                                /* only one zone is used */
                                //计算磁盘大小   =实际大小-备用块大小
                                Mass_Block_Count[2] = FLASH_MAX_SECTOR_ADDR/FLASH_SECTOR_SIZE; //NAND_ZONE_SIZE * NAND_BLOCK_SIZE * NAND_MAX_ZONE ;
                                Mass_Block_Size[2]  = FLASH_SECTOR_SIZE;//NAND_PAGE_SIZE;
                                Mass_Memory_Size[2] = (Mass_Block_Count[2] * Mass_Block_Size[2]);
                                u3_printf("Type = K9F1G08U0B ");

                                //LCD_ShowString(30,170,200,16,16,"Type = K9F1G08U0B");                        
  }
        else
        {
                                Max_Lun--;
                                u3_printf("NandFlash Error! ");
               
                                //LCD_ShowString(30,170,200,16,16,"NandFlash Error!");        //检测SD卡错误
        }       

        //SD卡
        if(SD_Init())
        {
                                //Max_Lun=0;                                                                                        //SD卡错误,则仅只有一个磁盘.
                                Max_Lun--;
                                u3_printf("SD Card Error! ");               
               
                                //LCD_ShowString(30,130,200,16,16,"SD Card Error!");        //检测SD卡错误
        }
        else //SD 卡正常
        {                                                                                                                             
                                //LCD_ShowString(30,130,200,16,16,"SD Card Size:     MB");
                                Mass_Memory_Size[1]=SDCardInfo.CardCapacity;                //得到SD卡容量(字节),当SD卡容量超过4G的时候,需要用到两个u32来表示
                                Mass_Block_Size[1] =512;                                                        //因为我们在Init里面设置了SD卡的操作字节为512个,所以这里一定是512个字节.
                                Mass_Block_Count[1]=Mass_Memory_Size[1]/Mass_Block_Size[1];
                                u3_printf("SD Card Volume:%d ", Mass_Memory_Size[1]>>20);               

                                //LCD_ShowNum(134,130,Mass_Memory_Size[1]>>20,5,16);        //显示SD卡容量
        }
       
        //W25Q128
        if(W25QXX_TYPE!=W25Q128)
        {
                                //LCD_ShowString(30,130,200,16,16,"W25Q128 Error!");        //检测SD卡错误
                                u3_printf("W25Q128 Error! ");               
        }
        else //SPI FLASH 正常
        {                                                                                                                             
                                Mass_Memory_Size[0]=1024*1024*12;        //前12M字节
                                Mass_Block_Size[0] =512;                        //设置SPI FLASH的操作扇区大小为512
                                Mass_Block_Count[0]=Mass_Memory_Size[0]/Mass_Block_Size[0];
                                u3_printf("SPI FLASH Size:12MB ");               
               
                                //LCD_ShowString(30,150,200,16,16,"SPI FLASH Size:12MB");         
        }
       
        delay_ms(1800);
        USB_Port_Set(0);         //USB先断开
        delay_ms(700);
        USB_Port_Set(1);        //USB再次连接
        //LCD_ShowString(30,170,200,16,16,"USB Connecting...");        //提示USB开始连接         
      u3_printf("USB Connecting... ");               
        Data_Buffer=mymalloc(SRAMIN,BULK_MAX_PACKET_SIZE*2*4);        //为USB数据缓存区申请内存
        Bulk_Data_Buff=mymalloc(SRAMIN,BULK_MAX_PACKET_SIZE);        //申请内存

        //USB配置
        USB_Interrupts_Config();   
        Set_USBClock();   
        USB_Init();            
        delay_ms(1800);                       
        while(1)
        {       
                delay_ms(1);                                  
                if(USB_STA!=USB_STATUS_REG)//状态改变了
                {                                                           
                                LCD_Fill(30,190,240,190+16,WHITE);//清除显示                                    
                               
                                if(USB_STATUS_REG&0x01)//正在写                  
                                {
                                                LCD_ShowString(30,190,200,16,16,"USB Writing...");//提示USB正在写入数据         
                                }
                               
                                if(USB_STATUS_REG&0x02)//正在读
                                {
                                                LCD_ShowString(30,190,200,16,16,"USB Reading...");//提示USB正在读出数据                   
                                }
                               
                                if(USB_STATUS_REG&0x04)
                                                LCD_ShowString(30,210,200,16,16,"USB Write Err ");//提示写入错误
                                else
                                                LCD_Fill(30,210,240,210+16,WHITE);//清除显示          
                               
                                if(USB_STATUS_REG&0x08)
                                                LCD_ShowString(30,230,200,16,16,"USB Read  Err ");//提示读出错误
                                else
                                                LCD_Fill(30,230,240,230+16,WHITE);//清除显示   
                               
                                USB_STA=USB_STATUS_REG;//记录最后的状态
                }
               
                if(Divece_STA!=bDeviceState)
                {
                                if(bDeviceState==CONFIGURED)
                                                LCD_ShowString(30,170,200,16,16,"USB Connected    ");//提示USB连接已经建立
                                else
                                                LCD_ShowString(30,170,200,16,16,"USB DisConnected ");//提示USB被拔出了
                               
                                Divece_STA=bDeviceState;
                }
               
                tct++;
                if(tct==200)
                {
                                tct=0;
                                LED0=!LED0;//提示系统在运行
                                if(USB_STATUS_REG&0x10)
                                {
                                                offline_cnt=0;//USB连接了,则清除offline计数器
                                                bDeviceState=CONFIGURED;
                                }
                                else//没有得到轮询
                                {
                                                offline_cnt++;  
                                                if(offline_cnt>10)bDeviceState=UNCONNECTED;//2s内没收到在线标记,代表USB被拔出了
                                }
                               
                                USB_STATUS_REG=0;
                }
        };
}



////////////////////////////////////////////////////
附件是编译通过的工程文件,麻烦大家给看一下问题出在哪儿。非常感谢,已经卡了三四天了,郁闷。

友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
2条回答
muzilili
2019-08-19 20:14
晕,怎么后面代码是斜体的,不好意思了,可以直接下载附件看
1.nand的实现是网上找的一个这个型号的例程,测试了一下读写,应该是没有问题的;
2.主要改了USB跟Mass相关的,其他的没怎么动,可以看到有盘符;
3.但是盘符不能操作,不知道还有哪儿需要修改;
4.比较奇怪的是。可以看到3个盘符,除了NandFlash的这个,其他的两个都可以操作,所以不应该是没有挂载FATFS的原因。

一周热门 更多>