diff options
Diffstat (limited to 'assembly')
| -rw-r--r-- | assembly/crosswalk/Makefile | 24 | ||||
| -rw-r--r-- | assembly/crosswalk/crosswalk.S | 198 | ||||
| l--------- | assembly/crosswalk/rvcontroller.ld | 1 |
3 files changed, 223 insertions, 0 deletions
diff --git a/assembly/crosswalk/Makefile b/assembly/crosswalk/Makefile new file mode 100644 index 0000000..ec7bc31 --- /dev/null +++ b/assembly/crosswalk/Makefile @@ -0,0 +1,24 @@ +MARCH ?= rv32imacbzicntr_zicond_zicsr_zifencei_zihintpause_zilsd_zclsd_zabha_zacas_zbkb_zbkx_zcb_zcmp_zcmt + +.PHONY: all dump load clean + +all: crosswalk.hex + +crosswalk.o: crosswalk.S + riscv32-none-elf-as -I../rvcontroller-libraries -march=${MARCH} -o crosswalk.o crosswalk.S + +crosswalk.elf: crosswalk.o + riscv32-none-elf-ld -T rvcontroller.ld --no-warn-rwx-segments -o crosswalk.elf crosswalk.o + +dump: crosswalk.elf + riscv32-none-elf-objdump -d crosswalk.elf + +crosswalk.hex: crosswalk.elf + riscv32-none-elf-objcopy -O ihex crosswalk.elf crosswalk.hex + +load: crosswalk.hex + bash -c "wl-copy < crosswalk.hex" + +clean: + rm -f crosswalk.hex crosswalk.elf crosswalk.o + diff --git a/assembly/crosswalk/crosswalk.S b/assembly/crosswalk/crosswalk.S new file mode 100644 index 0000000..8633ed7 --- /dev/null +++ b/assembly/crosswalk/crosswalk.S @@ -0,0 +1,198 @@ +la t0,handler +csrw mtvec,t0 # Set up trap handler +li t0,0x400 +csrc mstatush,t0 # Turn off MDT +li t0,0x30000 +csrw mie,t0 # Mask all interrupts except mesecons/digilines +csrw mip,zero # Clear any pending interrupts +csrsi mstatus,0x8 # Turn on MIE to enable interrupts + +la t0,pedwaiting +sb zero,0(t0) # Clear the pedestrian waiting flag (really it should already be clear, this handles the case of a program restart) + +restart: +la a0,lightchannel +la a1,greenmsg +li a7,129 +ecall # Light -> green + +la a0,pedchannel +la a1,redmsg +li a7,129 +ecall # Ped -> red (don't walk) + +li a0,10 +call sleep + +waitloop: +la t0,pedwaiting +lb t0,0(t0) +bnez t0,startsequence # Check if someone is waiting +wfi # Otherwise wait for something to happen +j waitloop + +startsequence: +la a0,lightchannel +la a1,yellowmsg +li a7,129 +ecall # Light -> yellow + +li a0,3 +call sleep + +la a0,lightchannel +la a1,redmsg +li a7,129 +ecall # Light -> red + +li a0,2 +call sleep + +la a0,pedchannel +la a1,greenmsg +li a7,129 +ecall # Ped -> green (walk) + +li a0,5 +call sleep + +la a0,pedchannel +la a1,flashredmsg +li a7,129 +ecall # Ped -> flashing red (flashing don't walk) + +la t0,pedwaiting +sb zero,0(t0) # Clear the detection flag at this point too + +li a0,10 +call sleep + +la a0,pedchannel +la a1,redmsg +li a7,129 +ecall # Ped -> red (don't walk) + +li a0,1 +call sleep + +la a0,lightchannel +la a1,redyellowmsg +li a7,129 +ecall # Light -> red+yellow + +li a0,1 +call sleep + +j restart # This will turn the light green before going back to waiting + + +sleep: +csrr t0,time # Only using 32 bits here, this will have problems after 136ish years +add a0,t0,a0 +sleep_loop: +pause +csrr t0,time +blt t0,a0,sleep_loop +ret + + + +.align 4 +handler: +csrrw x31,mscratch,x31 # Free up x31 to hold the context address +la x31,hcontext # Using x register numbers here since trap handlers don't use the usual calling convention +sw x1,0(x31) # Save all the registers to the context +sd x2,4(x31) # Two at a time since we have Zilsd/Zclsd +sd x4,12(x31) +sd x6,20(x31) +sd x8,28(x31) +sd x10,36(x31) +sd x12,44(x31) +sd x14,52(x31) +sd x16,60(x31) +sd x18,68(x31) +sd x20,76(x31) +sd x22,84(x31) +sd x24,92(x31) +sd x26,100(x31) +sd x28,108(x31) +sw x30,116(x31) +csrr x30,mscratch # Get the old x31 value back into a register +sw x30,120(x31) # and write that back out too + +csrr t0,mcause # Read why the trap occurred + +li t1,0x80000011 # Interrupt 17 = digilines +beq t0,t1,handler_digilines + +j handler_other # Something else + +handler_digilines: +li a7,135 +la a0,channelbuf +li a1,21 +la a2,msgbuf +li a3,21 +ecall # Read what the event was + +la t0,channelbuf +lb t0,0(t0) +li t1,'b' +bne t0,t1,handler_notbutton # Check if the channel started with 'b' (not going to bother checking the rest) + +la t0,pedwaiting +li t1,1 +sb t1,0(t0) # Set the pedestrian waiting flag + +handler_notbutton: + +li a7,133 +ecall # Check if there are more messages to process +bnez a0,handler_digilines + +csrw mip,zero # Clear out all pending interrupts +la x31,hcontext # x numbers here for the same reason as during the save +lw x1,0(x31) # Load all of the registers from the context +ld x2,4(x31) # Two at a time since we have Zilsd/Zclsd +ld x4,12(x31) +ld x6,20(x31) +ld x8,28(x31) +ld x10,36(x31) +ld x12,44(x31) +ld x14,52(x31) +ld x16,60(x31) +ld x18,68(x31) +ld x20,76(x31) +ld x22,84(x31) +ld x24,92(x31) +ld x26,100(x31) +ld x28,108(x31) +ld x30,116(x31) +mret # Return to the program + +handler_other: +li a7,4 +la a0,unimplementedmsg +ecall # Display unimplemented trap message + +csrr a0,mcause # Read what the cause was +li a7,1 +ecall # Tell the user + +li a7,10 +ecall # Then halt + + +hcontext: .skip 32*4 +unimplementedmsg: .asciz "Unimplemented trap!\nmcause: " +channelbuf: .asciz " " +msgbuf: .asciz " " + +lightchannel: .asciz "light" +pedchannel: .asciz "ped" +redmsg: .asciz "RED" +yellowmsg: .asciz "YELLOW" +greenmsg: .asciz "GREEN" +flashredmsg: .asciz "FLASHRED" +redyellowmsg: .asciz "REDYELLOW" +pedwaiting: .byte 0 diff --git a/assembly/crosswalk/rvcontroller.ld b/assembly/crosswalk/rvcontroller.ld new file mode 120000 index 0000000..bc01402 --- /dev/null +++ b/assembly/crosswalk/rvcontroller.ld @@ -0,0 +1 @@ +../../rvcontroller.ld
\ No newline at end of file |
