XÂY DỰNG SDCARD

Một phần của tài liệu khảo sát và thực hiện một số ứng dụng với board altera fpga de3 (Trang 71)

Hình 5.3-1 biểu diễn sơ đồ khối của ứng dụng SD Card.

Trước tiên, vào phần mềm Quartus II tạo một project. Sau đó, chọn họ và thiết bị.

Hình 5.3-2: Chọn nơi lưu, đặt tên project và tên thư mục

Hình 5.3-3: Chọn họ và thiết bị

Trong project này, chúng ta sẽ thực hiện tạo một hệ thống SOPC bằng cách sử dụng SOPC Builder. Hệ thống này sẽ được tạo ra bằng file Verilog HDL, đặt tên cho hệ thống là DE3_SOPC.

Hình 5.3-4: Tạo hệ thống phần cứng

Ta tạo một hệ thống SOPC gồm: CPU, RAM, JTAG UART, System ID, Timer, pio_led, pio_button, pio_sd_clk, pio_sd_cmd, pio_sd_dat và pll:

Đầu tiên, ta chọn Processor/Nios II Processor: CPU là bộ xử lý trung tâm, điều khiển hoạt động của hệ thống.

Tiếp theo, ta chọn Memories and Memory Controllers/On-Chip/On-Chip Memory (RAM or ROM): RAM dung để lưu trữ dữ liệu và lệnh chương trình.

Sau khi tạo bộ nhớ RAM xong, quay trở lại CPU để gán RAM cho nó.

Hình 5.3-7: Gán bộ nhớ RAM cho CPU

Tiếp theo, chọn Interface Protocols/Serial/JTAG UART: JTAG UART có chức năng kết nối với máy chủ để nạp chương trình hệ thống xuống board DE3 thông qua cổng USB Blaster.

Hình 5.3-8: Cấu hình JTAG UART

Chọn Peripherals/Debug and Performance/System ID Perpheral: System ID là module cung cấp một số tác dụng nhận dạng hệ thống phần cứng trên board DE3.

Tùy thuộc vào thời gian delay cần thiết kế mà ta có thể thay đổi giá trị trong Period, đơn vị trong Units. Ta vào Peripherals/Microcontroller Peripherals/Interval Timer:

Hình 5.3-10: Cấu hình Timer

Giao thức PIO sẽ thiết kế 5 mạch kết nối gồm: 1 ngõ ra 24 bit (LED RGB), 1 ngõ vào (button), 1 ngõ ra (SD_CLK), 1 ngõ vào ra (SD_CMD) và 1 ngõ vào ra (SD_DAT).

Hình 5.3-11: Cấu hình PIO

Hình 5.3-13: Cấp xung clock ngõ ra 50Mhz

Để biên dịch hệ thống, ta cần gán địa chỉ nền cho các core đã thiết kế. Chọn System/Auto-Assign Base Addresses

Kết quả sau khi gán địa chỉ nền:

Hình 5.3-15: Tạo hệ thống thành công

Sau khi xây dựng hệ thống hoàn chỉnh, bắt đầu gán chân cho hệ thống và nạp xuống board. Quay lại phần mềm Quartus II vào File chọn Add/Remove Files in Project sẽ xuất hiện hộp thoại, chỉ đến file .v.

Hình 5.3-16: Thêm file .v

Để gán chân chân cho hệ thống, ta vào File/New chọn Block Diagram/ Schematic File. Vào Symbol Tool để lấy sơ đồ khối hệ thống (DE3_SOPC).

Sau đó, ta thực hiện gán chân cho hệ thống, vào Pin Tool để lấy ngõ vào, ngõ ra, ngõ vào ra. Vào Assignments/Import Assignments… dẫn tập tin DE3_SDCARD.qsf để xác định chân cụ thể. Lưu ý: gán chân chỗ ngõ vào/ra/hai chiều.

Hình 5.3-17: Gán chân cho hệ thống

Hình 5.3-18: Biên dịch thành công

Sau khi biên dịch xong, nhấp vào Programmer, chọn Start để nạp file DE3_SDCARD.sof xuống board DE3. Kết quả nạp xuống board thành công.

Hình 5.3-19: Nạp xuống board thành công

Khi nạp xuống board thành công, tiến hành viết chương trình ứng dụng cho hệ thống phần cứng đã được thiết kế bằng chương trình Nios II Software Build Tools for Eclipse.

