From 3a59de2947dc7d275fb8c3ea01065d6a38c5933a Mon Sep 17 00:00:00 2001 From: Byron Lathi Date: Thu, 14 Apr 2022 11:19:08 -0500 Subject: [PATCH 1/7] Change data count to have proper width (9) This was probably an off-by-one mistage, with the width set to 10 instead of 9. The width should be 9 since the buffer is 512 bytes. --- hw/fpga/sd_controller.sv | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/hw/fpga/sd_controller.sv b/hw/fpga/sd_controller.sv index b8f864f..c606a31 100644 --- a/hw/fpga/sd_controller.sv +++ b/hw/fpga/sd_controller.sv @@ -24,7 +24,7 @@ logic [47:0] rxcmd_buf; logic [31:0] rx_val; logic [7:0] rxdata_buf [512]; -logic [9:0] data_count; +logic [8:0] data_count; logic [15:0] data_crc; @@ -89,7 +89,7 @@ always_ff @(posedge clk) begin end if (cs & addr == 4'h5 && sd_clk) begin - data_count <= data_count + 9'b1; + data_count <= data_count + 8'b1; end if (state.macro == RXCMD) begin @@ -102,6 +102,7 @@ always_ff @(posedge clk) begin if (state.macro == RXDCRC && ~sd_clk) begin data_crc[4'd15-state.count] <= i_sd_data; + data_count <= '0; end end From ee95a592cd2cf19da345e7959080e69b900d9809 Mon Sep 17 00:00:00 2001 From: Byron Lathi Date: Thu, 14 Apr 2022 11:20:48 -0500 Subject: [PATCH 2/7] Reset bit count upon entering RXDATA The but count should be set to 7 when entering RXDATA. previously it was not reset or left at 0, which caused the first byte to only have the lsb set and all other bits to be read incorrectly. --- hw/fpga/sd_controller.sv | 1 + 1 file changed, 1 insertion(+) diff --git a/hw/fpga/sd_controller.sv b/hw/fpga/sd_controller.sv index c606a31..54b7001 100644 --- a/hw/fpga/sd_controller.sv +++ b/hw/fpga/sd_controller.sv @@ -136,6 +136,7 @@ always_comb begin end if (~i_sd_data) begin + next_state.d_bit_count = '1; next_state.macro = RXDATA; end From d1409281483e546c81f76c5ce4e3185500feee58 Mon Sep 17 00:00:00 2001 From: Byron Lathi Date: Thu, 14 Apr 2022 11:23:44 -0500 Subject: [PATCH 3/7] Add testing function for reading sd blocks Add a simple function which reads a 512 block from the SD card and then prints it to the console. --- sw/main.c | 38 ++++++++++++++++++++++++++------------ 1 file changed, 26 insertions(+), 12 deletions(-) diff --git a/sw/main.c b/sw/main.c index dc7182b..d32281d 100644 --- a/sw/main.c +++ b/sw/main.c @@ -6,6 +6,28 @@ #include "mapper.h" #include "sd_card.h" +uint8_t buf[512]; + +void sd_readblock(uint8_t addr) { + uint32_t resp; + int i; + + sd_card_command(addr, 17); + sd_card_resp(&resp); + cprintf("CMD17: %lx\n", resp); + + sd_card_wait_for_data(); + + cprintf("Read data: \n"); + for (i = 0; i < 512; i++){ + buf[i] = sd_card_read_byte(); + } + + for (i = 0; i < 512; i++){ + cprintf("%c", buf[i]); + } +} + int main() { int i; uint8_t sw; @@ -83,20 +105,12 @@ int main() { sd_card_resp(&resp); cprintf("CMD13: %lx\n", resp); - sd_card_command(0, 17); - sd_card_resp(&resp); - cprintf("CMD17: %lx\n", resp); + sd_readblock(0); + sd_readblock(1); + sd_readblock(2); + sd_readblock(3); - while(sw_read()); - - sd_card_wait_for_data(); - - cprintf("Read data: \n"); - for (i = 0; i < 512; i++){ - cprintf("%c", sd_card_read_byte()); - } - while (1) { sw = sw_read(); From 3c68e4584f316f9e66d88368ba86286e414512b8 Mon Sep 17 00:00:00 2001 From: Byron Lathi Date: Thu, 14 Apr 2022 13:49:11 -0500 Subject: [PATCH 4/7] Add some definitions for FAT32 file system Adds some struct types for the FAT32 file system. This just includes the information in the parameter blocks, not any actual files. --- sw/fat.h | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 sw/fat.h diff --git a/sw/fat.h b/sw/fat.h new file mode 100644 index 0000000..dcfb564 --- /dev/null +++ b/sw/fat.h @@ -0,0 +1,42 @@ +#ifndef _FAT_H +#define _FAT_H + +#include + +typedef struct { + uint16_t bytes_per_sector; + uint8_t sectors_per_cluster; + uint16_t reserved_sectors; + uint8_t fat_count; + uint16_t max_dir_entries; + uint16_t total_sector_count; + uint8_t media_descriptor; + uint16_t sectors_per_fat; +} dos_2_bpb_t; + +typedef struct { + dos_2_bpb_t bpb2; + uint16_t sectors_per_track; + uint16_t head_count; + uint32_t hidden_sector_count; + uint32_t logical_sector_count; + uint32_t sectors_per_fat; + uint16_t extended_flags; + uint16_t version; + uint32_t root_cluster; + uint16_t system_information; + uint16_t backup_boot_sector; + uint8_t reserved[12]; +} dos_3_bpb_t; + +typedef struct { + dos_3_bpb_t bpb3; + uint8_t drive_num; + uint8_t reserved; + uint8_t extended_signature; + uint32_t volume_id; + uint8_t partition_label[11]; + uint8_t filesystem_type[8]; +} ebpb_t; + +#endif \ No newline at end of file From 7df0b67b12fdd47e7cd4a111dad542e66e295e78 Mon Sep 17 00:00:00 2001 From: Byron Lathi Date: Thu, 14 Apr 2022 13:50:14 -0500 Subject: [PATCH 5/7] Print out information about the sd card filesystem. Prints out all of the parameter blocks for the SD card. --- sw/main.c | 43 +++++++++++++++++++++++++++++++++++++++---- 1 file changed, 39 insertions(+), 4 deletions(-) diff --git a/sw/main.c b/sw/main.c index d32281d..587dfd3 100644 --- a/sw/main.c +++ b/sw/main.c @@ -5,6 +5,7 @@ #include "uart.h" #include "mapper.h" #include "sd_card.h" +#include "fat.h" uint8_t buf[512]; @@ -24,14 +25,19 @@ void sd_readblock(uint8_t addr) { } for (i = 0; i < 512; i++){ - cprintf("%c", buf[i]); + if (i % 16 == 0) + cprintf("\n %2x: ", i); + cprintf("%2x ", buf[i]); } + + cprintf("\n"); } int main() { int i; uint8_t sw; uint32_t resp; + ebpb_t* epbp; char s[16]; s[15] = 0; @@ -106,10 +112,39 @@ int main() { cprintf("CMD13: %lx\n", resp); sd_readblock(0); - sd_readblock(1); - sd_readblock(2); - sd_readblock(3); + epbp = (ebpb_t*)&buf[11]; + + cprintf("Bytes per sector: %d\n", epbp->bpb3.bpb2.bytes_per_sector); + cprintf("Sectors per cluster: %d\n", epbp->bpb3.bpb2.sectors_per_cluster); + cprintf("Reserved Sectors: %d\n", epbp->bpb3.bpb2.reserved_sectors); + cprintf("Fat Count: %d\n", epbp->bpb3.bpb2.fat_count); + cprintf("Max Dir Entries: %d\n", epbp->bpb3.bpb2.max_dir_entries); + cprintf("Total Sector Count: %d\n", epbp->bpb3.bpb2.total_sector_count); + cprintf("Media Descriptor: 0x%x\n", epbp->bpb3.bpb2.media_descriptor); + cprintf("Sectors per Fat: %d\n", epbp->bpb3.bpb2.sectors_per_fat); + cprintf("\n"); + + cprintf("Sectors per track: %d\n", epbp->bpb3.sectors_per_track); + cprintf("Head Count: %d\n", epbp->bpb3.head_count); + cprintf("Hidden Sector Count: %d\n", epbp->bpb3.hidden_sector_count); + cprintf("Logical Sector Count: %d\n", epbp->bpb3.logical_sector_count); + cprintf("Sectors per Fat: %d\n", epbp->bpb3.sectors_per_fat); + cprintf("Extended Flags: 0x%x\n", epbp->bpb3.extended_flags); + cprintf("Version: %d\n", epbp->bpb3.version); + cprintf("Root Cluster: 0x%x\n", epbp->bpb3.root_cluster); + cprintf("System Information: 0x%x\n", epbp->bpb3.system_information); + cprintf("Backup Boot Sector: 0x%x\n", epbp->bpb3.backup_boot_sector); + cprintf("\n"); + + cprintf("Drive Number: %d\n", epbp->drive_num); + cprintf("Extended Signature: 0x%x\n", epbp->extended_signature); + cprintf("Volume ID: 0x%lx\n", epbp->volume_id); + cprintf("Partition Label: %.11s\n", &epbp->partition_label); + cprintf("Partition Label: %.8s\n", &epbp->filesystem_type); + cprintf("\n"); + + cprintf("Boot Signature: %x %x\n", buf[510], buf[511]); while (1) { From 380550c77d84e8a587d0c96e54f68bb3337e998a Mon Sep 17 00:00:00 2001 From: Byron Lathi Date: Thu, 14 Apr 2022 17:04:08 -0500 Subject: [PATCH 6/7] Add more struct definitions Adds filesystem info struct and directory entry structs --- sw/fat.h | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/sw/fat.h b/sw/fat.h index dcfb564..c61b152 100644 --- a/sw/fat.h +++ b/sw/fat.h @@ -39,4 +39,39 @@ typedef struct { uint8_t filesystem_type[8]; } ebpb_t; +typedef struct { + uint32_t sig; + uint8_t reserved[480]; + uint32_t sig2; + uint32_t free_data_clusters; + uint32_t last_allocated_data_cluster; + uint32_t reserved2; + uint32_t sig3; +} fs_info_sector_t; + +typedef struct { + uint8_t sequence_number; + uint16_t filename0[5]; + uint8_t attributes; + uint8_t type; + uint8_t checksum; + uint16_t filename1[6]; + uint16_t reserved; + uint16_t filename[2]; +} vfat_dentry_t; + +typedef struct { + uint8_t filename[8]; + uint8_t extension[3]; + uint8_t attributes; + uint8_t reserved; + uint8_t create_time_10ms; + uint32_t create_date; + uint16_t access_date; + uint16_t first_cluster_h; + uint32_t modify_cluster; + uint16_t first_cluster_l; + uint32_t file_size; +} dos_dentry_t; + #endif \ No newline at end of file From 246d7a5e6fd96d254cc42a9505400390d400f989 Mon Sep 17 00:00:00 2001 From: Byron Lathi Date: Thu, 14 Apr 2022 17:04:47 -0500 Subject: [PATCH 7/7] Print out more information, read a file Prints out information about the drive, now inside its own function. Also changes the read function to take in a 32 bit address instead of a 16 bit one. Attempts to read the first file on the disk --- sw/main.c | 165 ++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 112 insertions(+), 53 deletions(-) diff --git a/sw/main.c b/sw/main.c index 587dfd3..30332d0 100644 --- a/sw/main.c +++ b/sw/main.c @@ -9,7 +9,7 @@ uint8_t buf[512]; -void sd_readblock(uint8_t addr) { +void sd_readblock(uint32_t addr) { uint32_t resp; int i; @@ -24,20 +24,65 @@ void sd_readblock(uint8_t addr) { buf[i] = sd_card_read_byte(); } + /* for (i = 0; i < 512; i++){ if (i % 16 == 0) cprintf("\n %2x: ", i); cprintf("%2x ", buf[i]); } + */ cprintf("\n"); } +void print_pbp_info(ebpb_t* epbp){ + cprintf("Bytes per sector: %d\n", epbp->bpb3.bpb2.bytes_per_sector); + cprintf("Sectors per cluster: %d\n", epbp->bpb3.bpb2.sectors_per_cluster); + cprintf("Reserved Sectors: %d\n", epbp->bpb3.bpb2.reserved_sectors); + cprintf("Fat Count: %d\n", epbp->bpb3.bpb2.fat_count); + cprintf("Max Dir Entries: %d\n", epbp->bpb3.bpb2.max_dir_entries); + cprintf("Total Sector Count: %d\n", epbp->bpb3.bpb2.total_sector_count); + cprintf("Media Descriptor: 0x%x\n", epbp->bpb3.bpb2.media_descriptor); + cprintf("Sectors per Fat: %d\n", epbp->bpb3.bpb2.sectors_per_fat); + cprintf("\n"); + + cprintf("Sectors per track: %d\n", epbp->bpb3.sectors_per_track); + cprintf("Head Count: %d\n", epbp->bpb3.head_count); + cprintf("Hidden Sector Count: %ld\n", epbp->bpb3.hidden_sector_count); + cprintf("Logical Sector Count: %ld\n", epbp->bpb3.logical_sector_count); + cprintf("Sectors per Fat: %ld\n", epbp->bpb3.sectors_per_fat); + cprintf("Extended Flags: 0x%x\n", epbp->bpb3.extended_flags); + cprintf("Version: %d\n", epbp->bpb3.version); + cprintf("Root Cluster: 0x%lx\n", epbp->bpb3.root_cluster); + cprintf("System Information: 0x%x\n", epbp->bpb3.system_information); + cprintf("Backup Boot Sector: 0x%x\n", epbp->bpb3.backup_boot_sector); + cprintf("\n"); + + cprintf("Drive Number: %d\n", epbp->drive_num); + cprintf("Extended Signature: 0x%x\n", epbp->extended_signature); + cprintf("Volume ID: 0x%lx\n", epbp->volume_id); + cprintf("Partition Label: %.11s\n", &epbp->partition_label); + cprintf("Partition Label: %.8s\n", &epbp->filesystem_type); + cprintf("\n"); +} + int main() { int i; uint8_t sw; uint32_t resp; ebpb_t* epbp; + fs_info_sector_t* fsis; + vfat_dentry_t* vfat_dentry; + dos_dentry_t* dos_dentry; + uint32_t cluster; + + + uint16_t reserved_count; + uint32_t sectors_per_fat; + uint8_t fat_count; + + uint32_t data_region_start; + char s[16]; s[15] = 0; @@ -45,36 +90,13 @@ int main() { cprintf("Hello, world!\n"); for (i = 0; i < 16; i++){ - cprintf("Mapping %1xxxx to %2xxxx\n", i, i); + //cprintf("Mapping %1xxxx to %2xxxx\n", i, i); mapper_write(i, i); } cprintf("Enabling Mapper\n"); mapper_enable(1); - cprintf("Writing 0xcccc to 0x4000\n"); - *(unsigned int*)(0x4000) = 0xcccc; - - cprintf("Writing 0xdddd to 0x5000\n"); - *(unsigned int*)(0x5000) = 0xdddd; - - cprintf("Mapping %1xxxx to %2xxxx\n", 4, 16); - mapper_write(16, 4); - - cprintf("Mapping %1xxxx to %2xxxx\n", 5, 16); - mapper_write(16, 5); - - cprintf("Writing 0xa5a5 to 0x4000\n"); - *(unsigned int*)(0x4000) = 0xa5a5; - - cprintf("Reading from 0x5000: %x\n", *(unsigned int*)(0x5000)); - - cprintf("Resetting map\n"); - mapper_write(4, 4); - mapper_write(5, 5); - - cprintf("Reading from 0x4000: %x\n", *(unsigned int*)(0x4000)); - cprintf("Reading from 0x5000: %x\n", *(unsigned int*)(0x5000)); // This will read a 512 block from the sd card. // The RCA is hard coded for the one that I have on hand as responses @@ -115,37 +137,74 @@ int main() { epbp = (ebpb_t*)&buf[11]; - cprintf("Bytes per sector: %d\n", epbp->bpb3.bpb2.bytes_per_sector); - cprintf("Sectors per cluster: %d\n", epbp->bpb3.bpb2.sectors_per_cluster); - cprintf("Reserved Sectors: %d\n", epbp->bpb3.bpb2.reserved_sectors); - cprintf("Fat Count: %d\n", epbp->bpb3.bpb2.fat_count); - cprintf("Max Dir Entries: %d\n", epbp->bpb3.bpb2.max_dir_entries); - cprintf("Total Sector Count: %d\n", epbp->bpb3.bpb2.total_sector_count); - cprintf("Media Descriptor: 0x%x\n", epbp->bpb3.bpb2.media_descriptor); - cprintf("Sectors per Fat: %d\n", epbp->bpb3.bpb2.sectors_per_fat); - cprintf("\n"); - - cprintf("Sectors per track: %d\n", epbp->bpb3.sectors_per_track); - cprintf("Head Count: %d\n", epbp->bpb3.head_count); - cprintf("Hidden Sector Count: %d\n", epbp->bpb3.hidden_sector_count); - cprintf("Logical Sector Count: %d\n", epbp->bpb3.logical_sector_count); - cprintf("Sectors per Fat: %d\n", epbp->bpb3.sectors_per_fat); - cprintf("Extended Flags: 0x%x\n", epbp->bpb3.extended_flags); - cprintf("Version: %d\n", epbp->bpb3.version); - cprintf("Root Cluster: 0x%x\n", epbp->bpb3.root_cluster); - cprintf("System Information: 0x%x\n", epbp->bpb3.system_information); - cprintf("Backup Boot Sector: 0x%x\n", epbp->bpb3.backup_boot_sector); - cprintf("\n"); - - cprintf("Drive Number: %d\n", epbp->drive_num); - cprintf("Extended Signature: 0x%x\n", epbp->extended_signature); - cprintf("Volume ID: 0x%lx\n", epbp->volume_id); - cprintf("Partition Label: %.11s\n", &epbp->partition_label); - cprintf("Partition Label: %.8s\n", &epbp->filesystem_type); - cprintf("\n"); + print_pbp_info(epbp); cprintf("Boot Signature: %x %x\n", buf[510], buf[511]); + reserved_count = epbp->bpb3.bpb2.reserved_sectors; + fat_count = epbp->bpb3.bpb2.fat_count; + sectors_per_fat = epbp->bpb3.sectors_per_fat; + + sd_readblock(1); + + fsis = (fs_info_sector_t*)&buf[0]; + + cprintf("Free Data clusters: %ld\n", fsis->free_data_clusters); + cprintf("Last allocated data cluster: %ld\n", fsis->last_allocated_data_cluster); + + cprintf("32 reserved sectors, reading from sector 32...\n"); + sd_readblock(32); + cprintf("CLUST_0: %08lx\n", *(uint32_t*)&buf[0]); + cprintf("CLUST_1: %08lx\n", *(uint32_t*)&buf[1*4]); + + cprintf("Root cluster: %08lx\n", *(uint32_t*)&buf[2*4]); + + data_region_start = reserved_count + fat_count*sectors_per_fat; + cprintf("Data Region starting sector: %lx\n", data_region_start); + cprintf("Reading root directory entry...\n"); + + cprintf("%ld\n", data_region_start*512); + + sd_readblock(data_region_start); + + vfat_dentry = (vfat_dentry_t*)buf; + while(vfat_dentry->sequence_number == 0xe5) + vfat_dentry++; + + + cprintf("Sequence: %x\n", vfat_dentry->sequence_number); + cprintf("Name: "); + for (i = 0;; i++) { // this will not work for proper vfat names + if (i < 5) { + if (!vfat_dentry->filename0[i]) + break; + cprintf("%c", vfat_dentry->filename0[i]); + } else if (i < 11) { + if (!vfat_dentry->filename0[i]) + break; + cprintf("%c", vfat_dentry->filename1[i-5]); + } else { + break; + } + } + cprintf("\n"); + dos_dentry = (dos_dentry_t*)(vfat_dentry + 1); + + cprintf("DOS name: %.8s.%.3s\n", &dos_dentry->filename, &dos_dentry->extension); + + cluster = (dos_dentry->first_cluster_h << 16) + dos_dentry->first_cluster_l; + cprintf("Cluster: %ld\n", cluster); + + cprintf("File location: %lx\n", data_region_start + (cluster - 2) * 8); + + sd_readblock(data_region_start + (cluster - 2) * 8); + + cprintf("File contents: %s\n", buf); + + cprintf("Done!\n"); + + + while (1) { sw = sw_read();