Merge branch 'exec' into 'master'
Move code out of main and into their own files See merge request bslathi19/super6502!14
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);
|
||||
}
|
||||
36
sw/fat.h
36
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;
|
||||
|
||||
#endif
|
||||
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");
|
||||
}
|
||||
4
sw/o65.h
4
sw/o65.h
@@ -60,6 +60,6 @@ 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,10 +3,16 @@
|
||||
|
||||
#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);
|
||||
uint8_t sd_card_read_byte();
|
||||
void sd_card_wait_for_data();
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user