Ta chọn đường dẫn nơi lưu trữ phần mềm ứng dụng:

Hình 5.3-21: Chọn nơi lưu trữ phần mềm

Sau khi đã chọn đường dẫn, cửa sổ soạn thảo chương trình ứng dụng được tạo ra. Vào File/New chọn Nios II Application and BSP from Template.

Hình 5.3-23: Tạo ứng dụng mới dựa trên code có sẵn

Chương trình ứng dụng sử dụng code mẫu có sẵn và đánh đoạn code thay thế code có sẵn theo ý muốn.

#include <stdio.h>

#include "terasic_lib\terasic_includes.h" #include "terasic_fat\FatFileSystem.h" #include "terasic_sdcard\SDCardDriver.h"

bool Fat_Test(FAT_HANDLE hFat, char *pDumpFile){ bool bSuccess;

int nCount = 0;

FAT_BROWSE_HANDLE hBrowse; FILE_CONTEXT FileContext;

bSuccess = Fat_FileBrowseBegin(hFat, &hBrowse); if (bSuccess){

while(Fat_FileBrowseNext(&hBrowse, &FileContext)){ if (FileContext.bLongFilename){

alt_u8 *pData8;

pData16 = (alt_u16 *)FileContext.szName; pData8 = FileContext.szName; printf("[%d]", nCount); while(*pData16){ if (*pData8) printf("%c", *pData8); pData8++; if (*pData8) printf("%c", *pData8); pData8++; // pData16++;} printf("\n"); }else{

printf("[%d]%s\n", nCount, FileContext.szName);} nCount++;}}

if (bSuccess && pDumpFile && strlen(pDumpFile)){ FAT_FILE_HANDLE hFile;

hFile = Fat_FileOpen(hFat, pDumpFile); if (hFile){

char szRead[256];

int nReadSize, nFileSize, nTotalReadSize=0; nFileSize = Fat_FileSize(hFile);

if (nReadSize > sizeof(szRead)) nReadSize = sizeof(szRead); printf("%s dump:\n", pDumpFile);

while(bSuccess && nTotalReadSize < nFileSize){ nReadSize = sizeof(szRead);

if (nReadSize > (nFileSize - nTotalReadSize)) nReadSize = (nFileSize - nTotalReadSize); if (Fat_FileRead(hFile, szRead, nReadSize)){ int i;

for(i=0;i<nReadSize;i++){ printf("%c", szRead[i]);} nTotalReadSize += nReadSize;}

else{ bSuccess = FALSE;

printf("\nFaied to read the file \"%s\"\n", pDumpFile);}} // while if (bSuccess) printf("\n");

Fat_FileClose(hFile);} else{ bSuccess = FALSE;

printf("Cannot find the file \"%s\"\n", pDumpFile); }} return bSuccess;}

int main()

const alt_u32 LED_GREEN_PATTERN = 0xFF00FF; const alt_u32 LED_RED_PATTERN = 0x00FFFF; FAT_HANDLE hFat;

printf("========== DE3 SDCARD Demo [13/04/2015]\n"); while(1){

IOWR_ALTERA_AVALON_PIO_DATA(PIO_LED_BASE, LED_BLUE_PATTERN); hFat = Fat_Mount(FAT_SD_CARD, 0);

if (hFat){

printf("sdcard mount success!\n");

printf("Root Directory Item Count:%d\n", Fat_FileCount(hFat)); Fat_Test(hFat, "test.txt");

Fat_Unmount(hFat);

IOWR_ALTERA_AVALON_PIO_DATA(PIO_LED_BASE, LED_GREEN_PATTERN); }else{

printf("Failed to mount the SDCARD!\nPlease insert the SDCARD into DE3 board and press BUTTON3.\n");

IOWR_ALTERA_AVALON_PIO_DATA(PIO_LED_BASE, LED_RED_PATTERN); } // wait users to press BUTTON3

while ((IORD_ALTERA_AVALON_PIO_DATA(PIO_BUTTON_BASE) & 0x08) == 0x08); IOWR_ALTERA_AVALON_PIO_DATA(PIO_LED_BASE, LED_BLUE_PATTERN); usleep(400*1000); // debounce

} // while return 0;}

Sau đó, ta thực hiện biên dịch chương trình ứng dụng, nhấp chuột phải vào DE3_SDCARD chọn Build Project.

Hình 5.3-25: Biên dịch chương trình thành công

Để chạy chương trình ứng dụng, nhấp chuột phải lên DE3_SDCARD chọn Run As/Run Configuration để tạo New_configuration, sau đó Run để chạy chương trình xuống board.

Hình 5.3-26: Chạy chương trình ứng dụng

Kết quả khi chạy chương trình là “HAI QUYEN & HONG HANH [10/5/2015]”.

Hình 5.3-27: Kết quả chạy thành công

Khi chương trình thực thi, nó phát hiện thẻ SD được chèn vào. Nếu một thẻ SD được tìm thấy, nó sẽ kiểm tra thẻ SD có định dạng hệ thống tập tin FAT hay chưa. Nếu một

hệ thống tập tin FAT được tìm thấy, nó sẽ tìm kiếm tất cả các file trong thư mục gốc của hệ thống tập tin FAT và lúc này đèn xanh lá sẽ được sáng.

Hình 5.3-28: Phát hiện thẻ SD thành công

Mặt khác, LED màu đỏ sáng nếu chương trình không thành công phân tích các hệ thống tập tin FAT hoặc không có thẻ SD được tìm thấy trong các ổ cắm thẻ SD của Board DE3. Nếu người dùng nhấn button3 của Board DE3, chương trình sẽ thực hiện quá trình trên một lần nữa.

CHƢƠNG 6: KẾT LUẬN VÀ ĐỊNH HƢỚNG PHÁT TRIỂN ĐỀ TÀI 6.1 KẾT LUẬN

Trong thời gian 4 tháng tìm hiểu đề tài, nhóm đã hoàn thành việc nghiên cứu board DE3 và xây dựng ứng dụng đọc dữ liệu từ SD Card. Qua đề tài này, nhóm có thêm kiến thức về FPGA, Altera DE3, cách xây dựng hệ thống SOPC từ Quartus II và cách sử dụng Nios II để lập trình cho hệ thống phần cứng được thiết kế. Bên cạnh việc có thêm kiến thức mới, chúng tôi cũng học được cách làm việc nhóm hiệu quả. Tuy hoàn thành được việc đọc dữ liệu từ SD Card nhưng do thời gian hạn chế nên nhóm chưa thực được những ứng dụng khác trên Altera DE3 như: nhận dữ liệu qua cổng USB.

6.2 ĐỊNH HƢỚNG PHÁT TRIỂN ĐỀ TÀI

Nghiên cứu board DE3 và xây dựng ứng dụng mà nhóm thực hiện chỉ hoàn thành ở mức cơ bản đọc dữ liệu từ SD Card. Trong thời gian tới, ứng dụng cần được cải tiến và có nhiều tính năng hơn.

Định hướng phát triển cho đề tài:

Xây dựng thêm ứng dụng nhận dữ liệu qua cổng USB có trên board và kết nối được với các thiết bị như máy nghe nhạc, điện thoại... .

TÀI LIỆU THAM KHẢO

[1] DE3 User Manual.

URL: https://www.altera.com/support/training/university/de3.html

[2] Aseem Vasudev and Jayanti Addepalli. Interfacing SD Cards with Blackfin® Processors. 2010.

[3] Getting Started with the Graphical User Interface.

URL:https://www.altera.com/en_US/pdfs/literature/hb/nios2/n2sw_nii52017.pdf

PHỤ LỤC A

SỰ GIAO TIẾP GIỮA BOARD VÀ THÀNH PHẦN TRÊN BOARD

Button và LED đơn:

http://www.mediafire.com/watch/txd4h7er4gtfdyj/WP_20150510_172(1).mp4

Button và LED 7 đoạn:

PHỤ LỤC B

HƢỚNG DẪN XÂY DỰNG SD CARD

 Khi tạo xong project ứng dụng, ta nhấp chuột phải vào DE3_SDCARD chọn New/Source Folder để tạo thư mục chứa các thư viện xây dựng thẻ SD.

Hình B.1: Tạo project ứng dụng

 Chúng ta sẽ tạo 3 thư mục đó là terasic_fat, terasic_lib và terasic_sdcard. Ta nhấp chuột phải vào DE3_SDCARD chọn New/Source Folder để tạo một thư mục.

Hình B.2: Tạo thư mục chứa các thư viện

 Khi thư mục terasic_fat được tạo ra, ta nhấp chuột phải vào nó và chọn New, sau đó chọn Source File và Header File để tạo thư viện .c và .h, ta đặt tên là

Hình B.3: Tạo thư viện .c

Hình B.4: Tạo thư viện .h Thư viện FatFileSystem.c:

#include <string.h> // memcpy

#include "..\terasic_lib\terasic_includes.h" #include "FatFileSystem.h"

#include "FatInternal.h" #ifdef DEBUG_FAT

#define FAT_DEBUG(x) DEBUG(x) #else

#define FAT_DEBUG(x) #endif

void fatComposeShortFilename(FAT_DIRECTORY *pDir, char *szFilename); bool fatSameLongFilename(alt_u16 *p1, alt_u16 *p2);

FAT_HANDLE Fat_Mount(FAT_DEVICE FatDevice, DEVICE_HANDLE hDevice){ //Fat_Unmount(); FAT_HANDLE hFat = 0; if (FatDevice == FAT_SD_CARD){ #ifdef SUPPORT_SD_CARD hFat = fatMountSdcard(); #endif //SUPPORT_SD_CARD

}else if (FatDevice == FAT_USB_DISK){ #ifdef SUPPORT_USB_DISK

hFat = fatMountUsbDisk(hDevice); #endif }

return hFat; }

void Fat_Unmount(FAT_HANDLE Fat){

VOLUME_INFO *pVol = (VOLUME_INFO *)Fat; if (!pVol) return;

#ifdef FAT_READONLY if (pVol->szFatTable){ free(pVol->szFatTable);

pVol->szFatTable = 0; } #endif //#ifdef FAT_READONLY

pVol->bMount = FALSE; free(pVol); }

