diff --git a/sw/kernel/devices/board_io.h b/sw/kernel/devices/board_io.h new file mode 100644 index 0000000..da8aa51 --- /dev/null +++ b/sw/kernel/devices/board_io.h @@ -0,0 +1,10 @@ +#ifndef _BOARD_IO_H +#define _BOARD_IO_H + +#include + +uint8_t sw_read(); + +void led_set(uint8_t val); + +#endif \ No newline at end of file diff --git a/sw/kernel/devices/board_io.s b/sw/kernel/devices/board_io.s new file mode 100644 index 0000000..e8999e9 --- /dev/null +++ b/sw/kernel/devices/board_io.s @@ -0,0 +1,24 @@ +.include "io.inc65" + +.importzp sp, sreg + +.export _sw_read +.export _led_set + +.autoimport on + +.code + +; @out A: The Value of the switches +; Reads the current values of the switches. +_sw_read: + lda SW + ldx #$0 + rts + +; @in A: val +; @out A: 0 for success, 1 for failure +; Sets the LEDs +_led_set: + sta LED + rts \ No newline at end of file diff --git a/sw/kernel/devices/interrupt.h b/sw/kernel/devices/interrupt.h new file mode 100644 index 0000000..d0231aa --- /dev/null +++ b/sw/kernel/devices/interrupt.h @@ -0,0 +1,15 @@ +#ifndef _INTERRUPT_H +#define _INTERRUPT_H + +#include + +#define BUTTON (1 << 0) +#define UART (1 << 1) + +void irq_int(); +void nmi_int(); + +uint8_t irq_get_status(); +void irq_set_status(uint8_t); + +#endif \ No newline at end of file diff --git a/sw/kernel/devices/interrupt.s b/sw/kernel/devices/interrupt.s new file mode 100644 index 0000000..02b24ae --- /dev/null +++ b/sw/kernel/devices/interrupt.s @@ -0,0 +1,51 @@ +; --------------------------------------------------------------------------- +; interrupt.s +; --------------------------------------------------------------------------- +; +; Interrupt handler. +; +; Checks for a BRK instruction and returns from all valid interrupts. + +.import _handle_irq +.import _cputc, _clrscr + +.export _irq_int, _nmi_int + +.include "io.inc65" + +.segment "CODE" + +.PC02 ; Force 65C02 assembly mode + +; --------------------------------------------------------------------------- +; Non-maskable interrupt (NMI) service routine + +_nmi_int: RTI ; Return from all NMI interrupts + +; --------------------------------------------------------------------------- +; Maskable interrupt (IRQ) service routine + +_irq_int: PHX ; Save X register contents to stack + TSX ; Transfer stack pointer to X + PHA ; Save accumulator contents to stack + INX ; Increment X so it points to the status + INX ; register value saved on the stack + LDA $100,X ; Load status register contents + AND #$10 ; Isolate B status bit + BNE break ; If B = 1, BRK detected + +; --------------------------------------------------------------------------- +; IRQ detected, return + +irq: PLA ; Restore accumulator contents + PLX ; Restore X register contents + jsr _handle_irq ; Handle the IRQ + RTI ; Return from all IRQ interrupts + +; --------------------------------------------------------------------------- +; BRK detected, stop + +break: + pla + plx + rti \ No newline at end of file diff --git a/sw/kernel/devices/sd_card.c b/sw/kernel/devices/sd_card.c new file mode 100644 index 0000000..8eaf708 --- /dev/null +++ b/sw/kernel/devices/sd_card.c @@ -0,0 +1,439 @@ +#include + +#include "sd_card.h" +#include "sd_print.h" +#include "spi.h" + +/******************************************************************************* + Initialize SD card +*******************************************************************************/ +uint8_t SD_init() +{ + uint16_t i; + + uint8_t res[5], cmdAttempts = 0; + + SD_powerUpSeq(); + + while((res[0] = SD_goIdleState()) != SD_IN_IDLE_STATE) + { + cmdAttempts++; + if(cmdAttempts == CMD0_MAX_ATTEMPTS) + { + cputs("Go IDLE\r\n"); + return SD_ERROR; + } + } + + for (i = 0; i < 1000; i++); + + SD_sendIfCond(res); + if(res[0] != SD_IN_IDLE_STATE) + { + cputs("IF Cond\r\n"); + return SD_ERROR; + } + + if(res[4] != 0xAA) + { + return SD_ERROR; + } + + cmdAttempts = 0; + do + { + if(cmdAttempts == CMD55_MAX_ATTEMPTS) + { + cputs("op_cond error\r\n"); + return SD_ERROR; + } + + res[0] = SD_sendApp(); + if(SD_R1_NO_ERROR(res[0])) + { + res[0] = SD_sendOpCond(); + } + + for (i = 0; i < 1000; i++); + + cmdAttempts++; + } + while(res[0] != SD_READY); + + for (i = 0; i < 1000; i++); + + SD_readOCR(res); + + return SD_SUCCESS; +} + +/* +// Send a command with starting end ending clock pulses +uint8_t res1_cmd(uint8_t cmd, uint32_t arg, uint8_t crc) +{ + uint8_t res1; + // assert chip select + spi_exchange(0xFF); + spi_select(0); + spi_exchange(0xFF); + + // send CMD0 + SD_command(cmd, arg, crc); + + // read response + res1 = SD_readRes1(); + + // deassert chip select + spi_exchange(0xFF); + spi_deselect(0); + spi_exchange(0xFF); + + return res1; +} +*/ + +/******************************************************************************* + Run power up sequence +*******************************************************************************/ +/* +void SD_powerUpSeq() +{ + uint16_t i; + uint8_t j; + + // make sure card is deselected + spi_deselect(0); + + // give SD card time to power up + for (i = 0; i < 1000; i++); + + + // select SD card + spi_exchange(0xFF); + spi_deselect(0); + + // send 80 clock cycles to synchronize + for(j = 0; j < SD_INIT_CYCLES; j++) + spi_exchange(0xFF); +} +*/ + +/******************************************************************************* + Send command to SD card +*******************************************************************************/ +/* +void SD_command(uint8_t cmd, uint32_t arg, uint8_t crc) +{ + // transmit command to sd card + spi_exchange(cmd|0x40); + + // transmit argument + spi_exchange((uint8_t)(arg >> 24)); + spi_exchange((uint8_t)(arg >> 16)); + spi_exchange((uint8_t)(arg >> 8)); + spi_exchange((uint8_t)(arg)); + + // transmit crc + spi_exchange(crc|0x01); +} +*/ + +/******************************************************************************* + Read R1 from SD card +*******************************************************************************/ +/* +uint8_t SD_readRes1() +{ + uint8_t i = 0, res1; + + // keep polling until actual data received + while((res1 = spi_exchange(0xFF)) == 0xFF) + { + i++; + + // if no data received for 8 bytes, break + if(i > 8) break; + } + + return res1; +} +*/ + +/******************************************************************************* + Read R2 from SD card +*******************************************************************************/ +/* +void SD_readRes2(uint8_t *res) +{ + // read response 1 in R2 + res[0] = SD_readRes1(); + + // read final byte of response + res[1] = spi_exchange(0xFF); +} +*/ + +/******************************************************************************* + Read R3 from SD card +*******************************************************************************/ +/* +void SD_readRes3(uint8_t *res) +{ + // read response 1 in R3 + res[0] = SD_readRes1(); + + // if error reading R1, return + if(res[0] > 1) return; + + // read remaining bytes + SD_readBytes(res + 1, R3_BYTES); +} +*/ + +/******************************************************************************* + Read R7 from SD card +*******************************************************************************/ +/* +void SD_readRes7(uint8_t *res) +{ + // read response 1 in R7 + res[0] = SD_readRes1(); + + // if error reading R1, return + if(res[0] > 1) return; + + // read remaining bytes + SD_readBytes(res + 1, R7_BYTES); +} +*/ + +/******************************************************************************* + Read specified number of bytes from SD card +*******************************************************************************/ +/* +void SD_readBytes(uint8_t *res, uint8_t n) +{ + while(n--) *res++ = spi_exchange(0xFF); +} +*/ + +/******************************************************************************* + Command Idle State (CMD0) +*******************************************************************************/ +uint8_t SD_goIdleState() +{ + return res1_cmd(CMD0, CMD0_ARG, CMD0_CRC); +} + +/******************************************************************************* + Send Interface Conditions (CMD8) +*******************************************************************************/ +void SD_sendIfCond(uint8_t *res) +{ + // assert chip select + spi_exchange(0xFF); + spi_select(0); + spi_exchange(0xFF); + + // send CMD8 + SD_command(CMD8, CMD8_ARG, CMD8_CRC); + + // read response + SD_readRes7(res); + //SD_readBytes(res + 1, R7_BYTES); + + // deassert chip select + spi_exchange(0xFF); + spi_deselect(0); + spi_exchange(0xFF); +} + +/******************************************************************************* + Read Status +*******************************************************************************/ +void SD_sendStatus(uint8_t *res) +{ + // assert chip select + spi_exchange(0xFF); + spi_select(0); + spi_exchange(0xFF); + + // send CMD13 + SD_command(CMD13, CMD13_ARG, CMD13_CRC); + + // read response + SD_readRes2(res); + + // deassert chip select + spi_exchange(0xFF); + spi_deselect(0); + spi_exchange(0xFF); +} + +/******************************************************************************* + Read single 512 byte block + token = 0xFE - Successful read + token = 0x0X - Data error + token = 0xFF - timeout +*******************************************************************************/ +// uint8_t SD_readSingleBlock(uint32_t addr, uint8_t *buf, uint8_t *token) +// { +// uint8_t res1, read; +// uint16_t readAttempts; +// uint16_t i; + +// // set token to none +// *token = 0xFF; + +// // assert chip select +// spi_exchange(0xFF); +// spi_select(0); +// spi_exchange(0xFF); + +// // send CMD17 +// SD_command(CMD17, addr, CMD17_CRC); + +// // read R1 +// res1 = SD_readRes1(); + +// // if response received from card +// if(res1 != 0xFF) +// { +// // wait for a response token (timeout = 100ms) +// readAttempts = 0; +// while(++readAttempts != SD_MAX_READ_ATTEMPTS) +// if((read = spi_exchange(0xFF)) != 0xFF) break; + +// cprintf("read attempts: %d\r\n", readAttempts); + +// // if response token is 0xFE +// if(read == SD_START_TOKEN) +// { +// // read 512 byte block +// for(i = 0; i < SD_BLOCK_LEN; i++) *buf++ = spi_exchange(0xFF); + +// // read 16-bit CRC +// spi_exchange(0xFF); +// spi_exchange(0xFF); +// } + +// // set token to card response +// *token = read; +// } + +// // deassert chip select +// spi_exchange(0xFF); +// spi_deselect(0); +// spi_exchange(0xFF); + +// return res1; +// } + +#define SD_MAX_WRITE_ATTEMPTS 3907 + +/******************************************************************************* +Write single 512 byte block +token = 0x00 - busy timeout +token = 0x05 - data accepted +token = 0xFF - response timeout +*******************************************************************************/ +uint8_t SD_writeSingleBlock(uint32_t addr, uint8_t *buf, uint8_t *token) +{ + uint16_t readAttempts; + uint8_t res1, read; + uint16_t i; + + /* + + // set token to none + *token = 0xFF; + + // assert chip select + spi_exchange(0xFF); + spi_select(0); + spi_exchange(0xFF); + + // send CMD24 + SD_command(CMD24, addr, CMD24_CRC); + + // read response + res1 = SD_readRes1(); + + // if no error + if(res1 == SD_READY) + { + // send start token + spi_exchange(SD_START_TOKEN); + + // write buffer to card + for(i = 0; i < SD_BLOCK_LEN; i++) spi_exchange(buf[i]); + + // wait for a response (timeout = 250ms) + readAttempts = 0; + while(++readAttempts != SD_MAX_WRITE_ATTEMPTS) + if((read = spi_exchange(0xFF)) != 0xFF) { *token = 0xFF; break; } + + // if data accepted + if((read & 0x1F) == 0x05) + { + // set token to data accepted + *token = 0x05; + + // wait for write to finish (timeout = 250ms) + readAttempts = 0; + while(spi_exchange(0xFF) == 0x00) + if(++readAttempts == SD_MAX_WRITE_ATTEMPTS) { *token = 0x00; break; } + } + } + + // deassert chip select + spi_exchange(0xFF); + spi_deselect(0); + spi_exchange(0xFF); + + */ + + return res1; +} + +/******************************************************************************* + Reads OCR from SD Card +*******************************************************************************/ +void SD_readOCR(uint8_t *res) +{ + uint8_t tmp; + + // assert chip select + spi_exchange(0xFF); + spi_select(0); + tmp = spi_exchange(0xFF); + + if(tmp != 0xFF) while(spi_exchange(0xFF) != 0xFF) ; + + // send CMD58 + SD_command(CMD58, CMD58_ARG, CMD58_CRC); + + // read response + SD_readRes3(res); + + // deassert chip select + spi_exchange(0xFF); + spi_deselect(0); + spi_exchange(0xFF); +} + +/******************************************************************************* + Send application command (CMD55) +*******************************************************************************/ +uint8_t SD_sendApp() +{ + return res1_cmd(CMD55, CMD55_ARG, CMD55_CRC);; +} + +/******************************************************************************* + Send operating condition (ACMD41) +*******************************************************************************/ +uint8_t SD_sendOpCond() +{ + return res1_cmd(ACMD41, ACMD41_ARG, ACMD41_CRC); +} diff --git a/sw/kernel/devices/sd_card.h b/sw/kernel/devices/sd_card.h new file mode 100644 index 0000000..3e9304d --- /dev/null +++ b/sw/kernel/devices/sd_card.h @@ -0,0 +1,80 @@ +#ifndef _SD_CARD_H +#define _SD_CARD_H + +#include + +// command definitions +#define CMD0 0 +#define CMD0_ARG 0x00000000 +#define CMD0_CRC 0x94 +#define CMD8 8 +#define CMD8_ARG 0x0000001AA +#define CMD8_CRC 0x86 +#define CMD9 9 +#define CMD9_ARG 0x00000000 +#define CMD9_CRC 0x00 +#define CMD10 9 +#define CMD10_ARG 0x00000000 +#define CMD10_CRC 0x00 +#define CMD13 13 +#define CMD13_ARG 0x00000000 +#define CMD13_CRC 0x00 +#define CMD17 17 +#define CMD17_CRC 0x00 +#define CMD24 24 +#define CMD24_CRC 0x00 +#define CMD55 55 +#define CMD55_ARG 0x00000000 +#define CMD55_CRC 0x00 +#define CMD58 58 +#define CMD58_ARG 0x00000000 +#define CMD58_CRC 0x00 +#define ACMD41 41 +#define ACMD41_ARG 0x40000000 +#define ACMD41_CRC 0x00 + +#define SD_IN_IDLE_STATE 0x01 +#define SD_READY 0x00 +#define SD_R1_NO_ERROR(X) X < 0x02 + +#define R3_BYTES 4 +#define R7_BYTES 4 + +#define CMD0_MAX_ATTEMPTS 255 +#define CMD55_MAX_ATTEMPTS 255 +#define SD_ERROR 1 +#define SD_SUCCESS 0 +#define SD_MAX_READ_ATTEMPTS 1563 +#define SD_READ_START_TOKEN 0xFE +#define SD_INIT_CYCLES 80 + +#define SD_START_TOKEN 0xFE +#define SD_ERROR_TOKEN 0x00 + +#define SD_DATA_ACCEPTED 0x05 +#define SD_DATA_REJECTED_CRC 0x0B +#define SD_DATA_REJECTED_WRITE 0x0D + +#define SD_BLOCK_LEN 512 + +// SD functions +uint8_t SD_init(); +void SD_powerUpSeq(); +void SD_command(uint8_t cmd, uint32_t arg, uint8_t crc); +uint8_t SD_readRes1(); +void SD_readRes2(uint8_t *res); +void SD_readRes3(uint8_t *res); +void SD_readRes7(uint8_t *res); +void SD_readBytes(uint8_t *res, uint8_t n); +uint8_t SD_goIdleState(); +void SD_sendIfCond(uint8_t *res); +void SD_sendStatus(uint8_t *res); +void SD_readOCR(uint8_t *res); +uint8_t SD_sendApp(); +uint8_t SD_sendOpCond(); +uint8_t SD_readSingleBlock(uint32_t addr, uint8_t *buf, uint8_t *error); +uint8_t SD_writeSingleBlock(uint32_t addr, uint8_t *buf, uint8_t *res); + +uint8_t res1_cmd(uint8_t cmd, uint32_t arg, uint8_t crc); + +#endif \ No newline at end of file diff --git a/sw/kernel/devices/sd_card_asm.s b/sw/kernel/devices/sd_card_asm.s new file mode 100644 index 0000000..06e2142 --- /dev/null +++ b/sw/kernel/devices/sd_card_asm.s @@ -0,0 +1,303 @@ +.export _SD_command +.export _SD_readRes1 +.export _SD_readRes2 +.export _SD_readRes3 +.export _SD_readRes7 +.export _SD_readBytes +.export _SD_powerUpSeq +.export _res1_cmd +.export _SD_readSingleBlock + +.importzp sp, ptr1, ptr2, ptr3, ptr4, tmp1, tmp2, tmp3 + +.autoimport on + +.MACPACK generic + +; void SD_command(uint8_t cmd, uint32_t arg, uint8_t crc) + +; The plan: push crc to stack, load arg into tmp1 through 4 + +.proc _SD_command: near + + pha ; Push CRC to cpu stack + ldy #$04 + lda (sp),y ; Load CMD + ora #$40 ; start bit + jsr _spi_exchange + + dey +arg_loop: ; send ARG + lda (sp),y ; is this sending only 3? + jsr _spi_exchange + dey + bpl arg_loop + + pla ; Pull CRC from stack + ora #$01 ; stop bit + jsr _spi_exchange + jsr incsp5 ; pop all off stack + rts + +.endproc + +; uint8_t SD_readRes1 (void) + +.proc _SD_readRes1: near +; Try to read/write up to 8 times, then return value + + ldx #$08 + +tryread: + lda #$ff + jsr _spi_exchange + cmp #$ff + bne end + dex + bne tryread + +end: ; x will be 0 here anyway + rts + +.endproc + +; void SD_readRes2(uint8_t *res) + +.proc _SD_readRes2: near + + sta ptr1 ; store res in ptr1 + stx ptr1 + 1 + + jsr _SD_readRes1 ; get first response 1 + sta (ptr1) + + lda #$ff + jsr _spi_exchange ; get final byte of response + ldy #$01 + sta (ptr1),y + jsr incsp2 + rts + +.endproc + +; void SD_readBytes(uint8_t *res, uint8_t n) + +.proc _SD_readBytes: near + + tax + jsr popptr1 ; store res in ptr1 + +read: + lda #$ff ; read data first + jsr _spi_exchange + sta (ptr1) + inc ptr1 ; then increment res + bne @L1 + inc ptr1 + 1 +@L1: dex ; then decrement x + bne read ; and if x is zero we are done + rts + +.endproc + +; void SD_readRes7(uint8_t *res) + _SD_readRes7: +; void SD_readRes3(uint8_t *res) +.proc _SD_readRes3: near + + sta ptr1 ; store res in ptr1 + stx ptr1 + 1 + + jsr _SD_readRes1 ; read respopnse 1 in R3 + cmp #$02 ; if error reading R1, return + bge @L1 + + inc ptr1 ; read remaining bytes + bne @L2 + inc ptr1 +@L2: lda ptr1 ; push low byte + ldx ptr1 + 1 + jsr pushax + lda #$04 ; R3_BYTES + jsr _SD_readBytes + +@L1: rts + +.endproc + +; uint8_t res1_cmd(uint8_t cmd, uint32_t arg, uint8_t crc) + +.proc _res1_cmd: near + + pha ; push crc to processor stack + lda #$ff + jsr _spi_exchange + lda #$00 ; this gets ignored anyway + jsr _spi_select + lda #$ff + jsr _spi_exchange + + pla + jsr _SD_command ; rely on command to teardown stack + + jsr _SD_readRes1 + tay ; spi doesn't touch y + + lda #$ff + jsr _spi_exchange + lda #$00 ; this gets ignored anyway + jsr _spi_deselect + lda #$ff + jsr _spi_exchange + + tya + ldx #$00 ; Promote to integer + rts + +.endproc + +; void SD_powerUpSeq(void) + +.proc _SD_powerUpSeq: near + + lda #$00 + jsr _spi_deselect + jsr _sd_delay + lda #$ff + jsr _spi_exchange + lda #$00 + jsr _spi_deselect + + ldx #$50 ; SD_INIT_CYCLES +@L1: lda #$ff + jsr _spi_exchange + dex + bne @L1 + + rts + +.endproc + + +; 1ms delay approx. saves no registers +.proc _sd_delay: near + ldx #$01 ; delay loop: A*X*10 + 4 +@L1: lda #$c8 ; 1ms at 2MHz +@L2: dec ; 2 + bne @L2 ; 3 + dex ; 2 + bne @L1 ; 3 + rts +.endproc + +; ;uint8_t SD_readSingleBlock(uint32_t addr, uint8_t *buf, uint8_t *token) +.proc _SD_readSingleBlock: near + ; token address in a/x + ; buf address next on stack + ; sd address above that + + ; ptr2 = *token + sta ptr2 + stx ptr2 + 1 + + lda #$ff + sta (ptr2) + + ; ptr1 = *buf + jsr popptr1 + + ; 4 bytes on stack are addr + + ; Move addr down on the stack + lda sp + sta ptr3 + lda sp + 1 + sta ptr3 + 1 + + ; find a way to do this in a loop? + jsr decsp1 + ldy #$0 + lda (ptr3),y + sta (sp),y + iny + lda (ptr3),y + sta (sp),y + iny + lda (ptr3),y + sta (sp),y + iny + lda (ptr3),y + sta (sp),y + + lda #$ff + jsr _spi_exchange + lda #$00 ; this gets ignored anyway + jsr _spi_select + lda #$ff + jsr _spi_exchange + + ; push cmd17 + lda #$11 + ldy #$4 + sta (sp),y + + ; crc, 0 + lda #$00 + jsr _SD_command ; rely on command to teardown stack + + jsr _SD_readRes1 + + cmp #$ff ; if 0xFF then you failed + beq end + sta tmp3 ; tmp3 = read + + ; y = read_attempts + ldy #$0 +resp_loop: + lda #$ff + jsr _spi_exchange + sta tmp2 ; tmp2 = read + lda tmp2 + cmp #$ff + bne got_resp + iny + bne resp_loop + bra after_read + +got_resp: + ldx #$2 + ldy #$00 +load_loop: + lda #$ff + jsr _spi_exchange + sta (ptr1) + inc ptr1 + bne @2 + inc ptr1 + 1 +@2: dey + bne load_loop + ldy #$00 + dex + bne load_loop + lda #$ff + jsr _spi_exchange + lda #$ff + jsr _spi_exchange + +after_read: + lda tmp2 + sta (ptr2) + lda tmp3 + +end: + pha + lda #$ff + jsr _spi_exchange + lda #$00 ; this gets ignored anyway + jsr _spi_deselect + lda #$ff + jsr _spi_exchange + pla + rts + +.endproc \ No newline at end of file diff --git a/sw/kernel/devices/sd_print.c b/sw/kernel/devices/sd_print.c new file mode 100644 index 0000000..7e3d305 --- /dev/null +++ b/sw/kernel/devices/sd_print.c @@ -0,0 +1,26 @@ +#include + +#include "sd_print.h" +#include "sd_card.h" + + +void SD_printBuf(uint8_t *buf) +{ + uint8_t colCount = 0; + uint16_t i; + for(i = 0; i < SD_BLOCK_LEN; i++) + { + cprintf("%2x", *buf++); + if(colCount == 31) + { + cputs("\r\n"); + colCount = 0; + } + else + { + cputc(' '); + colCount++; + } + } + cputs("\r\n"); +} diff --git a/sw/kernel/devices/sd_print.h b/sw/kernel/devices/sd_print.h new file mode 100644 index 0000000..fd42418 --- /dev/null +++ b/sw/kernel/devices/sd_print.h @@ -0,0 +1,61 @@ +#ifndef SD_PRINT_H +#define SD_PRINT_H + + +#include + + +/* R1 MACROS */ +#define PARAM_ERROR(X) X & 0b01000000 +#define ADDR_ERROR(X) X & 0b00100000 +#define ERASE_SEQ_ERROR(X) X & 0b00010000 +#define CRC_ERROR(X) X & 0b00001000 +#define ILLEGAL_CMD(X) X & 0b00000100 +#define ERASE_RESET(X) X & 0b00000010 +#define IN_IDLE(X) X & 0b00000001 + +/* R2 MACROS */ +#define OUT_OF_RANGE(X) X & 0b10000000 +#define ERASE_PARAM(X) X & 0b01000000 +#define WP_VIOLATION(X) X & 0b00100000 +#define CARD_ECC_FAILED(X) X & 0b00010000 +#define CC_ERROR(X) X & 0b00001000 +#define ERROR(X) X & 0b00000100 +#define WP_ERASE_SKIP(X) X & 0b00000010 +#define CARD_LOCKED(X) X & 0b00000001 + +/* R3 MACROS */ +#define POWER_UP_STATUS(X) X & 0x40 +#define CCS_VAL(X) X & 0x40 +#define VDD_2728(X) X & 0b10000000 +#define VDD_2829(X) X & 0b00000001 +#define VDD_2930(X) X & 0b00000010 +#define VDD_3031(X) X & 0b00000100 +#define VDD_3132(X) X & 0b00001000 +#define VDD_3233(X) X & 0b00010000 +#define VDD_3334(X) X & 0b00100000 +#define VDD_3435(X) X & 0b01000000 +#define VDD_3536(X) X & 0b10000000 + +/* R7 MACROS */ +#define CMD_VER(X) ((X >> 4) & 0xF0) +#define VOL_ACC(X) (X & 0x1F) +#define VOLTAGE_ACC_27_33 0b00000001 +#define VOLTAGE_ACC_LOW 0b00000010 +#define VOLTAGE_ACC_RES1 0b00000100 +#define VOLTAGE_ACC_RES2 0b00001000 + +/* DATA ERROR TOKEN */ +#define SD_TOKEN_OOR(X) X & 0b00001000 +#define SD_TOKEN_CECC(X) X & 0b00000100 +#define SD_TOKEN_CC(X) X & 0b00000010 +#define SD_TOKEN_ERROR(X) X & 0b00000001 + +void SD_printR1(uint8_t res); +void SD_printR2(uint8_t *res); +void SD_printR3(uint8_t *res); +void SD_printR7(uint8_t *res); +void SD_printBuf(uint8_t *buf); +void SD_printDataErrToken(uint8_t token); + +#endif \ No newline at end of file diff --git a/sw/kernel/devices/spi.h b/sw/kernel/devices/spi.h new file mode 100644 index 0000000..61816d0 --- /dev/null +++ b/sw/kernel/devices/spi.h @@ -0,0 +1,12 @@ +#ifndef _SPI_H +#define _SPI_H + +#include + +void spi_select(uint8_t id); +void spi_deselect(uint8_t id); +uint8_t spi_read(); +void spi_write(uint8_t data); +uint8_t spi_exchange(uint8_t data); + +#endif \ No newline at end of file diff --git a/sw/kernel/devices/spi.s b/sw/kernel/devices/spi.s new file mode 100644 index 0000000..5595a9a --- /dev/null +++ b/sw/kernel/devices/spi.s @@ -0,0 +1,39 @@ +.include "io.inc65" + +.importzp zp, sreg + +.export _spi_select, _spi_deselect +.export _spi_read, _spi_write, _spi_exchange + +.autoimport on + +.code + +; void spi_select(uint8_t id) +; Select a (the) slave by pulling its CS line down +; TODO allow active high or active low CS +; TODO allow more than one slave +_spi_select: + lda #$1 ; Ignore whatever id is, 1 is the only option + sta SPI_CTRL + rts + +; void spi_deslect(uint8_t id) +; Deslect a slave by pulling its CS line up +; TODO allow active high or active low CS +_spi_deselect: + stz SPI_CTRL + rts + +; uint8_t spi_read() +_spi_read: + lda #$0 +; void spi_write(uint8_t data) +_spi_write: +; uint8_t spi_exchange(uint8_t data) +_spi_exchange: + sta SPI_OUTPUT +@1: lda SPI_CTRL + bmi @1 + lda SPI_INPUT + rts diff --git a/sw/kernel/irq.c b/sw/kernel/irq.c new file mode 100644 index 0000000..9911f8d --- /dev/null +++ b/sw/kernel/irq.c @@ -0,0 +1,11 @@ + +#include +#include + +#include "devices/interrupt.h" +#include "devices/uart.h" + + + +void handle_irq() { +} \ No newline at end of file