Move code out of main and into their own files
All of the SD card commands are moved into their own file, with functions sd_init, sd_get_rca, sd_select_card, sd_get_status, and sd_readblock. The FAT functions are movied into fat.c and give functions fat_init and fat_read. Note that the filename is ignored for now, it always reads the first file in the root directory. The loading of o65 files is done in o65.c, and executing is done in exec.c This cleans up the main file signifigantly and leaves the project open to expansion.
This commit is contained in:
61
sw/exec.c
Normal file
61
sw/exec.c
Normal file
@@ -0,0 +1,61 @@
|
||||
#include <stdint.h>
|
||||
#include <conio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "fat.h"
|
||||
#include "o65.h"
|
||||
|
||||
void exec(char* filename) {
|
||||
o65_header_t* header;
|
||||
o65_opt_t* o65_opt;
|
||||
uint8_t* seg_ptr;
|
||||
|
||||
uint8_t* code_base;
|
||||
uint8_t* data_base;
|
||||
uint16_t code_len;
|
||||
uint16_t data_len;
|
||||
|
||||
uint8_t (*exec)(void);
|
||||
uint8_t ret;
|
||||
|
||||
fat_read(filename, fat_buf);
|
||||
|
||||
header = (o65_header_t*)fat_buf;
|
||||
|
||||
if (header->c64_marker == O65_NON_C64 &&
|
||||
header->magic[0] == O65_MAGIC_0 &&
|
||||
header->magic[1] == O65_MAGIC_1 &&
|
||||
header->magic[2] == O65_MAGIC_2) {
|
||||
|
||||
code_base = (uint8_t*)header->tbase;
|
||||
data_base = (uint8_t*)header->dbase;
|
||||
code_len = header->tlen;
|
||||
data_len = header->dlen;
|
||||
|
||||
|
||||
o65_opt = (o65_opt_t*)(fat_buf + sizeof(o65_header_t));
|
||||
while (o65_opt->olen)
|
||||
{
|
||||
o65_print_option(o65_opt);
|
||||
o65_opt = (o65_opt_t*)((uint8_t*)o65_opt + o65_opt->olen);
|
||||
}
|
||||
|
||||
seg_ptr = (uint8_t*)o65_opt + 1;
|
||||
|
||||
memcpy((uint8_t*)code_base, seg_ptr, code_len);
|
||||
|
||||
seg_ptr+=code_len;
|
||||
|
||||
memcpy((uint8_t*)data_base, seg_ptr, data_len);
|
||||
|
||||
exec = (uint8_t (*)(void))code_base;
|
||||
|
||||
ret = 0;
|
||||
|
||||
ret = (*exec)();
|
||||
|
||||
cprintf("ret: %x\n", ret);
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
6
sw/exec.h
Normal file
6
sw/exec.h
Normal file
@@ -0,0 +1,6 @@
|
||||
#ifndef _EXEC_H
|
||||
#define _EXEC_H
|
||||
|
||||
void exec(char* filename);
|
||||
|
||||
#endif
|
||||
73
sw/fat.c
Normal file
73
sw/fat.c
Normal file
@@ -0,0 +1,73 @@
|
||||
#include <conio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "fat.h"
|
||||
#include "sd_card.h"
|
||||
|
||||
uint8_t fat_buf[512];
|
||||
|
||||
static full_bpb_t bpb;
|
||||
|
||||
static uint32_t data_region_start;
|
||||
|
||||
void fat_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");
|
||||
}
|
||||
|
||||
void fat_init(){
|
||||
sd_readblock(0, fat_buf);
|
||||
|
||||
memcpy(&bpb, &fat_buf[11], sizeof(ebpb_t));
|
||||
|
||||
sd_readblock(1, fat_buf);
|
||||
sd_readblock(32, fat_buf);
|
||||
|
||||
data_region_start = bpb.reserved_sectors + bpb.fat_count*bpb.sectors_per_fat_32;
|
||||
}
|
||||
|
||||
void fat_read(char* filename, void* buf) {
|
||||
vfat_dentry_t* vfat_dentry;
|
||||
dos_dentry_t* dos_dentry;
|
||||
uint32_t cluster;
|
||||
|
||||
(void)filename; //just ignore filename
|
||||
|
||||
sd_readblock(data_region_start, buf);
|
||||
|
||||
vfat_dentry = (vfat_dentry_t*)buf;
|
||||
while(vfat_dentry->sequence_number == 0xe5)
|
||||
vfat_dentry++;
|
||||
|
||||
dos_dentry = (dos_dentry_t*)(vfat_dentry + 1);
|
||||
|
||||
cluster = ((uint32_t)dos_dentry->first_cluster_h << 16) + dos_dentry->first_cluster_l;
|
||||
|
||||
sd_readblock(data_region_start + (cluster - 2) * 8, buf);
|
||||
}
|
||||
34
sw/fat.h
34
sw/fat.h
@@ -3,6 +3,8 @@
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
extern uint8_t fat_buf[];
|
||||
|
||||
typedef struct {
|
||||
uint16_t bytes_per_sector;
|
||||
uint8_t sectors_per_cluster;
|
||||
@@ -39,6 +41,34 @@ typedef struct {
|
||||
uint8_t filesystem_type[8];
|
||||
} ebpb_t;
|
||||
|
||||
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_16;
|
||||
uint16_t sectors_per_track;
|
||||
uint16_t head_count;
|
||||
uint32_t hidden_sector_count;
|
||||
uint32_t logical_sector_count;
|
||||
uint32_t sectors_per_fat_32;
|
||||
uint16_t extended_flags;
|
||||
uint16_t version;
|
||||
uint32_t root_cluster;
|
||||
uint16_t system_information;
|
||||
uint16_t backup_boot_sector;
|
||||
uint8_t reserved[12];
|
||||
uint8_t drive_num;
|
||||
uint8_t reserved2;
|
||||
uint8_t extended_signature;
|
||||
uint32_t volume_id;
|
||||
uint8_t partition_label[11];
|
||||
uint8_t filesystem_type[8];
|
||||
} full_bpb_t;
|
||||
|
||||
typedef struct {
|
||||
uint32_t sig;
|
||||
uint8_t reserved[480];
|
||||
@@ -74,4 +104,8 @@ typedef struct {
|
||||
uint32_t file_size;
|
||||
} dos_dentry_t;
|
||||
|
||||
void fat_print_pbp_info(ebpb_t* epbp);
|
||||
void fat_init();
|
||||
void fat_read(char* filename, void* buf);
|
||||
|
||||
#endif
|
||||
300
sw/main.c
300
sw/main.c
@@ -8,96 +8,13 @@
|
||||
#include "sd_card.h"
|
||||
#include "fat.h"
|
||||
#include "o65.h"
|
||||
#include "exec.h"
|
||||
|
||||
uint8_t buf[512];
|
||||
|
||||
void sd_readblock(uint32_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++){
|
||||
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;
|
||||
|
||||
o65_header_t* header;
|
||||
o65_opt_t* o65_opt;
|
||||
uint8_t* seg_ptr;
|
||||
|
||||
uint8_t* code_base;
|
||||
uint8_t* data_base;
|
||||
uint16_t code_len;
|
||||
uint16_t data_len;
|
||||
|
||||
uint8_t (*exec)(void);
|
||||
uint8_t ret;
|
||||
|
||||
uint16_t reserved_count;
|
||||
uint32_t sectors_per_fat;
|
||||
uint8_t fat_count;
|
||||
|
||||
uint32_t data_region_start;
|
||||
|
||||
char s[16];
|
||||
s[15] = 0;
|
||||
uint16_t rca;
|
||||
|
||||
clrscr();
|
||||
cprintf("Hello, world!\n");
|
||||
@@ -110,218 +27,17 @@ int main() {
|
||||
cprintf("Enabling Mapper\n");
|
||||
mapper_enable(1);
|
||||
|
||||
sd_init();
|
||||
|
||||
// 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
|
||||
// are not implemented yet.
|
||||
sd_card_command(0, 0);
|
||||
rca = sd_get_rca();
|
||||
cprintf("rca: %x\n", rca);
|
||||
|
||||
sd_card_command(0x000001aa, 8);
|
||||
sd_card_resp(&resp);
|
||||
cprintf("CMD8: %lx\n", resp);
|
||||
|
||||
sd_card_command(0, 55);
|
||||
sd_card_command(0x40180000, 41);
|
||||
sd_card_resp(&resp);
|
||||
cprintf("CMD41: %lx\n", resp);
|
||||
|
||||
sd_card_command(0, 55);
|
||||
sd_card_command(0x40180000, 41);
|
||||
sd_card_resp(&resp);
|
||||
cprintf("CMD41: %lx\n", resp);
|
||||
|
||||
sd_card_command(0, 2);
|
||||
sd_card_resp(&resp);
|
||||
cprintf("CMD2: %lx\n", resp);
|
||||
|
||||
sd_card_command(0, 3);
|
||||
sd_card_resp(&resp);
|
||||
cprintf("CMD3: %lx\n", resp);
|
||||
|
||||
sd_card_command(0x59b40000, 7);
|
||||
sd_card_resp(&resp);
|
||||
cprintf("CMD7: %lx\n", resp);
|
||||
|
||||
sd_card_command(0x59b41000, 13);
|
||||
sd_card_resp(&resp);
|
||||
cprintf("CMD13: %lx\n", resp);
|
||||
|
||||
sd_readblock(0);
|
||||
|
||||
epbp = (ebpb_t*)&buf[11];
|
||||
|
||||
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 = ((uint32_t)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);
|
||||
|
||||
header = (o65_header_t*)buf;
|
||||
|
||||
if (header->c64_marker == O65_NON_C64 &&
|
||||
header->magic[0] == O65_MAGIC_0 &&
|
||||
header->magic[1] == O65_MAGIC_1 &&
|
||||
header->magic[2] == O65_MAGIC_2) {
|
||||
cprintf("Found a valid o65 file!\n\n");
|
||||
|
||||
cprintf("tbase: %x\n", header->tbase);
|
||||
cprintf("tlen: %x\n", header->tlen);
|
||||
cprintf("dbase: %x\n", header->dbase);
|
||||
cprintf("dlen: %x\n", header->dlen);
|
||||
cprintf("bbase: %x\n", header->bbase);
|
||||
cprintf("blen: %x\n", header->blen);
|
||||
cprintf("zbase: %x\n", header->zbase);
|
||||
cprintf("zlen: %x\n", header->zlen);
|
||||
cprintf("stack: %x\n", header->stack);
|
||||
cprintf("\n");
|
||||
|
||||
code_base = (uint8_t*)header->tbase;
|
||||
data_base = (uint8_t*)header->dbase;
|
||||
code_len = header->tlen;
|
||||
data_len = header->dlen;
|
||||
|
||||
|
||||
o65_opt = (o65_opt_t*)(buf + sizeof(o65_header_t));
|
||||
while (o65_opt->olen)
|
||||
{
|
||||
cprintf("Option Length: %d\n", o65_opt->olen);
|
||||
cprintf("Option Type: %x ", o65_opt->type);
|
||||
switch (o65_opt->type) {
|
||||
case O65_OPT_FILENAME: cprintf("Filename\n"); break;
|
||||
case O65_OPT_OS: cprintf("OS\n"); break;
|
||||
case O65_OPT_ASSEMBLER: cprintf("Assembler\n"); break;
|
||||
case O65_OPT_AUTHOR: cprintf("Author\n"); break;
|
||||
case O65_OPT_DATE: cprintf("Creation Date\n"); break;
|
||||
default: cprintf("Invalid\n"); break;
|
||||
}
|
||||
|
||||
if (o65_opt->type != O65_OPT_OS) {
|
||||
for (i = 0; i < o65_opt->olen - 2; i++) {
|
||||
cprintf("%c", o65_opt->data[i]);
|
||||
}
|
||||
} else {
|
||||
cprintf("%x", o65_opt->data[0]);
|
||||
}
|
||||
cprintf("\n\n");
|
||||
o65_opt = (o65_opt_t*)((uint8_t*)o65_opt + o65_opt->olen);
|
||||
}
|
||||
|
||||
seg_ptr = (uint8_t*)o65_opt + 1;
|
||||
|
||||
cprintf("Code: \n");
|
||||
for (i = 0; i < code_len; i++) {
|
||||
cprintf("%x ", seg_ptr[i]);
|
||||
}
|
||||
cprintf("\n\n");
|
||||
|
||||
memcpy((uint8_t*)code_base, seg_ptr, code_len);
|
||||
|
||||
seg_ptr+=code_len;
|
||||
|
||||
cprintf("Data: \n");
|
||||
for (i = 0; i < data_len; i++) {
|
||||
cprintf("%x ", seg_ptr[i]);
|
||||
}
|
||||
cprintf("\n\n");
|
||||
|
||||
memcpy((uint8_t*)data_base, seg_ptr, data_len);
|
||||
|
||||
cprintf("Memory Copied!\n");
|
||||
cprintf("Code: \n");
|
||||
for (i = 0; i < code_len; i++) {
|
||||
cprintf("%x ", code_base[i]);
|
||||
}
|
||||
cprintf("\n\n");
|
||||
cprintf("Data: \n");
|
||||
for (i = 0; i < data_len; i++) {
|
||||
cprintf("%x ", data_base[i]);
|
||||
}
|
||||
cprintf("\n\n");
|
||||
|
||||
exec = (uint8_t (*)(void))code_base;
|
||||
|
||||
ret = 0;
|
||||
|
||||
ret = (*exec)();
|
||||
|
||||
cprintf("ret: %x\n", ret);
|
||||
|
||||
|
||||
}
|
||||
sd_select_card(rca);
|
||||
|
||||
fat_init();
|
||||
exec("/test.o65");
|
||||
|
||||
cprintf("Done!\n");
|
||||
|
||||
|
||||
|
||||
while (1) {
|
||||
|
||||
sw = sw_read();
|
||||
led_set(sw);
|
||||
|
||||
cscanf("%15s", s);
|
||||
cprintf("\n");
|
||||
for (i = 0; i < 16; i++)
|
||||
cprintf("s[%d]=%c ", i, s[i]);
|
||||
cprintf("\n");
|
||||
cprintf("Read string: %s\n", s);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
28
sw/o65.c
Normal file
28
sw/o65.c
Normal file
@@ -0,0 +1,28 @@
|
||||
#include <conio.h>
|
||||
|
||||
#include "o65.h"
|
||||
|
||||
void o65_print_option(o65_opt_t* opt) {
|
||||
int i;
|
||||
|
||||
cprintf("Option Length: %d\n", opt->olen);
|
||||
cprintf("Option Type: %x ", opt->type);
|
||||
|
||||
switch (opt->type) {
|
||||
case O65_OPT_FILENAME: cprintf("Filename\n"); break;
|
||||
case O65_OPT_OS: cprintf("OS\n"); break;
|
||||
case O65_OPT_ASSEMBLER: cprintf("Assembler\n"); break;
|
||||
case O65_OPT_AUTHOR: cprintf("Author\n"); break;
|
||||
case O65_OPT_DATE: cprintf("Creation Date\n"); break;
|
||||
default: cprintf("Invalid\n"); break;
|
||||
}
|
||||
|
||||
if (opt->type != O65_OPT_OS) {
|
||||
for (i = 0; i < opt->olen - 2; i++) {
|
||||
cprintf("%c", opt->data[i]);
|
||||
}
|
||||
} else {
|
||||
cprintf("%x", opt->data[0]);
|
||||
}
|
||||
cprintf("\n\n");
|
||||
}
|
||||
2
sw/o65.h
2
sw/o65.h
@@ -60,6 +60,8 @@ typedef struct {
|
||||
uint8_t data[1]; //This is actually variable length
|
||||
} o65_opt_t;
|
||||
|
||||
void o65_print_option(o65_opt_t* opt);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
75
sw/sd_card.c
Normal file
75
sw/sd_card.c
Normal file
@@ -0,0 +1,75 @@
|
||||
#include <stdint.h>
|
||||
#include <conio.h>
|
||||
|
||||
#include "sd_card.h"
|
||||
|
||||
void sd_init() {
|
||||
uint32_t resp;
|
||||
sd_card_command(0, 0);
|
||||
|
||||
sd_card_command(0x000001aa, 8);
|
||||
sd_card_resp(&resp);
|
||||
//cprintf("CMD8: %lx\n", resp);
|
||||
|
||||
sd_card_command(0, 55);
|
||||
sd_card_command(0x40180000, 41);
|
||||
sd_card_resp(&resp);
|
||||
//cprintf("CMD41: %lx\n", resp);
|
||||
|
||||
sd_card_command(0, 55);
|
||||
sd_card_command(0x40180000, 41);
|
||||
sd_card_resp(&resp);
|
||||
//cprintf("CMD41: %lx\n", resp);
|
||||
|
||||
sd_card_command(0, 2);
|
||||
sd_card_resp(&resp);
|
||||
//cprintf("CMD2: %lx\n", resp);
|
||||
}
|
||||
|
||||
uint16_t sd_get_rca() {
|
||||
uint32_t resp;
|
||||
|
||||
sd_card_command(0, 3);
|
||||
resp = 0;
|
||||
sd_card_resp(&resp);
|
||||
|
||||
//cprintf("CMD3: %lx\n", resp);
|
||||
|
||||
return resp >> 16;
|
||||
}
|
||||
|
||||
uint16_t sd_select_card(uint16_t rca) {
|
||||
uint32_t resp;
|
||||
|
||||
sd_card_command((uint32_t)rca << 16, 7);
|
||||
sd_card_resp(&resp);
|
||||
|
||||
return (uint16_t) resp;
|
||||
}
|
||||
|
||||
uint16_t sd_get_status(uint16_t rca) {
|
||||
uint32_t resp;
|
||||
|
||||
sd_card_command((uint32_t)rca << 16, 13);
|
||||
sd_card_resp(&resp);
|
||||
|
||||
return (uint16_t) resp;
|
||||
}
|
||||
|
||||
void sd_readblock(uint32_t addr, void* buf) {
|
||||
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++){
|
||||
((uint8_t*)buf)[i] = sd_card_read_byte();
|
||||
}
|
||||
|
||||
//cprintf("\n");
|
||||
}
|
||||
@@ -3,6 +3,12 @@
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
void sd_init();
|
||||
uint16_t sd_get_rca();
|
||||
uint16_t sd_select_card(uint16_t rca);
|
||||
uint16_t sd_get_status(uint16_t rca);
|
||||
void sd_readblock(uint32_t addr, void* buf);
|
||||
|
||||
void sd_card_command(uint32_t arg, uint8_t cmd);
|
||||
|
||||
void sd_card_resp(uint32_t* resp);
|
||||
|
||||
Reference in New Issue
Block a user