NOTICE توجه: این یک موضوع قدیمی است که آخرین پست ارسالی آن مربوط به 1905 روز قبل است . لطفا فقط پاسخ ها ، سوالات و درخواست های 100 درصد مرتبط را به آن ارسال کنید و برای درخواست ها و سوالات جدید موضوع جدیدی را ایجاد کنید
نمایش نتایج: از 1 به 12 از 12

موضوع: راه اندازی NAND Flash و FATFS با استفاده از CubeMX (توابع HAL)

  1. #1
    کاربر فعال sajjad_AD آواتار ها
    تاریخ عضویت
    Aug 2009
    نام
    سجاد
    نوشته ها
    307
    تشکر
    336
    تشکر شده 471 بار در 181 پست

    Thumbs up راه اندازی NAND Flash و FATFS با استفاده از CubeMX (توابع HAL)

    درود

    واحد FSMC یک باس ارتباطی واقعاً انعطاف پذیر ایجاد می کنه که می تونه با انواع حافظه ها ارتباط برقرار کنه که در این پروژه قراره با استفاده از این واحد، NAND فلش K9F4G08U0B (همون NAND موجود در فروشگاه فقط با حافظه بیشتر) رو به میکرو متصل و بوسیله FATFS با این حافظه کار کنیم و فایل و پوشه و از این چیزا ایجاد کنیم و ...

    برای ارتباط سخت افزاری این NAND Flash باید پایه ها بصورت ذیل به میکرو وصل شوند:

    D0 تا D7 به D0 تا D7 واحد FMC وصل شوند
    R/B به پایه NWAIT واحد FMC وصل شود
    RE به پایه NOE واحد FMC وصل شود
    CE به پایه NCE2 واحد FMC وصل شود
    CLE به پایه CLE واحد FMC وصل شود
    ALE
    به پایه ALE واحد FMC وصل شود
    WE
    به پایه NWE واحد FMC وصل شود


    شماتیک:




    برای ایجاد پروژه، CubeMX رو باز کنید و بعد از انتخاب میکروکنترولر مورد نظر، که در اینجا از STM32F429ZGT6 استفاده شده، در قسمت FMC بخش NAND Flash 1 رو به صورت نمایش داده شده در عکس پیکربندی می کنیم و برای استفاده از FATFS در قسمت FATFS تیک user-defined رو میذاریم دلیل نبودن حافظه های NAND و NOR در قسمت FATFS، عدم ساپورت CubeMX از این حافظه ها در مود FATFS می باشد که باید خودمون درایور مربوط به این کار رو بنویسیم ...
    مثل همیشه واحد های RCC و SYS رو هم پیکربندی می کنیم، عکس:



    در مرحله بعد در برگه Configuration، واحد FMC و FATFS رو به این شکل پیکربندی می کنیم:



    برای تنظیم FMC تاخیر ها رو با توجه به کلاک میکرو و سرعت NAND Flash مون مقدار دهی می کنیم
    ECC Computation رو Enable و مقدارش رو 512 قرار می دیم (به دیتاشیت NAND فلش مراجعه شود)
    Page Size , Spare Area Size , Block Size , Block Number و Zone Size رو هم بر اساس مشخصات NAND Flash مورد استفاده مقدار دهی می کنیم

    در قسمت FATFS کافیه که سکتور سایز رو 2048 (برابر با Page Size حافظه NAND) قرار بدیم، البته کمتر هم می شه انتخاب کرد، دست خودتونه

    در نهایت از منوی ...Project\Settings مقدار Stack Size رو به 0x3000 افزایش می دیم.

    تمام... Generate code رو بزنید تا وارد مرحله بعد شیم.

    تنها کاری که مونده اینه که درایور مربوط به حافظه NAND Flash مون رو در فایل user_diskio.c بنویسیم که به این صورت می شه:

    کد:
    /* USER CODE BEGIN 0 */
    
    /* Includes ------------------------------------------------------------------*/
    #include <string.h>
    #include "ff_gen_drv.h"
    
    /* Private typedef -----------------------------------------------------------*/
    /* Private define ------------------------------------------------------------*/
    #define NAND_Flash_Block_size     8
    #define NAND_Flash_Page_size      2048
    
    /* Private variables ---------------------------------------------------------*/
    /* Disk status */
    static volatile DSTATUS Stat = STA_NOINIT;
    
    static uint8_t NAND_Flash_Block_Buffer[NAND_Flash_Block_size][NAND_Flash_Page_size];
    
    extern NAND_HandleTypeDef hnand1;
    
    /* Private function prototypes -----------------------------------------------*/
               
    DSTATUS USER_initialize (BYTE pdrv);
    DSTATUS USER_status (BYTE pdrv);
    DRESULT USER_read (BYTE pdrv, BYTE *buff, DWORD sector, UINT count);
    #if _USE_WRITE == 1
      DRESULT USER_write (BYTE pdrv, const BYTE *buff, DWORD sector, UINT count);  
    #endif /* _USE_WRITE == 1 */
    #if _USE_IOCTL == 1
      DRESULT USER_ioctl (BYTE pdrv, BYTE cmd, void *buff);
    #endif /* _USE_IOCTL == 1 */
    
    Diskio_drvTypeDef  USER_Driver =
    {
      USER_initialize,
      USER_status,
      USER_read, 
    #if  _USE_WRITE
      USER_write,
    #endif  /* _USE_WRITE == 1 */  
    #if  _USE_IOCTL == 1
      USER_ioctl,
    #endif /* _USE_IOCTL == 1 */
    };
    
    /* Private functions ---------------------------------------------------------*/
    
    /**
      * @brief  Initializes a Drive
      * @param  pdrv: Physical drive number (0..)
      * @retval DSTATUS: Operation status
      */
    DSTATUS USER_initialize (
        BYTE pdrv           /* Physical drive nmuber to identify the drive */
    )
    {
    
          NAND_IDTypeDef NAND_ID;
        
      Stat = STA_NOINIT;
      
      /* USER CODE HERE */
    
        if(HAL_NAND_Read_ID(&hnand1, &NAND_ID) == HAL_OK)
        {
            Stat = RES_OK;
        }
        else
        {
            Stat = RES_ERROR;
        }
        
      return Stat;
        
    }
    
    /**
      * @brief  Gets Disk Status 
      * @param  pdrv: Physical drive number (0..)
      * @retval DSTATUS: Operation status
      */
    DSTATUS USER_status (
        BYTE pdrv       /* Physical drive nmuber to identify the drive */
    )
    {
    
          NAND_IDTypeDef NAND_ID;
    
      Stat = STA_NOINIT;
      
      /* USER CODE HERE */
    
      if(HAL_NAND_Read_ID(&hnand1, &NAND_ID) == HAL_OK)
      {
        Stat &= ~STA_NOINIT;
      }
    
      return Stat;
    }
    
    /**
      * @brief  Reads Sector(s) 
      * @param  pdrv: Physical drive number (0..)
      * @param  *buff: Data buffer to store read data
      * @param  sector: Sector address (LBA)
      * @param  count: Number of sectors to read (1..128)
      * @retval DRESULT: Operation result
      */
    DRESULT USER_read (
        BYTE pdrv,      /* Physical drive nmuber to identify the drive */
        BYTE *buff,     /* Data buffer to store read data */
        DWORD sector,   /* Sector address in LBA */
        UINT count      /* Number of sectors to read */
    )
    {
      /* USER CODE HERE */
    
          NAND_AddressTypeDef NAND_Address;
    
        for(int i=0;i<count;i++) {
        
        NAND_Address.Zone  = 0x00;
        NAND_Address.Block = (sector+i) / NAND_Flash_Block_size;
          NAND_Address.Page  = (sector+i) - (NAND_Address.Block * NAND_Flash_Block_size);
    
        if(HAL_NAND_Read_Page_8b(&hnand1, &NAND_Address, &buff[i*_MAX_SS], 1) != HAL_OK)
          return RES_ERROR;
    
      }
    
      return RES_OK;
    }
    
    /**
      * @brief  Writes Sector(s)  
      * @param  pdrv: Physical drive number (0..)
      * @param  *buff: Data to be written
      * @param  sector: Sector address (LBA)
      * @param  count: Number of sectors to write (1..128)
      * @retval DRESULT: Operation result
      */
    #if _USE_WRITE == 1
    DRESULT USER_write (
        BYTE pdrv,          /* Physical drive nmuber to identify the drive */
        const BYTE *buff,   /* Data to be written */
        DWORD sector,       /* Sector address in LBA */
        UINT count          /* Number of sectors to write */
    )
    { 
      /* USER CODE HERE */
    
          NAND_AddressTypeDef NAND_Address;
        
          int Page_Address;
    
        for(int i=0;i<count;i++) {
        
        NAND_Address.Zone  = 0x00;
        NAND_Address.Block = (sector+i) / NAND_Flash_Block_size;
          NAND_Address.Page  = 0x00;
        
        if(HAL_NAND_Read_Page_8b(&hnand1, &NAND_Address, &NAND_Flash_Block_Buffer[0][0], NAND_Flash_Block_size) != HAL_OK)
          return RES_ERROR;
    
            Page_Address = (sector+i) - (NAND_Address.Block * NAND_Flash_Block_size);
            
            for(int j=0;j<NAND_Flash_Page_size;j++)
              NAND_Flash_Block_Buffer[Page_Address][j] = buff[(i*_MAX_SS)+j];
    
        if(HAL_NAND_Erase_Block(&hnand1, &NAND_Address) != HAL_OK)
          return RES_ERROR;
    
        if(HAL_NAND_Write_Page_8b(&hnand1, &NAND_Address, &NAND_Flash_Block_Buffer[0][0], NAND_Flash_Block_size) != HAL_OK)
          return RES_ERROR;            
    
      }
        
      return RES_OK;
    }
    #endif /* _USE_WRITE == 1 */
    
    /**
      * @brief  I/O control operation  
      * @param  pdrv: Physical drive number (0..)
      * @param  cmd: Control code
      * @param  *buff: Buffer to send/receive control data
      * @retval DRESULT: Operation result
      */
    #if _USE_IOCTL == 1
    DRESULT USER_ioctl (
        BYTE pdrv,      /* Physical drive nmuber (0..) */
        BYTE cmd,       /* Control code */
        void *buff      /* Buffer to send/receive control data */
    )
    {
      
      /* USER CODE HERE */
    
      DRESULT res = RES_ERROR;
    
      if (Stat & STA_NOINIT) return RES_NOTRDY;
      
      switch (cmd)
      {
      /* Make sure that no pending write process */
      case CTRL_SYNC :
        res = RES_OK;
        break;
      
      /* Get number of sectors on the disk (DWORD) */
      case GET_SECTOR_COUNT :
        *(DWORD*)buff = hnand1.Info.BlockNbr * NAND_Flash_Block_size;
        res = RES_OK;
        break;
      
      /* Get R/W sector size (WORD) */
      case GET_SECTOR_SIZE :
        *(WORD*)buff = hnand1.Info.PageSize;
        res = RES_OK;
        break;
      
      /* Get erase block size in unit of sector (DWORD) */
      case GET_BLOCK_SIZE :
        *(DWORD*)buff = hnand1.Info.PageSize;
        break;
      
      default:
        res = RES_PARERR;
      }
    
      return res;
    }
    #endif /* _USE_IOCTL == 1 */
    
    /* USER CODE END 0 */
    و یه نکته دیگه باید یه اصلاح کوچیک تو فایل stm32f4xx_hal_nand.c که راه انداز NAND Flash ایجاد شده توسط CubeMX با استفاده از توابع HAL می باشد انجام بدیم و اون اینه که طبق دیتاشیت K9F4G08U0B برای نوشتن و خواندن دیتا از فلش، آدرس دهی طی 5 سیکل انجام میشه (2 سیکل اول آدرس ستون و 3 سیکل آخر آدرس سطر می باشند) پس به این صورت اصلاح می شود:

    کد:
        *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U; 
        *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U; 
            
        *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(addressoffset);
        *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(addressoffset);
        *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_3RD_CYCLE(addressoffset);
      
        /* for 512 and 1 GB devices, 4th cycle is required */
        //if(hnand->Info.BlockNbr >= 1024U)
        //{
        //  *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_4TH_CYCLE(addressoffset);
        //}

    طبق کد نوشته شده این سطر باید دو بار تکرار شود:
    کد:
    *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U;

    و این سطر کامنت می شود:
    کد:
        //if(hnand->Info.BlockNbr >= 1024U)
        //{
        //  *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_4TH_CYCLE(addressoffset);
        //}

    این کار در توابع HAL_NAND_Read_Page و HAL_NAND_Write_Page انجام می شود.


    و در تابع HAL_NAND_Erase_Block کافیه که این سطر کامنت شود:
    کد:
        //if(hnand->Info.BlockNbr >= 1024U)
        //{
        //  *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_4TH_CYCLE(addressoffset);
        //}
    تو main چنتا از توابع FATFS رو تست می کنیم به طور مثال من این ها رو تو Sample مون گذاشتم:

    کد:
    f_mount(&FatFs, (TCHAR const*)USER_Path, 0);
    
    f_mkfs((TCHAR const*)USER_Path, 0, 0);
    
    f_opendir(&MyDir, (TCHAR const*)USER_Path);
    
    f_open(&MyFile, "STM32.TXT", FA_CREATE_ALWAYS | FA_WRITE);
        
    f_write(&MyFile, "0123456789", 10, &BW);
        
    f_close(&MyFile);
                    
    f_open(&MyFile, "STM32.TXT", FA_OPEN_ALWAYS | FA_READ);
    برنامه رو کامپایل کنید و نتیجه رو ببینید

    در مورد invalid blocks که تو دیتاشیت اومده، بگم که ممکنه تعدادی از Block های NAND Flash مورد استفاده خراب و غیر قابل استفاده باشند که از تعداد انگشتان دست تجاوز نمی کنه...

    روش ذکر شده روش جالبی برای استفاده عملی نیست چون رم زیادی رو اشغال می کنه اما یه مثال از bsp هم آپلود کردم که از رو اون واس نوشتن یه درایور پدر مادر دار الگو بگیرید موفق باشید.
    پروژه Keil Arm و CubeMX ضمیمه شده
    تصاوير کوچک فايل پيوست تصاوير کوچک فايل پيوست برای دیدن سایز بزرگ روی عکس کلیک کنید

