Листинг 1. Исходный файл программы тестирования процессорной системы TEST_DE2_70_Media_Computer.s

.include "address_map.s"

.equ RIBBON_CABLE_INSTALLED, 0

/* Программа демонстрирует различные возможности процессорной системы.

* Она выполняет следующие действия:

* 1. Тестирует статическую память.

* 2. Прокручивает текст на семисегментном дисплее. Если ошибок при тестировании

* статической памяти не обнаружено, то текст содержит слова "dE2" и "PASSEd". Если

* были обнаружены ошибки, то выводится слово "Error".

* 3. Мигает зелеными светодиодами. Скорость мигания светодиодов и прокрутки текста на

* семисегментных индикаторах регулируется прерываниями таймера.

* 4. Подключает переключатели к красным светодиодам.

* 5. Обрабатывает прерывания от кнопок. Нажатие кнопки KEY1 увеличивает скорость

* прокрутки текста. Нажатие кнопки KEY2 снижает скорость, кнопки KEY3 - останавливает

* прокрутку.

* 6. Тестирует порты расширения JP1, JP2.

* 7.Отсылает обратно данные, полученные по интерфейсу JTAG UART (символы, введенные в терминальном окне программы Altera Monitor Program) и наоборот. */

.text

.global _start

_start:

/* инициализируем регистры sp и fp */

movia sp, 0x03FFFFFC /* Стек начинается с последнего адреса SDRAM памяти

mov fp, sp

/* инициализируем буфер семисегментных индикаторов */

movia r16, DISPLAY_BUFFER

movi r17, 0xde2

stw r17, 0(r16)

stw zero, 4(r16)

stw zero, 8(r16)

/* инициализируем зеленые светодиоды */

movia r2, 0x55555555

movia r16, GREEN_LED_PATTERN

stw r2, 0(r16)

/* инициализируем счетчик задержки, используемый для определения изменений отображаемого текста */

movia r16, EIGHT_SEC

stw zero, 0(r16)

/* инициализируем переключатели */

movia r16, DISPLAY_TOGGLE

stw zero, 0(r16)

/* направление передачи может быть сохранено в SHIFT_DIRECTION,

где 0-влево, 1-вправо */

movi r2, 1

movia r16, SHIFT_DIRECTION

stw r2, 0(r16)

/* запускаем таймер и разрешаем его прерывания */

movia r16, INTERVAL_TIMER_BASE

movi r15, 0b0111 /* START = 1, CONT = 1, ITO = 1

sthio r15, 4(r16)

/* разрешаем прерывания от кнопок */

movia r16, PUSHBUTTON_BASE

movi r15, 0b01110 /* устанавливаем биты маски прерывания в 1

stwio r15, 8(r16)

/* разрешаем прерывания процессора */

movi r15, 0b011 /* разрешаем прерывания от таймера и кнопок

.if RIBBON_CABLE_INSTALLED

ori r15, r15, 0b1000000000000 /* также разрешаем прерывания для порта расширения JP2

.endif

wrctl ienable, r15

movi r15, 1

wrctl status, r15

/* цикл, в котором тестируется статическая память и обновляются семисегментные индикаторы */

movia r15, 0x55555555

movia r17, SRAM_END

DO_DISPLAY:

movia r16, SRAM_BASE

movia r17, SRAM_END

MEM_LOOP:

call UPDATE_HEX_DISPLAY

call UPDATE_RED_LED /* подключаем переключатели к красным светодиодам

call UPDATE_UARTS /* обновление и JTAG порта и последовательного порта

/* тестируем порты расширения, если подключен 40-контактный кабель Ribbon */

.if RIBBON_CABLE_INSTALLED

call TEST_EXPANSION_PORTS /*возвращает 0, если тест закончился неудачей

beq r2, zero, SHOW_ERROR

.endif

stw r15, 0(r16)

ldw r14, 0(r16)

bne r14, r15, SHOW_ERROR

addi r16, r16, 4

ble r16, r17, MEM_LOOP

xori r15, r15, 0xFFFF

xorhi r15, r15, 0xFFFF

/* обновляем буфер семисегментных индикаторов примерно каждые 8 секунд */

movia r16, EIGHT_SEC

ldw r17, 0(r16)

movi r14, 80 /* 80 прерываний таймера равны примерно 10 секундам

ble r17, r14, DO_DISPLAY

stw zero, 0(r16)

/* выводим на семисегментные индикаторы слова dE2 и PASSEd */

movia r16, DISPLAY_TOGGLE

