summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--assembly/crosswalk/Makefile24
-rw-r--r--assembly/crosswalk/crosswalk.S198
l---------assembly/crosswalk/rvcontroller.ld1
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