bool Fat_FileBrowseBegin(FAT_HANDLE hFat, FAT_BROWSE_HANDLE

*pFatBrowseHandle){

VOLUME_INFO *pVol = (VOLUME_INFO *)hFat; if (!pVol) return FALSE;

if (!pVol->bMount) return FALSE; pFatBrowseHandle->DirectoryIndex = 0; pFatBrowseHandle->hFat = hFat;

return TRUE;}

bool Fat_FileBrowseNext(FAT_BROWSE_HANDLE *pFatBrowseHandle, FILE_CONTEXT *pFileContext){

bool bFind = FALSE, bVlaid, bError=FALSE, bLongFilename = FALSE; int OrderValue = 0;

FAT_DIRECTORY *pDir;

unsigned int nSecter, nOffset; char szBlock[512];

VOLUME_INFO *pVol = (VOLUME_INFO *)pFatBrowseHandle->hFat; if (!pVol) return FALSE;

if (!pVol->bMount) return FALSE;

do{nOffset=(sizeof(FAT_DIRECTORY)*pFatBrowseHandle->DirectoryIndex)/pVol- > BPB_BytsPerSec;

nSecter = pVol->RootDirectoryEntrySecter + nOffset; if (!pVol->ReadBlock512(pVol->DiskHandle, nSecter, szBlock)){ bError = TRUE;}

else{

nOffset=(sizeof(FAT_DIRECTORY)*pFatBrowseHandle>DirectoryIndex)%pVol- >BPB_BytsPerSec;

pDir = (FAT_DIRECTORY *)(szBlock + nOffset); pFatBrowseHandle->DirectoryIndex++;

bVlaid = fatIsValid(pDir);

if (bVlaid){ if ((pDir->Attribute & ATTR_LONG_NAME) == ATTR_LONG_NAME) { FAT_LONG_DIRECTORY *pLDIR = (FAT_LONG_DIRECTORY *)pDir;

// check attribute

if ((pLDIR->LDIR_Attr & ATTR_LONG_NAME) != ATTR_LONG_NAME){ bError = TRUE; }else{ // check order if (OrderValue == 0){ if (bLongFilename) bError = TRUE; else

OrderValue = pLDIR->LDIR_Ord & 0x3F;

memset(pFileContext->szName, 0, sizeof(pFileContext->szName)); }else{

if ((pLDIR->LDIR_Ord & 0x3F) != OrderValue) bError = TRUE;}} // if (!bError){ int BaseOffset; bLongFilename = TRUE; OrderValue--; BaseOffset = OrderValue * 26; // cast filename memcpy(pFileContext->szName+BaseOffset, pLDIR->LDIR_Name1, 10); memcpy(pFileContext->szName+BaseOffset+10, pLDIR->LDIR_Name2, 12); memcpy(pFileContext->szName+BaseOffset+22, pLDIR->LDIR_Name3, 4);}

}else{

if (bLongFilename){ pFileContext->Attribute = ATTR_LONG_NAME; if ((pDir->Attribute & (ATTR_ARCHIVE | ATTR_DIRECTORY)) == 0) bError = TRUE;

else

bFind = TRUE;}

else{ fatComposeShortFilename(pDir, pFileContext->szName); bFind = TRUE;}

if (bFind){ // my ext

pFileContext->bLongFilename = bLongFilename;

pFileContext->bFile = (pDir->Attribute & ATTR_ARCHIVE)?TRUE:FALSE; pFileContext->bDirectory = (pDir->Attribute & ATTR_DIRECTORY)?TRUE:FALSE; pFileContext->bVolume = (pDir->Attribute & ATTR_VOLUME_ID)?TRUE:FALSE; // pFileContext->Attribute = pDir->Attribute; pFileContext->CreateTime = pDir->CreateTime; pFileContext->LastAccessDate = pDir->LastAccessDate; pFileContext->FirstLogicalClusterHi = pDir->FirstLogicalClusterHi; pFileContext->LastWriteTime = pDir->LastWriteTime; pFileContext->LastWriteDate = pDir->LastWriteDate; pFileContext->FirstLogicalCluster = pDir->FirstLogicalCluster; pFileContext->FileSize = pDir->FileSize;}}}} }while (!bFind && !fatIsLast(pDir) && !bError);

return bFind;} /*

bool Fat_FileBrowseNext(FAT_BROWSE_HANDLE *pFatBrowseHandle, FAT_DIRECTORY *pDirectory){

bool bFind = FALSE, bError=FALSE; FAT_DIRECTORY *pDir;

unsigned int nSecter, nOffset; char szBlock[512];

VOLUME_INFO *pVol = (VOLUME_INFO *)pFatBrowseHandle->hFat; if (!pVol) return FALSE;

if (!pVol->bMount) return FALSE; do{

nOffset = (sizeof(FAT_DIRECTORY)*pFatBrowseHandle->DirectoryIndex)/pVol- >BPB_BytsPerSec;

// if (!SD_read_block(nSecter, szBlock)){

if (!pVol->ReadBlock512(pVol->DiskHandle, nSecter, szBlock)){ bError = TRUE;

}else{

nOffset = (sizeof(FAT_DIRECTORY)*pFatBrowseHandle->DirectoryIndex)%pVol- >BPB_BytsPerSec;

pDir = (FAT_DIRECTORY *)(szBlock + nOffset);

printf("[%d]=%02Xh\n", pFatBrowseHandle->DirectoryIndex, pDir->Name[0]); pFatBrowseHandle->DirectoryIndex++;

bFind = fatIsValid(pDir); if (bFind){

*pDirectory = *pDir;

printf("find....\n");}} }while (!bFind && !fatIsLast(pDir) && !bError); return bFind;}

*/

unsigned int Fat_FileCount(FAT_HANDLE Fat){ unsigned int nCount = 0;

FAT_BROWSE_HANDLE hBrowse; FILE_CONTEXT FileContext; if (Fat_FileBrowseBegin(Fat, &hBrowse)){ while(Fat_FileBrowseNext(&hBrowse, &FileContext)) nCount++;} return nCount;}

bool fatSameLongFilename(alt_u16 *p1, alt_u16 *p2){ bool bSame = TRUE;

while(bSame && ((*p1 != 0) || (*p2 != 0))){ if (*p1 != *p2){ bSame = FALSE;} p1++; p2++;} return bSame;}

void fatComposeShortFilename(FAT_DIRECTORY *pDir, char *szFilename){ int i,nPos=0;

i=0;

while(i < 8 && pDir->Name[i] != 0 && pDir->Name[i] != ' ') szFilename[nPos++] = pDir->Name[i++];

if (pDir->Attribute & (ATTR_ARCHIVE | ATTR_DIRECTORY)){

szFilename[nPos++] = '.'; i=0;

while(i < 3 && pDir->Extension[i] != 0 && pDir->Extension[i] != ' ') szFilename[nPos++] = pDir->Extension[i++];}

szFilename[nPos++] = 0;} // File Access

FAT_FILE_HANDLE Fat_FileOpen(FAT_HANDLE Fat, const char *pFilename){ bool bFind = FALSE;

FAT_BROWSE_HANDLE hBrowse; FILE_CONTEXT FileContext;

FAT_FILE_INFO *pFile = 0;

if (Fat_FileBrowseBegin(Fat, &hBrowse)){

while (!bFind && Fat_FileBrowseNext(&hBrowse, &FileContext)){ if (FileContext.bLongFilename){

bFind = fatSameLongFilename((alt_u16 *)FileContext.szName, (alt_u16

*)pFilename); }else{

if (strcmpi(FileContext.szName, pFilename) == 0)bFind = TRUE;} if (bFind){ pFile = malloc(sizeof(FAT_FILE_INFO)); if (pFile){ pFile->SeekPos = 0; pFile->Directory = FileContext; pFile->IsOpened = TRUE; pFile->Cluster = FileContext.FirstLogicalCluster; pFile->ClusterSeq = 0; pFile->Fat = Fat;}}}} return (FAT_FILE_HANDLE)pFile;}

unsigned int Fat_FileSize(FAT_FILE_HANDLE hFileHandle){ FAT_FILE_INFO *f = (FAT_FILE_INFO *)hFileHandle; if (f->IsOpened)

return f->Directory.FileSize; return 0;}

bool Fat_FileRead(FAT_FILE_HANDLE hFileHandle, void *pBuffer, const int nBufferSize){

FAT_FILE_INFO *f = (FAT_FILE_INFO *)hFileHandle; VOLUME_INFO *pVol;

unsigned int Pos, PhysicalSecter, NextCluster, Cluster; unsigned int BytesPerCluster, nReadCount=0, nClusterSeq;

int s;

bool bSuccess= TRUE; char szBlock[512];

if (!f || !f->Fat) return FALSE; pVol = (VOLUME_INFO *)f->Fat; if (!f->IsOpened){

FAT_DEBUG(("[FAT] Fat_FileRead, file not opened\r\n")); return bSuccess;}

BytesPerCluster = pVol->nBytesPerCluster; //gVolumeInfo.BPB_BytsPerSec * gVolumeInfo.BPB_SecPerCluster;

Pos = f->SeekPos;

if (BytesPerCluster == 32768){ nClusterSeq = Pos >> 15; Pos -= (f->ClusterSeq << 15);}

else if (BytesPerCluster == 16384){ nClusterSeq = Pos >> 14; Pos -= (f->ClusterSeq << 14);}

else if (BytesPerCluster == 2048){ nClusterSeq = Pos >> 11; Pos -= (f->ClusterSeq << 11);}

else{ nClusterSeq = Pos/BytesPerCluster;

Pos -= f->ClusterSeq*BytesPerCluster;} Cluster = f->Cluster;

if (nClusterSeq != f->ClusterSeq){ Cluster = f->Cluster; // move to first clustor for reading

while (Pos >= BytesPerCluster && bSuccess){ // go to next cluster

NextCluster = fatNextCluster(pVol, Cluster);

if (NextCluster == 0){ bSuccess = FALSE; FAT_DEBUG(("[FAT] Fat_FileRead, not next Cluster, current Cluster=%d\r\n", Cluster)); } else{ Cluster = NextCluster; }

Pos -= BytesPerCluster; f->Cluster = Cluster;

f->ClusterSeq++; }} // reading

while(nReadCount < nBufferSize && bSuccess){ if (pVol->BPB_SecPerCluster == 32)

PhysicalSecter = ((Cluster-2) << 5) + pVol->DataEntrySecter; // -2: FAT0 & FAT1 are reserved

else if (pVol->BPB_SecPerCluster == 64)

PhysicalSecter = ((Cluster-2) << 6) + pVol->DataEntrySecter; // -2: FAT0 & FAT1 are reserved

PhysicalSecter = (Cluster-2)*pVol->BPB_SecPerCluster + pVol- >DataEntrySecter; // -2: FAT0 & FAT1 are reserved

for(s=0;s<pVol->BPB_SecPerCluster && nReadCount < nBufferSize;s++){ if (Pos >= pVol->BPB_BytsPerSec){Pos -= pVol->BPB_BytsPerSec;}

else{

int nCopyCount;

nCopyCount = pVol->BPB_BytsPerSec; if (Pos) nCopyCount -= Pos;

if (nCopyCount > (nBufferSize-nReadCount)) nCopyCount = nBufferSize- nReadCount;

if (nCopyCount == 512){

//if (PhysicalSecter == 262749)

// FAT_DEBUG(("[FAT] here, 262749"));

if (!pVol->ReadBlock512(pVol->DiskHandle, PhysicalSecter, (char

*)pBuffer+nReadCount)){

bSuccess = FALSE; // fail

FAT_DEBUG(("[FAT] Fat_FileRead, SD_read_block fail, PhysicalSecter=%d (512)\r\n", PhysicalSecter)); }

else{

//FAT_DEBUG(("[FAT] Fat_FileRead Success, PhysicalSecter=%d (512)\r\n", PhysicalSecter));

nReadCount += nCopyCount; if (Pos > 0) Pos = 0;}} else{

if (!pVol->ReadBlock512(pVol->DiskHandle, PhysicalSecter, szBlock)){ bSuccess = FALSE; // fail

FAT_DEBUG(("[FAT] Fat_FileRead, SD_read_block fail\r\n"));

else{memcpy((void *)((char *)pBuffer+nReadCount), szBlock+Pos,nCopyCount);

nReadCount += nCopyCount;

if (Pos > 0) Pos = 0;}}} PhysicalSecter++; } // next cluster

if (nReadCount < nBufferSize){NextCluster = fatNextCluster(pVol, Cluster); if (NextCluster == 0){ bSuccess = FALSE;

FAT_DEBUG(("[FAT] Fat_FileRead, no next cluster\r\n")); } else{ Cluster = NextCluster;}

//

f->ClusterSeq++;

f->Cluster = Cluster; } }

return bSuccess; }

bool Fat_FileSeek(FAT_FILE_HANDLE hFileHandle, const FAT_SEEK_POS SeekPos, const int nOffset){

FAT_FILE_INFO *f = (FAT_FILE_INFO *)hFileHandle; VOLUME_INFO *pVol;

bool bSuccess= TRUE;

if (!f || !f->Fat) return FALSE; pVol = (VOLUME_INFO *)f->Fat; if (!f->IsOpened) return FALSE; switch(SeekPos){

case FILE_SEEK_BEGIN: f->SeekPos = nOffset; break; case FILE_SEEK_CURRENT: f->SeekPos += nOffset; break;

case FILE_SEEK_END: f->SeekPos = f->Directory.FileSize+nOffset; break; default: bSuccess = FALSE; break; }

f->Cluster = f->Directory.FirstLogicalCluster; f->ClusterSeq = 0; return bSuccess; }

void Fat_FileClose(FAT_FILE_HANDLE hFileHandle){ FAT_FILE_INFO *f = (FAT_FILE_INFO *)hFileHandle; if (!f) return; free(f);}

bool Fat_FileIsOpened(FAT_FILE_HANDLE hFileHandle){ FAT_FILE_INFO *f = (FAT_FILE_INFO *)hFileHandle; if (!f) return FALSE; return f->IsOpened; }

float Fat_SpeedTest(FAT_HANDLE hFat, alt_u32 TestDurInMs){ bool bSuccess = TRUE;

alt_u32 time_start, time_finish, time_elapsed, TotalReadBytes=0; int nSecter = 0;

float fMegaBytePerSec = 0; char szBlock[512];

VOLUME_INFO *pVol = (VOLUME_INFO *)hFat;

if (!pVol) return 0; time_start = alt_nticks();

time_finish = alt_nticks() + TestDurInMs * 1000 / alt_ticks_per_second(); while(alt_nticks() < time_finish && bSuccess){

bSuccess = pVol->ReadBlock512(pVol->DiskHandle, nSecter, szBlock); nSecter++;

TotalReadBytes += sizeof(szBlock); } if (bSuccess){ time_elapsed = alt_nticks() - time_start;

fMegaBytePerSec = (float)TotalReadBytes * (float)alt_ticks_per_second() / (float)time_elapsed / 1024.0 / 1024.0; }

Thư viện FatInternal.c: #include "..\terasic_lib\terasic_includes.h" #include "FatFileSystem.h" #include "FatInternal.h" #include "FatConfig.h" #ifdef SUPPORT_SD_CARD #include "..\terasic_sdcard\SDCardDriver.h" #endif //SUPPORT_USB_DISK #ifdef SUPPORT_USB_DISK #include "..\terasic_usb_isp1761\class\usb_disk\usb_disk.h" #include "..\terasic_usb_isp1761\usb_host\usb_hub.h" #endif //SUPPORT_USB_DISK #ifdef DEBUG_FAT

#define FAT_DEBUG(x) {DEBUG(("[FAT]")); DEBUG(x);} #else

#define FAT_DEBUG(x) #endif

//extern VOLUME_INFO gVolumeInfo; // For FAT16 only

CLUSTER_TYPE fatClusterType(unsigned short Fat){ CLUSTER_TYPE Type;

if (Fat > 0 && Fat < 0xFFF0) Type = CLUSTER_NEXT_INFILE; else if (Fat >= 0xFFF8) // && Fat <= (unsigned short)0xFFFF) Type = CLUSTER_LAST_INFILE;

else if (Fat == (unsigned short)0x00) Type = CLUSTER_UNUSED; else if (Fat >= 0xFFF0 && Fat <= 0xFFF6) Type = CLUSTER_RESERVED; else if (Fat == 0xFFF7) Type = CLUSTER_BAD;

return Type;}

unsigned int fatNextCluster(VOLUME_INFO *pVol, unsigned short

ThisCluster){

CLUSTER_TYPE ClusterType; unsigned int NextCluster; #ifdef FAT_READONLY

// const int nFatEntrySize = 2; // 2 byte for FAT16

// NextCluster = *(unsigned short *)(gVolumeInfo.szFatTable + ThisCluster*nFatEntrySize);

NextCluster = *(unsigned short *)(pVol->szFatTable + (ThisCluster << 1)); ClusterType = fatClusterType(NextCluster);

if (ClusterType != CLUSTER_NEXT_INFILE && ClusterType != CLUSTER_LAST_INFILE){

NextCluster = 0; // invalid cluster } #else

int nFatEntryPerSecter;

const int nFatEntrySize = 2; // 2 byte for FAT16 unsigned int Secter;

char szBlock[512];

nFatEntryPerSecter = pVol->BPB_BytsPerSec/nFatEntrySize;

Secter = pVol->FatEntrySecter + (ThisCluster*nFatEntrySize)/pVol- >BPB_BytsPerSec;

if (pVol->ReadBlock512(pVol->DiskHandle, Secter,szBlock)){

NextCluster = *(unsigned short *)(szBlock +

(ThisCluster%nFatEntryPerSecter)*nFatEntrySize); ClusterType = fatClusterType(NextCluster);

if (ClusterType != CLUSTER_NEXT_INFILE && ClusterType !=

CLUSTER_LAST_INFILE)

NextCluster = 0; // invalid cluster } return NextCluster;

#endif

return NextCluster;}

void fatDumpDate(unsigned short Date){ int Year, Month, Day;

Year = ((Date >> 9) & 0x1F) + 1980; Month = ((Date >> 5) & 0xF);

Day = ((Date >> 0) & 0x1F);

FAT_DEBUG(("%d,%d,%d", Year, Month, Day)); } void fatDumpTime(unsigned short Date){

int H,M,S;

H = ((Date >> 9) & 0x1F); M = ((Date >> 5) & 0x3F); S = ((Date >> 0) & 0x1F)*2;

FAT_DEBUG(("%d:%d:%d", H, M, S)); } bool fatIsLast(FAT_DIRECTORY *pDir){

if (pDir->Name[0] == 0x00) return TRUE;

return FALSE; }

char szTest[] = {0x00, 0xE5, 0x22, 0x2A, 0x2B, 0x2C, 0x2E, 0x2F, 0x3A, 0x3B, 0x3C, 0x3E, 0x3F, 0x5B, 0x5C, 0x5D, 0x7C}; int i; for(i=0;i<sizeof(szTest)/sizeof(szTest[0]);i++){ if (pDir->Name[0] == szTest[i]){ return FALSE;}} return TRUE;} // debug

void fatDump(FAT_DIRECTORY *pDir){

char szInvalidName[] = {0x22, 0x2A, 0x2B, 0x2C, 0x2E, 0x2F, 0x3A, 0x3B, 0x3C, 0x3E, 0x3F, 0x5B, 0x5C, 0x5D, 0x7C};

int i;

if (pDir->Name[0] == (char)0xE5){

FAT_DEBUG(("the directory entry is free.\n")); return;}

if (pDir->Name[0] == 0x00){

FAT_DEBUG(("the directory entry is free, and there are no allocated directory entries after tis one.\n"));

return;}

if (pDir->Name[0] <= 0x20 && pDir->Name[0] != 0x05){ FAT_DEBUG(("Invalid file name.\n"));

Một phần của tài liệu khảo sát và thực hiện một số ứng dụng với board altera fpga de3 (Trang 71)

Tải bản đầy đủ (PDF)

(133 trang)