ldw r17, 0(r16)

beq r17, zero, SHOW_PASSED

stw zero, 0(r16)

/* выводим dE2 */

movia r16, DISPLAY_BUFFER

movi r17, 0xdE2

stw r17, 0(r16)

stw zero, 4(r16)

stw zero, 8(r16)

br DO_DISPLAY

SHOW_PASSED:

movi r17, 1

stw r17, 0(r16)

movia r16, DISPLAY_BUFFER

movia r17, 0xbA55Ed /* слово Passed

stw r17, 0(r16)

stw zero, 4(r16)

stw zero, 8(r16)

br DO_DISPLAY

SHOW_ERROR:

movia r16, DISPLAY_BUFFER

movia r17, 0xe7787 /* слово Error

stw r17, 0(r16)

stw zero, 4(r16)

stw zero, 8(r16)

DO_ERROR:

call UPDATE_HEX_DISPLAY

br DO_ERROR

/*******************************************************************************Обновляем значения, выводимые на семисегментный дисплей. Значения считываются из буфера

*******************************************************************************/

.global UPDATE_HEX_DISPLAy

UPDATE_HEX_DISPLAY:

subi sp, sp, 36 /* резервируем память в стеке

/* сохраняем регистры */

stw ra, 0(sp)

stw fp, 4(sp)

stw r15, 8(sp)

stw r16, 12(sp)

stw r17, 16(sp)

stw r18, 20(sp)

stw r19, 24(sp)

stw r20, 28(sp)

stw r21, 32(sp)

addi fp, sp, 36

/* выводим значения на индикаторы */

movia r15, DISPLAY_BUFFER

ldw r16, 4(r15)

/* Цикл, который заполняет буфер из 2 слов, который подключен к параллельному порту «DE2-70 Media Computer», подключенного к семисегментным индикаторам. Для каждого сегмента отводится 8 бит буфера*/

movia r17, 7

movia r15, HEX3_HEX0

movia r19, SEVEN_SEG_DECODE_TABLE

SEVEN_SEG_DECODER:

mov r18, r16

andi r18, r18, 0x000F

add r20, r19, r18

add r21, zero, zero

ldb r21, 0(r20) /* в r21 загружаем код символа

stb r21, 0(r15) /* сохраняем код в буфере

srli r16, r16, 4

addi r15, r15, 1

subi r17, r17, 1

bge r17, zero, SEVEN_SEG_DECODER

/* выводим на семисегментные индикаторы содержимое буфера */

movia r15, HEX3_HEX0

ldw r16, 0(r15)

movia r17, HEX3_HEX0_BASE

stwio r16, 0(r17)

ldw r16, 4(r15)

movia r17, HEX7_HEX4_BASE

stwio r16, 0(r17)

/* извлекаем из стека регистры */

ldw ra, 0(sp)

ldw fp, 4(sp)

ldw r15, 8(sp)

ldw r16, 12(sp)

ldw r17, 16(sp)

ldw r18, 20(sp)

ldw r19, 24(sp)

ldw r20, 28(sp)

ldw r21, 32(sp)

addi sp, sp, 36 /* освобождаем зарезервированную память стека

ret

/*****************Подключаем переключатели к красным светодиодам****************/

.global UPDATE_RED_LED

UPDATE_RED_LED:

/* сохраняем регистры в стеке */

subi sp, sp, 16 /* резервируем область памяти в стеке

stw ra, 0(sp)

stw fp, 4(sp)

stw r15, 8(sp)

stw r16, 12(sp)

addi fp, sp, 16

/* считываем значение с переключателей */

movia r15, SLIDER_SWITCH_BASE

ldwio r16, 0(r15)

/* выводим его на красные светодиоды */

movia r15, RED_LED_BASE

stwio r16, 0(r15)

/* извлекаем из стека регистры */

ldw ra, 0(sp)

ldw fp, 4(sp)

ldw r15, 8(sp)

ldw r16, 12(sp)

addi sp, sp, 16

ret

/******************************************************************************* Считываем символы из JTAG порта и последовательного

порта UART и отправляем их обратно в оба порта *******************************************************************************/

.global UPDATE_UARTS

UPDATE_UARTS:

/* сохраняем регистры в стеке */