نام: SCH.png
مشاهده: 756
حجم: 43.8 کیلو بایت   برای دیدن سایز بزرگ روی عکس کلیک کنید

نام: NAND1.png
مشاهده: 719
حجم: 65.8 کیلو بایت   برای دیدن سایز بزرگ روی عکس کلیک کنید

نام: NAND2.png
مشاهده: 728
حجم: 75.7 کیلو بایت  
    فايل هاي پيوست شده فايل هاي پيوست شده
    ویرایش توسط sajjad_AD : 07-09-2016 در ساعت 15:32

  2. کاربران : 17 تشکر کرده اند از شما sajjad_AD برای ارسال این پست سودمند:


  3. # ADS
    Circuit advertisement
    تاریخ عضویت
    Always
    نام
    Advertising world
    نوشته ها
    Many
     

  4. #2
    کاربر فعال
    تاریخ عضویت
    Jul 2012
    نوشته ها
    101
    تشکر
    23
    تشکر شده 3 بار در 1 پست

    پیش فرض

    لطفا برای sdio روهم تشریح کنید همراه کدها ممنون

  5. #3
    کاربر فعال sajjad_AD آواتار ها
    تاریخ عضویت
    Aug 2009
    نام
    سجاد
    نوشته ها
    307
    تشکر
    336
    تشکر شده 471 بار در 181 پست

    پیش فرض

    اینم یه سایت با محوریت CubeMX که خدا به مدیرش خیر بده

    microtechnics.ru

  6. کاربران : 4 تشکر کرده اند از شما sajjad_AD برای ارسال این پست سودمند:


  7. #4
    کاربر فعال
    تاریخ عضویت
    Jul 2012
    نوشته ها
    101
    تشکر
    23
    تشکر شده 3 بار در 1 پست

    پیش فرض

    نقل قول نوشته اصلی توسط sajjad_AD نمایش پست ها
    اینم یه سایت با محوریت CubeMX که خدا به مدیرش خیر بده

    microtechnics.ru
    من sd کارتمو به میکروم وصل کردم و طبق کدی که اینجا نوشته نوشتم و از میکرو کلاک 365khz ایجاد میشه ولی فایلی در sd کارتم درست نمیشه

    - - - Updated - - -

    if(f_mount(&fileSystem, SD_Path, 1) == FR_OK)
    {
    این شرط برقرار نمیشه ولی کلاک زده میشه
    ایراد کارم کجاست؟

  8. #5
    کاربر فعال sajjad_AD آواتار ها
    تاریخ عضویت
    Aug 2009
    نام
    سجاد
    نوشته ها
    307
    تشکر
    336
    تشکر شده 471 بار در 181 پست

    پیش فرض

    اول بپرسم که سخت افزارتون چیه؟
    خودتون طراحی کردین یا آماده تهیه نمودین؟

    اگه آمادس پس مشکل از سخت افزار نیس و این کار ها رو تو CubeMX انجام بدید:
    اولا SDIO / Mode رو حتما روی تک بیت قرار بدید و SDIOCLK clock devide factor رو بیشتر کنید و در نهایت از یه مموری با برندی متفاوت با اینی که الان داری استفاده می کنی استفاده کن

  9. کاربران : 4 تشکر کرده اند از شما sajjad_AD برای ارسال این پست سودمند:


  10. #6
    کاربر فعال
    تاریخ عضویت
    Jul 2012
    نوشته ها
    101
    تشکر
    23
    تشکر شده 3 بار در 1 پست

    پیش فرض

    خودش در مثالی که زده در 4بیت قرار داده
    بله برده اشو خودم زدم

    - - - Updated - - -

    سخت افزارمم stm32f103RET

  11. #7
    مدیر انجمن M.ABDOLLAHI آواتار ها
    تاریخ عضویت
    Dec 2008
    نام
    مهدی عبدالهی
    نوشته ها
    976
    تشکر
    1,567
    تشکر شده 2,677 بار در 667 پست

    پیش فرض

    افرین خیلی زحمت میکشی به مدیر سایت پیشنهاد میکنم ایشون را مدیر بخش stm32 بگذاره که حداقل یک تشکر کوچکی از زحماتش شده باشه
    و هر كس از ياد [خداى‏] رحمان دل بگرداند، بر او شيطانى مى‏گماريم تا براى وى دمسازى باشد. (36)و مسلّماً آنها ايشان را از راه باز مى‏دارند و [آنها] مى‏پندارند كه راه يافتگانند. (37)تا آن گاه كه او [با دمسازش‏] به حضور ما آيد، [خطاب به شيطان‏] گويد: «اى كاش ميان من و تو، فاصله خاور و باختر بود، كه چه بد دمسازى هستى!» (38)(سوره زخرف)بگو: «پليد و پاك يكسان نيستند، هر چند كثرت پليد [ها] تو را به شگفت آوَرَد. پس اى خردمندان، از خدا پروا كنيد، باشد كه رستگار شويد.» (100)(سوره مائده(

  12. تشکرها از این نوشته :


  13. #8
    کاربر علاقه مند ali_rostami_7 آواتار ها
    تاریخ عضویت
    Oct 2011
    نوشته ها
    91
    تشکر
    295
    تشکر شده 54 بار در 36 پست

    پیش فرض

    با سلام
    میکروکنترلری که من استفاده میکنم Stm32f429igt6 و آیسی نندفلشم هم k9f1g08u0c هست. متاسفانه هر کار میکنم جواب درست از این ایسی نمیگیرم به این صورت که دیتایی که در یک بلاک مینویسم با دیتایی که از ان میخوانم یکی نیست.
    سیگنال ها روی لاجیک میبینم و ظاهرا طبق دیتاشیت هستند. عملیات نوشتن و خواندن هم با موفقیت در برنامه اجرا میشوند. اما با این حال نمیدونم چرا درست انجام نمیشوند. در ادرس زیر پروژه رو گذاشتم از دوستان ممنونم میشم راهنمایی کنن.
    Dropbox - test_nand_flash.rar

  14. #9
    مدیر انجمن mzarkoob آواتار ها
    تاریخ عضویت
    Jun 2011
    نام
    مهدی زرکوب
    نوشته ها
    2,902
    تشکر
    1,202
    تشکر شده 2,317 بار در 1,273 پست

    پیش فرض

    الان روی برد 1788 کویر مدل k9f2g08u0 هست البته قبلا 1g بود.
    مهم اینه که اینیشیالیزشو توسط واحد مربوطه در میکرو درست انجام بدید. مابقی آدرس است.

  15. تشکرها از این نوشته :


  16. #10
    کاربر علاقه مند ali_rostami_7 آواتار ها
    تاریخ عضویت
    Oct 2011
    نوشته ها
    91
    تشکر
    295
    تشکر شده 54 بار در 36 پست

    پیش فرض

    مثالی از اینیتش رو دارید؟ چه پارامترهایی رو بدم؟
    در ضمن من میتونم id نندفلش رو هم بخونم. و درست هم هست.طبق دیتاشیت.

  17. #11
    مدیر انجمن mzarkoob آواتار ها
    تاریخ عضویت
    Jun 2011
    نام
    مهدی زرکوب
    نوشته ها
    2,902
    تشکر
    1,202
    تشکر شده 2,317 بار در 1,273 پست

    پیش فرض

    برای f4 انجام ندام هنوز.
    با 1788 با واحد EMC این اینیشیالیز انجام میشد. در f4 هم باید با واحد خودش این ار انجام بشه.
    آیا وقتی آی دی درست می خونه به معنای این نیست که اینیشیالیز درست انجام شده و در نوشتن یا خواندن ایراد وجود داره؟

  18. #12
    کاربر علاقه مند ali_rostami_7 آواتار ها
    تاریخ عضویت
    Oct 2011
    نوشته ها
    91
    تشکر
    295
    تشکر شده 54 بار در 36 پست

    پیش فرض

    منم از همین تعجب میکنم. از این جالب تر اینکه من تمام خطوط رو با لاجیک میبینم و روند سیگنال ها در خواندن یا نوشتن عین دیتاشیت میره جلو. موندم چرا اینجوری میشه.

موضوعات مشابه

  1. پاسخ: 20
    آخرين نوشته: 28-11-2016, 21:10
  2. پاسخ: 0
    آخرين نوشته: 17-10-2015, 09:46
  3. Nand flash
    توسط asmira در انجمن LPC series (NXP)
    پاسخ: 5
    آخرين نوشته: 29-09-2014, 10:54
  4. پاسخ: 6
    آخرين نوشته: 27-02-2014, 12:03
  5. راه اندازی nand flash با sam7
    توسط ramin.st در انجمن AT91 series (ATMEL)
    پاسخ: 2
    آخرين نوشته: 02-10-2013, 21:25

مجوز های ارسال و ویرایش

  • شما نمیتوانید موضوع جدیدی ارسال کنید
  • شما امکان ارسال پاسخ را ندارید
  • شما نمیتوانید فایل پیوست کنید.
  • شما نمیتوانید پست های خود را ویرایش کنید
  •