diff options
author | Uros Majstorovic <majstor@majstor.org> | 2018-03-14 19:08:00 +0100 |
---|---|---|
committer | Uros Majstorovic <majstor@majstor.org> | 2018-03-14 19:08:00 +0100 |
commit | 5fe913c88d8c1781de336cca3949142bd9fc370d (patch) | |
tree | 6bf57e4e34fb60e46035175946b15581b2ef638c /code/fe310/eos | |
parent | 4b655364d426f8429b063d9746c754beca6f7d1f (diff) |
i2s driver added; new amd trap entry vector added
Diffstat (limited to 'code/fe310/eos')
-rw-r--r-- | code/fe310/eos/Makefile | 5 | ||||
-rw-r--r-- | code/fe310/eos/event.h | 12 | ||||
-rw-r--r-- | code/fe310/eos/evt_def.h | 11 | ||||
-rw-r--r-- | code/fe310/eos/i2s.c | 211 | ||||
-rw-r--r-- | code/fe310/eos/i2s.h | 20 | ||||
-rw-r--r-- | code/fe310/eos/i2s_def.h | 28 | ||||
-rw-r--r-- | code/fe310/eos/interrupt.c | 1 | ||||
-rw-r--r-- | code/fe310/eos/msgq_def.h | 6 | ||||
-rw-r--r-- | code/fe310/eos/net.c | 1 | ||||
-rw-r--r-- | code/fe310/eos/timer.c | 1 | ||||
-rw-r--r-- | code/fe310/eos/trap_entry.S | 398 |
11 files changed, 681 insertions, 13 deletions
diff --git a/code/fe310/eos/Makefile b/code/fe310/eos/Makefile index 43313fd..e84d0f6 100644 --- a/code/fe310/eos/Makefile +++ b/code/fe310/eos/Makefile @@ -5,12 +5,15 @@ AR = $(FE310_HOME)/work/build/riscv-gnu-toolchain/riscv64-unknown-elf/prefix/bin CFLAGS = -O3 -fno-builtin-printf -march=rv32imac -mabi=ilp32 -mcmodel=medany -I$(FE310_HOME)/bsp/include -I$(FE310_HOME)/bsp/drivers -I$(FE310_HOME)/bsp/env -I$(FE310_HOME)/bsp/env/freedom-e300-hifive1 -I../.. -obj = eos.o msgq.o event.o interrupt.o timer.o net.o ecp.o +obj = trap_entry.o eos.o msgq.o event.o interrupt.o timer.o i2s.o net.o ecp.o %.o: %.c %.h $(CC) $(CFLAGS) -c $< +%.o: %.S + $(CC) $(CFLAGS) -c $< + all: $(obj) $(AR) rcs libeos.a $(obj) diff --git a/code/fe310/eos/event.h b/code/fe310/eos/event.h index ce71c0b..2dee419 100644 --- a/code/fe310/eos/event.h +++ b/code/fe310/eos/event.h @@ -1,16 +1,6 @@ #include <stdint.h> -#define EOS_EVT_FLAG_WRAP 0x1 - -#define EOS_EVT_NET 0x10 -#define EOS_EVT_TIMER 0x20 -#define EOS_EVT_AUDIO 0x30 -#define EOS_EVT_UI 0x40 - -#define EOS_EVT_MASK 0xF0 - -#define EOS_EVT_MAX_EVT 4 -#define EOS_EVT_SIZE_Q 4 +#include "evt_def.h" typedef void (*eos_evt_fptr_t) (unsigned char, unsigned char *, uint16_t); diff --git a/code/fe310/eos/evt_def.h b/code/fe310/eos/evt_def.h new file mode 100644 index 0000000..e07b23c --- /dev/null +++ b/code/fe310/eos/evt_def.h @@ -0,0 +1,11 @@ +#define EOS_EVT_FLAG_WRAP 0x1 + +#define EOS_EVT_NET 0x10 +#define EOS_EVT_TIMER 0x20 +#define EOS_EVT_AUDIO 0x30 +#define EOS_EVT_UI 0x40 + +#define EOS_EVT_MASK 0xF0 + +#define EOS_EVT_MAX_EVT 4 +#define EOS_EVT_SIZE_Q 4 diff --git a/code/fe310/eos/i2s.c b/code/fe310/eos/i2s.c new file mode 100644 index 0000000..98e2ffa --- /dev/null +++ b/code/fe310/eos/i2s.c @@ -0,0 +1,211 @@ +#include <unistd.h> + +#include "encoding.h" +#include "platform.h" + +#include "eos.h" +#include "interrupt.h" +#include "event.h" + +#include "i2s.h" +#include "i2s_def.h" + +#define I2S_PWM_REG_CK PWM1_REG +#define I2S_PWM_REG_WS PWM2_REG + +#define EOS_ABUF_IDX_MASK(IDX, SIZE) ((IDX) & ((SIZE) - 1)) + +EOSABuf _eos_i2s_mic_buf; +EOSABuf _eos_i2s_spk_buf; +uint16_t _eos_i2s_mic_wm; +uint16_t _eos_i2s_spk_wm; +uint32_t _eos_i2s_ck_period; +uint32_t _eos_i2s_mic_volume = 3; +static eos_evt_fptr_t evt_handler[I2S_MAX_HANDLER]; + +static void _abuf_init(EOSABuf *buf, uint8_t *array, uint16_t size) { + buf->idx_r = 0; + buf->idx_w = 0; + buf->size = size; + buf->array = array; +} + +static int _abuf_push(EOSABuf *buf, uint8_t sample) { + if (buf->idx_w - buf->idx_r == buf->size) return EOS_ERR_Q_FULL; + + buf->array[EOS_ABUF_IDX_MASK(buf->idx_w, buf->size)] = sample; + buf->idx_w++; + return EOS_OK; +} + +static int _abuf_pop(EOSABuf *buf, uint8_t *sample) { + if (buf->idx_r == buf->idx_w) { + return EOS_ERR_Q_EMPTY; + } else { + *sample = buf->array[EOS_ABUF_IDX_MASK(buf->idx_r, buf->size)]; + buf->idx_r++; + return EOS_OK; + } +} + +static uint16_t _abuf_read(EOSABuf *buf, uint8_t *sample, uint16_t ssize) { + uint16_t i; + + for (i=0; i<ssize; i++) { + if (buf->idx_r == buf->idx_w) break; + sample[i] = buf->array[EOS_ABUF_IDX_MASK(buf->idx_r, buf->size)]; + buf->idx_r++; + } + return i; +} + +static uint16_t _abuf_write(EOSABuf *buf, uint8_t *sample, uint16_t ssize) { + uint16_t i; + + for (i=0; i<ssize; i++) { + if (buf->idx_w - buf->idx_r == buf->size) break; + buf->array[EOS_ABUF_IDX_MASK(buf->idx_w, buf->size)] = sample[i]; + buf->idx_w++; + } + return i; +} + +static uint16_t _abuf_len(EOSABuf *buf) { + return buf->idx_w - buf->idx_r; +} + +static void audio_handler(unsigned char cmd, unsigned char *buffer, uint16_t len) { + if ((cmd & ~EOS_EVT_MASK) < I2S_MAX_HANDLER) { + evt_handler[cmd & ~EOS_EVT_MASK](cmd, buffer, len); + } else { + eos_evtq_bad_handler(cmd, buffer, len); + } +} + +void eos_i2s_init(void) { + int i; + unsigned long f = get_cpu_freq(); + + _eos_i2s_ck_period = 512; + GPIO_REG(GPIO_INPUT_EN) &= ~(1 << I2S_PIN_LR); + GPIO_REG(GPIO_OUTPUT_EN) |= (1 << I2S_PIN_LR); + GPIO_REG(GPIO_OUTPUT_XOR) &= ~(1 << I2S_PIN_LR); + + GPIO_REG(GPIO_INPUT_EN) &= ~(1 << I2S_PIN_CK); + GPIO_REG(GPIO_OUTPUT_EN) |= (1 << I2S_PIN_CK); + GPIO_REG(GPIO_OUTPUT_XOR) &= ~(1 << I2S_PIN_CK); + + GPIO_REG(GPIO_INPUT_EN) &= ~(1 << I2S_PIN_WS); + GPIO_REG(GPIO_OUTPUT_EN) |= (1 << I2S_PIN_WS); + GPIO_REG(GPIO_OUTPUT_XOR) &= ~(1 << I2S_PIN_WS); + + GPIO_REG(GPIO_INPUT_EN) |= (1 << I2S_PIN_SD); + GPIO_REG(GPIO_OUTPUT_EN) &= ~(1 << I2S_PIN_SD); + GPIO_REG(GPIO_PULLUP_EN) &= ~(1 << I2S_PIN_SD); + + GPIO_REG(GPIO_OUTPUT_VAL) &= ~(1 << I2S_PIN_LR); + + I2S_PWM_REG_CK(PWM_CFG) = 0; + I2S_PWM_REG_CK(PWM_COUNT) = 0; + I2S_PWM_REG_CK(PWM_CMP0) = _eos_i2s_ck_period - 1; + I2S_PWM_REG_CK(PWM_CMP1) = I2S_PWM_REG_CK(PWM_CMP0) / 2; + I2S_PWM_REG_CK(PWM_CMP2) = I2S_PWM_REG_CK(PWM_CMP0) / 4; + + I2S_PWM_REG_WS(PWM_CFG) = 0; + I2S_PWM_REG_WS(PWM_COUNT) = 0; + I2S_PWM_REG_WS(PWM_CMP0) = _eos_i2s_ck_period * 64 - 1; + I2S_PWM_REG_WS(PWM_CMP1) = I2S_PWM_REG_WS(PWM_CMP0) / 2; + I2S_PWM_REG_WS(PWM_CMP2) = I2S_PWM_REG_WS(PWM_CMP0) - 1024; + + eos_intr_set(I2S_IRQ_SD_ID, I2S_IRQ_SD_PRIORITY, NULL); + eos_intr_set(I2S_IRQ_CK_ID, I2S_IRQ_CK_PRIORITY, NULL); + eos_intr_set(I2S_IRQ_WS_ID, I2S_IRQ_WS_PRIORITY, NULL); + eos_intr_set(I2S_IRQ_CI_ID, I2S_IRQ_CI_PRIORITY, NULL); + + for (i=0; i<I2S_MAX_HANDLER; i++) { + evt_handler[i] = eos_evtq_bad_handler; + } + eos_evtq_set_handler(EOS_EVT_AUDIO, audio_handler, EOS_EVT_FLAG_WRAP); +} + +void eos_i2s_init_mic(uint8_t *mic_arr, uint16_t mic_arr_size, uint16_t mic_wm, eos_evt_fptr_t mic_wm_handler) { + _abuf_init(&_eos_i2s_mic_buf, mic_arr, mic_arr_size); + _eos_i2s_mic_wm = mic_wm; + evt_handler[I2S_EVT_MIC] = mic_wm_handler; +} + +void eos_i2s_init_spk(uint8_t *spk_arr, uint16_t spk_arr_size, uint16_t spk_wm, eos_evt_fptr_t spk_wm_handler) { + _abuf_init(&_eos_i2s_spk_buf, spk_arr, spk_arr_size); + _eos_i2s_spk_wm = spk_wm; + evt_handler[I2S_EVT_SPK] = spk_wm_handler; +} + +void eos_i2s_start(void) { + I2S_PWM_REG_CK(PWM_COUNT) = 0; + I2S_PWM_REG_WS(PWM_COUNT) = 0; + + I2S_PWM_REG_CK(PWM_CFG) = PWM_CFG_ENALWAYS | PWM_CFG_ZEROCMP; + I2S_PWM_REG_WS(PWM_CFG) = PWM_CFG_ENALWAYS | PWM_CFG_ZEROCMP; + + GPIO_REG(GPIO_IOF_SEL) |= (1 << I2S_PIN_CK); + GPIO_REG(GPIO_IOF_EN) |= (1 << I2S_PIN_CK); + + GPIO_REG(GPIO_IOF_SEL) |= (1 << I2S_PIN_WS); + GPIO_REG(GPIO_IOF_EN) |= (1 << I2S_PIN_WS); +} + +void eos_i2s_stop(void) { + I2S_PWM_REG_CK(PWM_CFG) = 0; + I2S_PWM_REG_WS(PWM_CFG) = 0; + I2S_PWM_REG_CK(PWM_COUNT) = 0; + I2S_PWM_REG_WS(PWM_COUNT) = 0; + + GPIO_REG(GPIO_IOF_EN) &= ~(1 << I2S_PIN_CK); + GPIO_REG(GPIO_IOF_SEL) &= ~(1 << I2S_PIN_CK); + + GPIO_REG(GPIO_IOF_EN) &= ~(1 << I2S_PIN_WS); + GPIO_REG(GPIO_IOF_SEL) &= ~(1 << I2S_PIN_WS); + + GPIO_REG(GPIO_OUTPUT_VAL) &= ~((1 << I2S_PIN_CK) | (1 << I2S_PIN_WS)); +} + +uint16_t eos_i2s_mic_len(void) { + uint16_t ret = _abuf_len(&_eos_i2s_mic_buf); + set_csr(mstatus, MSTATUS_MIE); + return ret; +} + +uint16_t eos_i2s_mic_read(uint8_t *sample, uint16_t ssize) { + clear_csr(mstatus, MSTATUS_MIE); + uint16_t ret = _abuf_read(&_eos_i2s_mic_buf, sample, ssize); + set_csr(mstatus, MSTATUS_MIE); + return ret; +} + +int eos_i2s_mic_pop(uint8_t *sample) { + clear_csr(mstatus, MSTATUS_MIE); + int ret = _abuf_pop(&_eos_i2s_mic_buf, sample); + set_csr(mstatus, MSTATUS_MIE); + return ret; +} + +uint16_t eos_i2s_spk_len(void) { + clear_csr(mstatus, MSTATUS_MIE); + uint16_t ret = _abuf_len(&_eos_i2s_spk_buf); + set_csr(mstatus, MSTATUS_MIE); + return ret; +} + +uint16_t eos_i2s_spk_write(uint8_t *sample, uint16_t ssize) { + clear_csr(mstatus, MSTATUS_MIE); + uint16_t ret = _abuf_write(&_eos_i2s_spk_buf, sample, ssize); + set_csr(mstatus, MSTATUS_MIE); + return ret; +} + +int eos_i2s_spk_push(uint8_t sample) { + clear_csr(mstatus, MSTATUS_MIE); + int ret = _abuf_push(&_eos_i2s_spk_buf, sample); + set_csr(mstatus, MSTATUS_MIE); + return ret; +} diff --git a/code/fe310/eos/i2s.h b/code/fe310/eos/i2s.h new file mode 100644 index 0000000..29e7a28 --- /dev/null +++ b/code/fe310/eos/i2s.h @@ -0,0 +1,20 @@ +#include <stdint.h> + +typedef struct EOSABuf { + uint16_t idx_r; + uint16_t idx_w; + uint16_t size; + uint8_t *array; +} EOSABuf; + +void eos_i2s_init(void); +void eos_i2s_init_mic(uint8_t *mic_arr, uint16_t mic_arr_size, uint16_t mic_wm, eos_evt_fptr_t mic_wm_handler); +void eos_i2s_init_spk(uint8_t *spk_arr, uint16_t spk_arr_size, uint16_t spk_wm, eos_evt_fptr_t spk_wm_handler); +void eos_i2s_start(void); +void eos_i2s_stop(void); +uint16_t eos_i2s_mic_len(void); +uint16_t eos_i2s_mic_read(uint8_t *sample, uint16_t ssize); +int eos_i2s_mic_pop(uint8_t *sample); +uint16_t eos_i2s_spk_len(void); +uint16_t eos_i2s_spk_write(uint8_t *sample, uint16_t ssize); +int eos_i2s_spk_push(uint8_t sample); diff --git a/code/fe310/eos/i2s_def.h b/code/fe310/eos/i2s_def.h new file mode 100644 index 0000000..04e9c27 --- /dev/null +++ b/code/fe310/eos/i2s_def.h @@ -0,0 +1,28 @@ +#define I2S_EVT_MIC 0x0 +#define I2S_EVT_SPK 0x1 +#define I2S_MAX_HANDLER 2 + +#define I2S_PIN_CK 19 // pin 3 +#define I2S_PIN_WS 11 // pin 17 +#define I2S_PIN_SD 12 // pin 18 + +#define I2S_PIN_LR 13 // pin 19 + +#define I2S_IRQ_SD_ID (INT_PWM1_BASE + 2) +#define I2S_IRQ_CK_ID (INT_PWM1_BASE + 0) +#define I2S_IRQ_WS_ID (INT_PWM2_BASE + 0) +#define I2S_IRQ_CI_ID (INT_PWM2_BASE + 2) + +#define I2S_IRQ_SD_PRIORITY 7 +#define I2S_IRQ_CK_PRIORITY 7 +#define I2S_IRQ_WS_PRIORITY 6 +#define I2S_IRQ_CI_PRIORITY 6 +#define I2S_IRQ_MASK 5 + +#define I2S_SMPL_WIDTH 13 + +/* asm */ +#define I2S_ABUF_OFF_IDXR 0 +#define I2S_ABUF_OFF_IDXW 2 +#define I2S_ABUF_OFF_SIZE 4 +#define I2S_ABUF_OFF_ARRAY 8 diff --git a/code/fe310/eos/interrupt.c b/code/fe310/eos/interrupt.c index 77ab6d5..b8c6540 100644 --- a/code/fe310/eos/interrupt.c +++ b/code/fe310/eos/interrupt.c @@ -5,6 +5,7 @@ #include "encoding.h" #include "platform.h" #include "plic/plic_driver.h" + #include "interrupt.h" // Global Instance data for the PLIC diff --git a/code/fe310/eos/msgq_def.h b/code/fe310/eos/msgq_def.h new file mode 100644 index 0000000..683de9b --- /dev/null +++ b/code/fe310/eos/msgq_def.h @@ -0,0 +1,6 @@ +/* asm */ +#define MSGQ_OFF_IDXR 0 +#define MSGQ_OFF_IDXW 1 +#define MSGQ_OFF_SIZE 2 +#define MSGQ_OFF_ARRAY 4 +#define MSGQ_ITEM_SIZE 12 diff --git a/code/fe310/eos/net.c b/code/fe310/eos/net.c index 4588485..3339223 100644 --- a/code/fe310/eos/net.c +++ b/code/fe310/eos/net.c @@ -6,7 +6,6 @@ #include "encoding.h" #include "platform.h" -#include "plic/plic_driver.h" #include "eos.h" #include "msgq.h" diff --git a/code/fe310/eos/timer.c b/code/fe310/eos/timer.c index 9e2ae9d..915be6f 100644 --- a/code/fe310/eos/timer.c +++ b/code/fe310/eos/timer.c @@ -3,6 +3,7 @@ #include "encoding.h" #include "platform.h" + #include "event.h" #include "timer.h" diff --git a/code/fe310/eos/trap_entry.S b/code/fe310/eos/trap_entry.S new file mode 100644 index 0000000..1c164d3 --- /dev/null +++ b/code/fe310/eos/trap_entry.S @@ -0,0 +1,398 @@ +#include "encoding.h" +#include "sifive/bits.h" + +#define MCAUSE_INT 0x80000000 +#define MCAUSE_EXT (MCAUSE_INT | IRQ_M_EXT) +#define MCAUSE_TIMER (MCAUSE_INT | IRQ_M_TIMER) + +#define PLIC_PRIORITY 0x0C000000 +#define PLIC_THRESHOLD 0x0C200000 +#define PLIC_CLAIM 0x0C200004 + +#define PWM0_CTRL_ADDR 0x10015000 +#define PWM1_CTRL_ADDR 0x10025000 +#define PWM2_CTRL_ADDR 0x10035000 + +#define PWM_CFG 0x00 +#define PWM_COUNT 0x08 + +#define PWM_CFG_CMP0IP 0x10000000 +#define PWM_CFG_CMP1IP 0x20000000 +#define PWM_CFG_CMP2IP 0x40000000 +#define PWM_CFG_CMP3IP 0x80000000 + +#define GPIO_CTRL_ADDR 0x10012000 +#define GPIO_INPUT_VAL 0x00 + +#define INT_PWM0_BASE 40 +#define INT_PWM1_BASE 44 +#define INT_PWM2_BASE 48 + +#define I2S_PWM_CTRL_ADDR_CK PWM1_CTRL_ADDR +#define I2S_PWM_CTRL_ADDR_WS PWM2_CTRL_ADDR + +#include "i2s_def.h" +#include "evt_def.h" +#include "msgq_def.h" + + .section .data.entry + .align 2 + +.global eos_trap_entry +eos_trap_entry: + addi sp, sp, -4*REGBYTES + + STORE x8, 0*REGBYTES(sp) + STORE x9, 1*REGBYTES(sp) + STORE x18, 2*REGBYTES(sp) + STORE x19, 3*REGBYTES(sp) + + csrr x8, mcause + li x18, MCAUSE_EXT + bne x8, x18, handler + li x18, PLIC_CLAIM + lw x9, 0(x18) + li x18, I2S_IRQ_SD_ID + beq x9, x18, handler_sd + li x18, I2S_IRQ_CK_ID + beq x9, x18, handler_ck + li x18, I2S_IRQ_WS_ID + beq x9, x18, handler_ws + li x18, I2S_IRQ_CI_ID + beq x9, x18, handler_ci + j handler + +handler_sd: + # read mic value -> x8 + li x18, GPIO_CTRL_ADDR + lw x8, GPIO_INPUT_VAL(x18) + + # set bit as ws pwm counter/ck period - sd volume -> x9 + li x18, I2S_PWM_CTRL_ADDR_WS + lw x9, PWM_COUNT(x18) + la x18, _eos_i2s_ck_period + lw x19, 0(x18) + divu x9, x9, x19 + la x18, _eos_i2s_mic_volume + lw x19, 0(x18) + sub x9, x9, x19 + + # disable sd irq + li x18, PLIC_PRIORITY + sw x0, 4*I2S_IRQ_SD_ID(x18) + + addi sp, sp, -1*REGBYTES + STORE x20, 0*REGBYTES(sp) + + # bit <= 0 -> exit + bge x0, x9, handler_sd_exit + + # sample |= sd gpio value << (32 - bit) -> x8 + # sample_mask |= 1 << (32 - bit) -> x20 + li x18, (0x1 << I2S_PIN_SD) + and x8, x8, x18 + srli x8, x8, I2S_PIN_SD + li x18, 32 + sub x19, x18, x9 + sll x8, x8, x19 + li x20, 1 + sll x20, x20, x19 + la x18, sd_sample_mask + lw x19, 0(x18) + or x19, x19, x20 + sw x19, 0(x18) + mv x20, x19 + la x18, sd_sample + lw x19, 0(x18) + or x19, x19, x8 + sw x19, 0(x18) + mv x8, x19 + + # bit < I2S_SMPL_WIDTH -> exit + li x18, I2S_SMPL_WIDTH + blt x9, x18, handler_sd_exit + + # disable ck irq + li x18, PLIC_PRIORITY + sw x0, 4*I2S_IRQ_CK_ID(x18) + + # reset irq mask + li x18, PLIC_THRESHOLD + sw x0, 0(x18) + + # reset sample / sample_mask + la x18, sd_sample + sw x0, 0(x18) + la x18, sd_sample_mask + sw x0, 0(x18) + + # correct for missed bits + la x18, sd_sample_save + li x19, 0x80000000 + srai x19, x19, I2S_SMPL_WIDTH-1 + and x20, x20, x19 + beq x19, x20, 0f + lw x8, 0(x18) +0: + sw x8, 0(x18) + srai x8, x8, 32-I2S_SMPL_WIDTH + + # aLaw encode -> x8 + li x18, 0x800 + li x19, 7 + bgez x8, 1f + neg x8, x8 + lui x9, 0x80000 + or x8, x8, x9 +1: + and x9, x8, x18 + beq x9, x18, 2f + beqz x19, 2f + srli x18, x18, 1 + addi x19, x19, -1 + j 1b +2: + mv x9, x19 + bnez x9, 3f + addi x9, x9, 1 +3: + sra x8, x8, x9 + li x9, 0x8000000f + and x8, x8, x9 + slli x19, x19, 4 + or x8, x8, x19 + bgez x8, 4f + ori x8, x8, 0x80 + +4: + xori x8, x8, 0x55 + andi x8, x8, 0xff + + # push to mic but + la x9, _eos_i2s_mic_buf + lhu x18, I2S_ABUF_OFF_IDXR(x9) + lhu x19, I2S_ABUF_OFF_IDXW(x9) + lhu x20, I2S_ABUF_OFF_SIZE(x9) + + sub x18, x19, x18 + beq x18, x20, handler_sd_exit + + addi x20, x20, -1 + and x20, x20, x19 + lw x18, I2S_ABUF_OFF_ARRAY(x9) + add x20, x20, x18 + sb x8, 0(x20) + + addi x19, x19, 1 + sh x19, I2S_ABUF_OFF_IDXW(x9) + + # push to event queue + la x9, _eos_i2s_mic_wm + lhu x20, 0(x9) + beqz x20, handler_sd_exit + + la x9, _eos_i2s_mic_buf + lhu x18, I2S_ABUF_OFF_IDXR(x9) + sub x18, x19, x18 + bne x18, x20, handler_sd_exit + + la x9, _eos_event_q + lbu x18, MSGQ_OFF_IDXR(x9) + lbu x19, MSGQ_OFF_IDXW(x9) + lbu x20, MSGQ_OFF_SIZE(x9) + + sub x18, x19, x18 + beq x18, x20, handler_sd_exit + + addi x20, x20, -1 + and x20, x20, x19 + li x18, MSGQ_ITEM_SIZE + mul x20, x20, x18 + lw x18, MSGQ_OFF_ARRAY(x9) + add x20, x20, x18 + li x18, (EOS_EVT_AUDIO | I2S_EVT_MIC) + sb x18, 0(x20) + + addi x19, x19, 1 + sb x19, MSGQ_OFF_IDXW(x9) + j handler_sd_exit + +handler_sd_exit: + LOAD x20, 0*REGBYTES(sp) + addi sp, sp, 1*REGBYTES + + # complete + li x18, I2S_IRQ_SD_ID + li x19, PLIC_CLAIM + sw x18, 0(x19) + + # exit + j trap_exit_data + +handler_ck: + # enable sd irq + li x18, PLIC_PRIORITY + li x19, I2S_IRQ_SD_PRIORITY + sw x19, 4*I2S_IRQ_SD_ID(x18) + + # complete + li x18, I2S_IRQ_CK_ID + li x19, PLIC_CLAIM + sw x18, 0(x19) + + # exit + j trap_exit_data + +handler_ws: + # enable wsc irq + li x18, PLIC_PRIORITY + li x19, I2S_IRQ_CI_PRIORITY + sw x19, 4*I2S_IRQ_CI_ID(x18) + + # complete + li x18, I2S_IRQ_WS_ID + li x19, PLIC_CLAIM + sw x18, 0(x19) + + # exit + j trap_exit_data + +handler_ci: + # disable wsc/enable ck irq + li x18, PLIC_PRIORITY + sw x0, 4*I2S_IRQ_CI_ID(x18) + li x19, I2S_IRQ_CK_PRIORITY + sw x19, 4*I2S_IRQ_CK_ID(x18) + + # set irq mask + li x18, PLIC_THRESHOLD + li x19, I2S_IRQ_MASK + sw x19, 0(x18) + + # complete + li x18, I2S_IRQ_CI_ID + li x19, PLIC_CLAIM + sw x18, 0(x19) + + # exit + j trap_exit_data + +trap_exit_data: + # Remain in M-mode after mret + li x18, MSTATUS_MPP + csrs mstatus, x18 + + LOAD x8, 0*REGBYTES(sp) + LOAD x9, 1*REGBYTES(sp) + LOAD x18, 2*REGBYTES(sp) + LOAD x19, 3*REGBYTES(sp) + + addi sp, sp, 4*REGBYTES + mret + +handler: + lui x18, %hi(trap_entry_text) + addi x18, x18, %lo(trap_entry_text) + jalr x0, x18 + + .align 4 + +sd_sample: + .word 0 +sd_sample_save: + .word 0 +sd_sample_mask: + .word 0 + + .section .text.entry + .align 2 + +trap_entry_text: + addi sp, sp, -28*REGBYTES + + STORE x1, 0*REGBYTES(sp) + STORE x2, 1*REGBYTES(sp) + STORE x3, 2*REGBYTES(sp) + STORE x4, 3*REGBYTES(sp) + STORE x5, 4*REGBYTES(sp) + STORE x6, 5*REGBYTES(sp) + STORE x7, 6*REGBYTES(sp) + STORE x10, 7*REGBYTES(sp) + STORE x11, 8*REGBYTES(sp) + STORE x12, 9*REGBYTES(sp) + STORE x13, 10*REGBYTES(sp) + STORE x14, 11*REGBYTES(sp) + STORE x15, 12*REGBYTES(sp) + STORE x16, 13*REGBYTES(sp) + STORE x17, 14*REGBYTES(sp) + STORE x20, 15*REGBYTES(sp) + STORE x21, 16*REGBYTES(sp) + STORE x22, 17*REGBYTES(sp) + STORE x23, 18*REGBYTES(sp) + STORE x24, 19*REGBYTES(sp) + STORE x25, 20*REGBYTES(sp) + STORE x26, 21*REGBYTES(sp) + STORE x27, 22*REGBYTES(sp) + STORE x28, 23*REGBYTES(sp) + STORE x29, 24*REGBYTES(sp) + STORE x30, 25*REGBYTES(sp) + STORE x31, 26*REGBYTES(sp) + + li x18, MCAUSE_TIMER + beq x8, x18, handle_timer + li x18, MCAUSE_EXT + beq x8, x18, handle_ext + mv a0, x8 + call _exit + +handle_timer: + call eos_timer_handle + j trap_exit_text + +handle_ext: + mv a0, x9 + call eos_intr_handle + li x18, PLIC_CLAIM + sw a0, 0(x18) + j trap_exit_text + +trap_exit_text: + # Remain in M-mode after mret + li t0, MSTATUS_MPP + csrs mstatus, t0 + + LOAD x1, 0*REGBYTES(sp) + LOAD x2, 1*REGBYTES(sp) + LOAD x3, 2*REGBYTES(sp) + LOAD x4, 3*REGBYTES(sp) + LOAD x5, 4*REGBYTES(sp) + LOAD x6, 5*REGBYTES(sp) + LOAD x7, 6*REGBYTES(sp) + LOAD x10, 7*REGBYTES(sp) + LOAD x11, 8*REGBYTES(sp) + LOAD x12, 9*REGBYTES(sp) + LOAD x13, 10*REGBYTES(sp) + LOAD x14, 11*REGBYTES(sp) + LOAD x15, 12*REGBYTES(sp) + LOAD x16, 13*REGBYTES(sp) + LOAD x17, 14*REGBYTES(sp) + LOAD x20, 15*REGBYTES(sp) + LOAD x21, 16*REGBYTES(sp) + LOAD x22, 17*REGBYTES(sp) + LOAD x23, 18*REGBYTES(sp) + LOAD x24, 19*REGBYTES(sp) + LOAD x25, 20*REGBYTES(sp) + LOAD x26, 21*REGBYTES(sp) + LOAD x27, 22*REGBYTES(sp) + LOAD x28, 23*REGBYTES(sp) + LOAD x29, 24*REGBYTES(sp) + LOAD x30, 25*REGBYTES(sp) + LOAD x31, 26*REGBYTES(sp) + + LOAD x8, 28*REGBYTES(sp) + LOAD x9, 29*REGBYTES(sp) + LOAD x18, 30*REGBYTES(sp) + LOAD x19, 31*REGBYTES(sp) + + addi sp, sp, 32*REGBYTES + mret |