subi sp, sp, 28 /* резервируем область памяти в стеке

stw ra, 0(sp)

stw fp, 4(sp)

stw r15, 8(sp)

stw r16, 12(sp)

stw r17, 16(sp)

stw r18, 20(sp)

stw r19, 24(sp)

addi fp, sp, 28

movia r15, JTAG_UART_BASE

movia r19, UART_BASE

GET_CHAR:

ldwio r17, 0(r15) /* проверяем, имеют ли JTAG или UART порты новые данные

andi r18, r17, 0x8000 /* считываем символ

beq r18, r0, GET_CHAR_UART

andi r16, r17, 0x00ff

PUT_CHAR:

ldwio r17, 4(r15) /* проверяем, готовы ли порты JTAG UART к приему данных

andhi r17, r17, 0xffff

beq r17, r0, PUT_CHAR_UART

stwio r16, 0(r15) /* отправляем символ обратно

PUT_CHAR_UART:

ldwio r17, 4(r19)

andhi r17, r17, 0xffff

beq r17, r0, GET_CHAR_UART

stwio r16, 0(r19)

GET_CHAR_UART:

ldwio r17, 0(r19)

andhi r18, r17, 0xFFFF

beq r18, r0, NO_CHAR

andi r16, r17, 0x00ff

ldwio r17, 4(r19)

andhi r17, r17, 0xffff

beq r17, r0, PUT_CHAR_JTAG

stwio r16, 0(r19)

PUT_CHAR_JTAG:

ldwio r17, 4(r15)

andhi r17, r17, 0xffff

beq r17, r0, NO_CHAR

stwio r16, 0(r15)

NO_CHAR:

/* восстанавливаем из стека регистры */

ldw ra, 0(sp)

ldw fp, 4(sp)

ldw r15, 8(sp)

ldw r16, 12(sp)

ldw r17, 16(sp)

ldw r18, 20(sp)

ldw r19, 24(sp)

addi sp, sp, 28

ret

/*******************************************************************************

Данный код тестирует порты расширения JP1 и JP2. Для этого должен использоваться кабель Ribbon

*******************************************************************************/

.global TEST_EXPANSION_PORTS

TEST_EXPANSION_PORTS:

/* сохраняем регистры в стеке */

subi sp, sp, 24

stw ra, 0(sp)

stw fp, 4(sp)

stw r15, 8(sp)

stw r16, 12(sp)

stw r17, 16(sp)

stw r18, 20(sp)

addi fp, sp, 24

movia r15, JP1_EXPANSION_BASE

movia r16, JP2_EXPANSION_BASE

movia r17, 0xFFFFFFFF

stwio r17, 4(r15)

add r17, zero, zero

stwio r17, 4(r16)

movia r17, 0x55555555

stwio r17, 0(r15)

add zero, zero, zero

ldwio r18, 0(r16)

bne r17, r18, RET_ERROR

movia r17, 0xAAAAAAAA

stwio r17, 0(r15)

add zero, zero, zero

ldwio r18, 0(r16)

bne r17, r18, RET_ERROR

movia r17, 0x01234567

stwio r17, 0(r15)

add zero, zero, zero

ldwio r18, 0(r16)

bne r17, r18, RET_ERROR

add r17, zero, zero

stwio r17, 4(r15)

movia r17, 0xFFFFFFFF

stwio r17, 4(r16)

movia r17, 0x55555555

stwio r17, 0(r16)

add zero, zero, zero

ldwio r18, 0(r15)

bne r17, r18, RET_ERROR

movia r17, 0xAAAAAAAA

stwio r17, 0(r16)

add zero, zero, zero

ldwio r18, 0(r15)

bne r17, r18, RET_ERROR

movia r17, 0x01234567

stwio r17, 0(r16)

add zero, zero, zero

ldwio r18, 0(r15)

bne r17, r18, RET_ERROR

movi r2, 1

br RETURN

RET_ERROR:

movi r2, 0

RETURN:

ldw ra, 0(sp)

ldw fp, 4(sp)

ldw r15, 8(sp)

ldw r16, 12(sp)

ldw r17, 16(sp)

ldw r18, 20(sp)

addi sp, sp, 24

ret

/****************************** DATA SECTION *********************************/

.data

.global DISPLAY_BUFFER

DISPLAY_BUFFER:

.fill 3, 4, 0

.global SHIFT_DIRECTION

SHIFT_DIRECTION:

.word 0

/* Таблица декодирования семисегментных индикаторов содержит значения включен(1)/выключен(0) для каждого сегмента индикаторов*/

SEVEN_SEG_DECODE_TABLE:

.byte 0b00000000, 0b00000110, 0b01011011, 0b01001111

