Алгоритм теста такой:
1. Очищаем весь КД в режиме "стек" (заполняем 0FFh).
2. Пишем байт в режиме ОЗУ в доступной области.
3. Считываем и проверяем -- если совпало с записанным, то стираем и идём к следующему адресу и в п.2
4. Если не совпало и не равно 0FFh -- выводим ошибку, стираем и к следующему адресу и в п.2.
5. Если не совпало и равно 0FFh -- выводим ошибку.
6. Ищем по всему диску в режиме "стек" байт, не равный 0FFh и если находим, то выводим его адрес и значение, очищаем и снова в п.2.
Вот как-то так... А результаты можно интерпретировать так:
- если байты в момент сбоя не пишутся на КД вообще -- это проблема с сигналом WE (ЗПЗУ).
- если байты пишутся по неправильному адресу -- проблема с адресной шиной, микросхемами Д3 или Д4. По результатам теста можно сравнить адреса и определить сбойные биты.
- ну третий вариант -- пишется неправильный байт (такого не было). Тогда надо проверять шину данных или циклы записи...
Откомпилированный тест в архиве:
MyTestKDer.7z
Исходники теста на ассемблере:
Код:
.ORG 00100h
L_0100: LXI D, L_DTST ; для начала очистка КД
PUSH D ; сохраняем в стеке ссылку
L_CLEAR:POP D ; считываем ссылку
LDAX D ; загружаем A по ссылке
ORA A
JZ L_NEXT ; переход, если там ноль ---->>>>
INX D ; DE=DE+1
PUSH D ; сохраняем в стеке новую ссылку
DI ; запрещаем прерывания
OUT 010h ; отправляем в порт
LXI H, 0000h
DAD SP ; SP+0 в HL
SHLD L_SAVE ; сохранить указатель на стек
LXI D, 0FFFFh ; чем заполнять -- предварительная очистка памяти
LXI H, 8000h ; сколько/2
LXI SP,0000h ; свой указатель на стек
L_LP0: PUSH D ; заполняем КД через стек...
DCX H
MOV A, L
ORA H
JNZ L_LP0 ; зациклено
XRA A ; обнуляем аккумулятор
OUT 010h ; отправляем в порт -- отключаем КД
LHLD L_SAVE ; считать сохранённый указатель на стек в HL
SPHL ; восстанавливаем SP
EI ; разрешаем прерывания
JMP L_CLEAR ; цикл очистки
;
L_NEXT: LXI D, L_TEXT1
MVI C, 009h
CALL 5 ; вывод сообщения об окончании очистки КД
LXI D, L_DTOZU ; ссылка на кофигурацию КД "ОЗУ"
PUSH D ; сохраняем в стеке ссылку
L_CHK: POP D ; считываем ссылку
LDAX D ; загружаем A по ссылке
ORA A
JZ L_DONE ; переход, если там ноль ---->>>>
INX D ; DE=DE+1
PUSH D ; сохраняем в стеке новую ссылку
DI ; запрещаем прерывания
OUT 010h ; отправляем в порт
LXI H, 08000h ; заполнение памяти -- сколько
LXI B, 08000h ; с какого адреса
L_LP1: MVI A, 055h ; чем заполнять
STAX B ; пишем
MOV A, M ; читаем в A из другой ячейки (для смены адреса)
LDAX B ; читаем записанное ранее в A
CPI 055h ; сравниваем
JZ L_GOOD ; значения равны -- двигаемся дальше...
MOV D, A ; сохраняем считанное значение в D
MVI A, 0FFh ; очищаем найденную ячейку
STAX B ; пишем
STAX B ; пишем второй раз, для надёжности
XRA A ; обнуляем аккумулятор
OUT 010h ; отправляем в порт -- отключаем КД
EI ; разрешаем прерывания
PUSH H ; сохранить счётчики
PUSH B
PUSH D ; сохраняем D
LXI D, L_TEXT2 ; сообщение об ошибке по адресу
MVI C, 009h
CALL 5 ; вывод сообщения
POP D
POP H ; восстанавливаем адрес
PUSH H
PUSH D ; сохраняем D
CALL L_BHEX ; выводим старший байт адреса в шестнадцатиричном виде
MOV H, L
CALL L_BHEX ; выводим младший байт адреса в шестнадцатиричном виде
LXI D, L_TEXT3 ; сообщение о считанном байте
MVI C, 009h
CALL 5 ; вывод сообщения
POP H ; восстанавливаем плохой байт
CALL L_BHEX ; выводим считанный байт в шестнадцатиричном виде
MOV A, H
CPI 0FFh ; сравниваем c 0FFh
CZ L_FDATA ; если так, то запускаем поиск по всему КД
POP B ; восстановить счётчики
POP H
POP D ; считываем адрес на конфигурацию КД
PUSH D ; и сохраняем
DCX D
LDAX D ; загружаем A по ссылке
DI ; запрещаем прерывания
OUT 010h ; отправляем в порт -- снова включаем КД
L_GOOD: MVI A, 0FFh ; очищаем ячейку
STAX B ; пишем
STAX B ; пишем второй раз, для надёжности
INX B
DCX H
MOV A, L
ORA H
JNZ L_LP1 ; пока HL не обнулится
XRA A ; обнуляем аккумулятор
OUT 010h ; отправляем в порт -- отключаем КД
EI ; разрешаем прерывания
LXI D, L_TEXT4 ; сообщение о переходе к другому банку КД
MVI C, 009h
CALL 5 ; вывод сообщения
JMP L_CHK ; цикл проверки
;
L_DONE: LXI D, L_TEXT
MVI C, 009h
CALL 5 ; вывод сообщения об окончании проверки КД
RET ; выход из программы
;
L_BHEX: MOV A, H ; H-входное значение для вывода
RRC
RRC
RRC
RRC ; сдвиг вправо на 4 бита
CALL L_BIT ; выводим старшие 4 бита
MOV A, H ; восстанавливаем значение
L_BIT: ANI 00Fh ; оставляем младшие 4 бита
CPI 00Ah
JM L_B10 ; если меньше 10
ADI 007h ; +7
L_B10: ADI 030h ; +30h
MVI D, 000h
MOV E, A
MVI C, 002h ; вывод символа
PUSH H ; сохраняем HL
CALL 5
POP H ; восстанавливаем HL
RET
;
; ПП поиска по всему КД
L_FDATA:LXI D, L_TEXT5 ; сообщение о начале поиска на КД
MVI C, 009h
CALL 5 ; вывод сообщения
LXI D, L_DTST ; конфигурация КД
PUSH D ; сохраняем в стеке ссылку
L_FNC: POP D ; считываем ссылку
LDAX D ; загружаем A по ссылке
ORA A
JNZ L_FNXT ; если не ноль
LXI D, L_TEXT6 ; сообщение о том, что ничего не нашли
MVI C, 009h
CALL 5 ; вывод сообщения
RET ; выход из ПП ---->>>>
L_FNXT: INX D ; DE=DE+1
PUSH D ; сохраняем в стеке новую ссылку
DI ; запрещаем прерывания
OUT 010h ; отправляем в порт
LXI H, 0000h
DAD SP ; SP+0 в HL
SHLD L_SAVE ; сохранить указатель на стек
LXI H, 00000h ; нач.адрес
LXI SP,00000h ; свой указатель на стек
L_LPF: POP D ; считываем из стека два байта
MOV A, E
CPI 0FFh ; если младший байт прочитанного не равен 0FFh
JNZ L_FERR ; выход из цикла с сообщением
INX H ; адрес +1
MOV A, D
CPI 0FFh ; если старший байт прочитанного не равен 0FFh
JNZ L_FERR ; выход из цикла с сообщением
INX H ; адрес +1
MOV A, L
ORA H
JNZ L_LPF ; зациклено, пока адрес не обнулится
XRA A ; обнуляем аккумулятор
OUT 010h ; отправляем в порт -- отключаем КД
LHLD L_SAVE ; считать сохранённый указатель на стек в HL
SPHL ; восстанавливаем SP
EI ; разрешаем прерывания
LXI D, L_TEXT4 ; сообщение о переходе к другому банку КД
MVI C, 009h
CALL 5 ; вывод сообщения
JMP L_FNC ; цикл поиска
;
L_FERR: STA L_EBYT ; сохраняем найденный байт
SHLD L_EADR ; сохраняем адрес
LXI D, 0FFFFh ; очищаем ячейку
PUSH D
XRA A ; обнуляем аккумулятор
OUT 010h ; отправляем в порт -- отключаем КД
LHLD L_SAVE ; считать сохранённый указатель на стек в HL
SPHL ; восстанавливаем SP
EI ; разрешаем прерывания
POP D ; считываем ссылку (для удаления её из стека)
LXI D, L_TEXT2 ; сообщение об ошибке по адресу
MVI C, 009h
CALL 5 ; вывод сообщения
LHLD L_EADR ; читаем найденный адрес
CALL L_BHEX ; выводим старший байт адреса в шестнадцатиричном виде
MOV H, L
CALL L_BHEX ; выводим младший байт адреса в шестнадцатиричном виде
LXI D, L_TEXT3 ; сообщение о считанном байте
MVI C, 009h
CALL 5 ; вывод сообщения
LDA L_EBYT ; читаем найденный байт
MOV H, A
CALL L_BHEX ; выводим считанный байт в шестнадцатиричном виде
RET ; завершаем поиск
;
L_SAVE: .dw 0000h
L_TEXT: .db 0Dh, 0Ah, "-- konec testa --$"
L_TEXT1:.db 0Dh, 0Ah, "-- o~istka kd wypolnena --$"
L_TEXT2:.db 0Dh, 0Ah, "o{ibka po adresu $"
L_TEXT3:.db ", s~itan bajt: $"
L_TEXT4:.db 0Dh, 0Ah, "perehod k sledu`}emu"
.db " banku kd $"
L_TEXT5:.db 0Dh, 0Ah, "i}em bajt na kd...$"
L_TEXT6:.db 0Dh, 0Ah, "ni~ego ne na{li. :-)"
.db " prodolvaem test.$"
L_DTST: .db 01Ch ; 00011100b -- вкл. 3 банк как стек на КД
.db 018h ; 00011000b -- вкл. 2 банк как стек на КД
.db 014h ; 00010100b -- вкл. 1 банк как стек на КД
.db 010h ; 00010000b -- вкл. 0 банк как стек на КД
.db 000h ; конец
L_DTOZU:.db 0E3h ; 11100011b -- вкл. 3 банк как ОЗУ 8000h-FFFFh
.db 0E2h ; 11100010b -- вкл. 2 банк как ОЗУ 8000h-FFFFh
.db 0E1h ; 11100001b -- вкл. 1 банк как ОЗУ 8000h-FFFFh
.db 0E0h ; 11100000b -- вкл. 0 банк как ОЗУ 8000h-FFFFh
.db 000h ; конец
L_EADR: .dw 0000h
L_EBYT: .db 00h
.END
[свернуть]