diff --git a/Labs/12. Peripheral units/firmware/mem_files/lab_12_rx_led_instr.mem b/Labs/12. Peripheral units/firmware/mem_files/lab_12_rx_led_instr.mem new file mode 100644 index 0000000..51bbb50 --- /dev/null +++ b/Labs/12. Peripheral units/firmware/mem_files/lab_12_rx_led_instr.mem @@ -0,0 +1,31 @@ +050000b7 +02000137 +0001c1b7 +20018193 +0030a623 +00100213 +0040a823 +000011b7 +d0d18193 +00008237 +f7f20213 +0ff00493 +00100313 +00100293 +30429073 +04c00293 +00028293 +30529073 +00000063 +0000a383 +00947433 +00841413 +00746433 +00340863 +00440a63 +00812023 +30200073 +00612223 +30200073 +02612223 +30200073 diff --git a/Labs/12. Peripheral units/firmware/software/rx_led.S b/Labs/12. Peripheral units/firmware/software/rx_led.S new file mode 100644 index 0000000..296cceb --- /dev/null +++ b/Labs/12. Peripheral units/firmware/software/rx_led.S @@ -0,0 +1,50 @@ +_start: +# Инициализируем начальные значения регистров + 0: 050000b7 li x1, 0x05000000 # сохраняем базовый адрес uart_rx + 4: 02000137 li x2, 0x02000000 # сохраняем базовый адрес светодиодов + 8: 0001c1b7 li x3, 0x0001c200 # устанавливаем бодрейт 115200 + c: 20018193 +10: 0030a623 sw x3, 0x0c(x1) +14: 00100213 li x4, 0x00000001 # устанавливаем parity_bit +18: 0040a823 sw x4, 0x10(x1) +1c: 000011b7 li x3, 0x00000D0D # сохраняем спец-код для режима моргания +20: d0d18193 +24: 00008237 li x4, 0x00000808 # сохраняем спец-код для сброса +28: f7f20213 +2c: 0ff00493 li x9, 0x000000ff # сохраняем маску для обнуления старшей части +30: 00100313 li x6, 0x00000001 # сохраняем единицу +34: 00100293 li x5, 0x00000001 # подготавливаем маску прерывания единственного + # (нулевого) входа +38: 30429073 csrw mie, x5 # загружаем маску в регистр маски + +3c: 04c00293 la x5, trap_handler # псевдоинструкция la аналогично li загружает число, +40: 00028293 # только в случае la — это число является адресом +40: 00028293 # указанного места (адреса обработчика перехвата) + # данная псевдоинструкция будет разбита на две + # инструкции: lui и addi +44: 30529073 csrw mtvec, x5 # устанавливаем вектор прерывания +# Вызов функции main +main: +48: 00000063 beq x0, x0, main # бесконечный цикл, аналогичный while (1); +# ОБРАБОТЧИК ПЕРЕХВАТА +# Без стороннего вмешательства процессор никогда не перейдет к инструкциям ниже, +# однако в случае прерывания в программный счетчик будет загружен адрес первой +# нижележащей инструкции. +# Сохраняем используемые регистры на стек +trap_handler: +4c: 0000a383 lw x7, 0(x1) # загружаем значение из uart rx +50: 00947433 and x8, x8, x9 # обнуляем старые 3 байта +54: 00841413 slli x8, x8, 8 # Сдвигаем регистр x8 на 1 байт влево +58: 00746433 or x8, x8, x7 # записываем считанный из rx байт на освободившееся место +5c: 00340863 beq x8, x3, blink_mode # если пришел спец-код моргания, переходим в blink_mode +60: 00440a63 beq x8, x4, reset # если пришел спец-код сброса, переходим в reset +64: 00812023 sw x8, 0(x2) # записываем значением с переключателей в светодиоды +68: 30200073 mret # возвращаем управление программе (pc = mepc) + # что означает возврат в бесконечный цикл +blink_mode: +6c: 00612223 sw x6, 4(x2) # записываем 1 в led_mode +70: 30200073 mret + +reset: +74: 02612223 sw x6, 0x24(x2) # записываем 1 в led_reset +78: 30200073 mret