.byte 0b01100110, 0b01101101, 0b01111100, 0b01010000

.byte 0b01011100, 0b01100111, 0b01110111, 0b01110011

.byte 0b00111001, 0b01011110, 0b01111001, 0b01110001

HEX3_HEX0:

.word 0

HEX7_HEX4:

.word 0

.global GREEN_LED_PATTERN

GREEN_LED_PATTERN:

.word 0

.global EIGHT_SEC

EIGHT_SEC:

.word 0

DISPLAY_TOGGLE:

.word 0

.end

Листинг 2 Исходный файл программы lab1_part3_DE.s

/* Программа осуществляет поиск максимального числа в списке целых чисел. */

.equ LIST, 0x500 /* Адрес начала списка в памяти. Первый элемент списка будет содержать максимальное число, 2-ой - количество чисел в списке*/

.global _start

_start:

movia r4, LIST /* В регистр R4 записывается адрес начала списка */

ldw r5, 4(r4) /* Считываем в регистр R5 значение количества чисел в списке */

addi r6, r4, 8 /* Вычисляем адрес памяти, с которого начинают располагаться числа для поиска*/

ldw r7, (r6) /* В регистр R7 из памяти по адресу R6 считывается первое число списка */

LOOP:

subi r5, r5, 1 /* Уменьшаем значение количества чисел в списке */

beq r5, r0, DONE /* Если значение регистра R5 равно 0, то выходим из цикла */

addi r6, r6, 4 /*Увеличиваем адрес памяти на 4 (переходим к следующему числу */

ldw r8, (r6) /* Считываем из памяти следующее число */

bge r7, r8, LOOP /* Если текущее максимальное число больше или равно считанному, то возвращаемся в начало цикла*/

add r7, r8, r0 /* Иначе, записываем в R7 новое максимальное число */

br LOOP

DONE:

stw r7, (r4) /* Записываем максимальное число в память по адресу 0x500 */

STOP:

br STOP /* Бесконечный цикл */

.org 0x100

RESULT:

.skip 4 /* Выделяем 4 байта для хранения максимального числа */

N:

.word 7 /* Количество чисел в списке */

NUMBERS:

.word 4, 5, 3, 6, 1, 8, 2 /* Числа из списка */

.end

Листинг 3 Исходный файл программы LCD_DE2_70.s

.include "nios_macros.s"

.text

.equ lcd,0x10003050 /*Адрес регистра lcd*/

.equ clear,0x00000001 /*Код команды очистки экрана lcd*/

.equ set1,0b10000000 /*Код команды установки курсора в первую позицию первой строки*/

.equ set2,0b11000000 /*Код команды установки курсора в начало 2 строки*/

.equ off,0b00001100 /*Код команды выключения курсора*/

.equ right,0b00011100 /*Код команды сдвига экрана вправо*/

.equ left,0b00011000 /*Код команды сдвига курсора влево*/

.global _start

_start:

movia r2,lcd

movi r3,clear /*Код команды очистки lcd*/

stbio r3,0(r2) /*Очищаем экран lcd*/

movi r3,set1

stbio r3,0(r2) /*Устанавливаем курсор в начало первой строки*/

movia r4,String1 /*В регистр R4 записываем адрес первой строки*/

cikl:

ldb r5,0(r4) /*Считываем символ из строки и помещаем его в R5*/

beq r5,zero,met /*Если считанныцй символ равен 0, то выходим из цикла*/

stbio r5,1(r2) /*Записываем из R5 в регистр данных lcd*/

addi r4,r4,1 /*Инкрементируем адрес символа строки*/

br cikl

met:

movi r3,set2

stbio r3,0(r2) /*Устанавливаем курсор в начало второй строки*/

movia r4,String2 /*Выводим вторую строку*/

cikl2:

ldb r5,0(r4)

beq r5,zero,met1

stbio r5,1(r2)

addi r4,r4,1

br cikl2

met1:

movi r3,off

stbio r3,0(r2) /*Выключаем курсор*/

met2:

movi r3,right

stbio r3,0(r2) /*Сдвигаем экран вправо*/

br met2

met3:

movi r3,left

stbio r3,0(r2) /*Сдвигаем экран влево*/

br met3

.data /*Определяем сегмент данных*/

String1:

.asciz "Kreitin konec"

String2:

.asciz "Alexander"

.end

Таблица 2 ASCII - коды символов


Понравилась статья? Добавь ее в закладку (CTRL+D) и не забудь поделиться с друзьями:  



double arrow
Сейчас читают про: