Исходный код вики API контроллеров AZ

Версия 21.1 от Max на 2025/02/08 20:08

Последние авторы
1 {{box cssClass="floatinginfobox" title="**Contents**"}}
2 {{toc/}}
3 {{/box}}
4
5 = **Концепция контроллера** =
6
7 Контроллер эмулирует до 32х дисковых устройств AZ на одной микроSD-карточке. Каждый эмулируемый диск (псевдодиск) представлен на карточке файлом с точки зрения файловой системы FAT32, поэтому не возникает никаких вопросов в размещении псевдодисков на носителе большого объема - просто помещаем карточку в кардридер, подключаем к PC, копируем на карточку файлы нужного объема (и с нужным содержимым), переставляем ее в контроллер, и всё! Более того, поработав с карточкой на ДВК/БК/УКНЦ, можно извлечь ее из контроллера, снова поместить в кардридер и скопировать наработанные файл-образы дисков на PC, где с ними можно работать любыми средствами - например, подключить к эмулятору, заархивировать и сложить куда-нибудь на хранение, отправить в конференцию, и т.п. Также не представляет особого труда скопировать какой-то материал, найденный в сети, на карточку, переставить ее в контроллер и использовать этот материал на ДВК/УКНЦ.
8
9
10 == **Регистры контроллера.** ==
11
12 Контроллер имеет 4 регистра на МПИ
13 \\• 177220 - регистр команд и состояния (CSR)
14 • 177222 - регистр данных (DR)
15 • 177224 - регистр начальной загрузки основной (BOOT1)
16 • 177226 - регистр начальной загрузки альтернативный (BOOT2)
17 \\Регистр CSR принимает команды в разрядах D0-D5 и бит разрешения прерываний в разряде D6, все только запись, читается всегда ноль. В разряде D7 читается бит готовности. Единица в нем означает, что предыдущая команда выполнена и контроллер готов к обмену. Ноль означает, что контроллер занят исполнением предыдущей операции, остальные регистры при этом отключены, обращение к любому из них вызовет Trap to 4. Если исполнение предыдущей команды вызвало ошибку, одновременно с битом D7 взводится бит D15.
18 \\Запись в регистры производится только словом, байтовая запись недопустима.
19 \\Весь обмен данными ведется через DR. Для команд, аргумент у которых одно слово, этот аргумент следует переслать в DR, а затем выслать команду в CSR. Для команд обмена с буфером контроллера, наоборот, следует выдать команду и только после нее принимать или передавать блок данных определённой длины.
20
21 == **Прерывания** ==
22
23 Большинство команд исполняется, практически, мгновенно - за время исполнения одной-двух команд ЦП. Но команды обмена с карточкой микро-SD все-таки, требуют времени. Ожидать окончания этих операций можно либо поллингом бита D7 CSR, либо (например, при наличии многозадачной ОС, которой есть, куда утилизировать это время) - взвести бит D6 CSR (разрешение прерываний) и заняться чем-то другим. Когда операция будет завершена, произойдет прерывание и по нему можно продолжить операции.
24
25
26 == **Пространства имен** ==
27
28 Как уже было сказано - дисковое устройство презентуемое в систему PDP-11 это физический файл на какой-то файловой системе. Начиная с V17 прошивки, появился сетевой функционал, он позволяет использовать сетевые диски предоставляемые посредством технологии [[MAXIOL Landisk>>https://forum.maxiol.com/index.php?s=&showtopic=5632&view=findpost&p=59531]]®. Соответственно, для полной унификации и обеспечения полной "прозрачности" все отличия сводятся к точке монтирования, на данный момент это следующие пространства:
29
30 * 0:/  - локальные файлы на MicroSD карточке
31 * R:/ - сетевые файлы в файловом репозитории
32 * N:/ - сетевые файлы в архиве [[https:~~/~~/mirrors.pdp-11.ru/>>https://mirrors.pdp-11.ru/]]
33
34 Планируемые сетевые пространства (фунционал будет реализован в следующих прошивках):
35
36 * P:/  - персональное облако, доступно только под одной УЗ
37 * S:/ - облако которое позволяет делится своими файлами с другими участниками
38
39 == Буфера ==
40
41 В контроллере несколько буферов различного назначения, все буфера имеют словные размеры ибо отдаются через 16ти битный регистр
42
43 * Основной буфер - IOBUF  [258] 
44 * Буфер энергонезависимой памяти - cmosmem_buffer[256]
45 * Буфер часов - выходной timestamp_out_buffer[14]
46 * Буфер часов - входной timestamp_in_buffer [7]
47 * Буфер ip информации - ipdata
48 * Буфер размера карты - sizecard
49
50 = **Основной блок команд** =
51
52 Команда посылается в CSR, в разряды 5-0. Пересылать следует только словом, байтовая запись недопустима. Разряды команды только для записи, читается всегда ноль. Коды команд приведены **восьмеричные**.
53
54 Данные команды используют основной буфер для своей работы (IOBUF  [258]).
55
56 == **000: Сброс контроллера** ==
57
58 Код команды - 000. Команда останавливает, если возможно, все операции контроллера. Её окончания следует дождаться посредством поллинга.
59 Пример программы:
60
61 {{code language="assembler"}}
62 ;.............................
63 MOV #AZ$CSR,R3
64 1$: CLR @R3; Пошлем команду "Сброс"
65 TSTB @R3; Проверим готовность контроллера
66 BPL 1$; Если не готов, сбрасываем еще
67 ; раз и проверяем снова
68 TST (R3)+; Проверим на ошибку,
69 ; одновременно сменим адрес
70 ; (пригодится дальше)
71 BMI ERR1
72 ;...............................
73 {{/code}}
74
75 Замечание о команде сброса. Вообще-то, она мгновенного действия - если контроллер не занят исполнением операции, которую прерывать нельзя, конкретно - обмен с SD. Пока идет обмен с SD, контроллер не воспринимает никаких команд и команда сброса может быть пропущена. Поэтому, если контроллер занят (бит D7 равен нулю), выдача команды сброса повторяется. Такое встречается достаточно редко (допустим, двойное нажатие Ctrl/C при перезаписи), обычно, при нормальном ходе операций, ожидание записи или чтения производится в специальном месте и, по окончании этой операции, выполняется не сброс, а совсем другие действия.
76
77
78 == **001: Выбор устройства** ==
79
80 Контроллер поддерживает до 32х псевдодисков. Команда "выбор устройства" выбирает для работы один из них. Код команды 001. Для выбора устройства следует переслать в регистр данных (177222) номер накопителя, с которым собираемся работать и затем послать в CSR код 001. Команда выполняется мгновенно, т.е. за время, пока ЦП пересылает код "выбор устройства". ПРи попытке выбрать диск AZ, которому не назначен файл-образ, в бите D15 регистра CSR возвращается ошибка.
81
82 Пример программы:
83
84 {{code language="assembler"}}
85 ;.......................
86
87 SetUni = 001; Символическое наименование команды
88 ; "Выбор устройства"
89
90 ; От предыдущего фрагмента в R3 остался адрес CSR+2=DR
91
92 ; Считаем, что в R0 в битах 0-3 находится номер
93 ; устройства, остальные биты - нули, процедура
94 ; вычисления этого номера не показана.
95
96 MOV R0,@R3; Перешлем в DR номер диска AZ, с
97 ; с которым собираемся работать
98
99 MOV #SetUni,-(R3); и пошлем команду "Выбор
100 ; накопителя", с исправлением адреса в R3, который
101 ; теперь снова указывает на CSR.
102
103 TST (R3)+; Проверим на ошибку и опять
104 ; передвинем адрес в R3 на DR
105 BMI ERR2
106
107 ;........................
108 {{/code}}
109
110
111 == **002: Установка номера блока, младшие биты номера блока** ==
112
113 Контроллер предоставляет машинке с МПИ в качестве дисков AZ0 - AZ7 файл-образы типа DSK на карточке микро-SD. Размер этих файл-образов и, соответственно, псевдодисков, может быть любым, вплоть до 4Г каждый. Адресация на этих псевдодисках прямая - полученный по МПИ номер блока, после сдвига, используется в качестве смещения от начала соответствующего файл-образа. Фактически, это нечто, вроде LBA на PC.
114 \\Существуют операционные системы PDP-11, поддерживающие такие диски - RSX-11, ДИАМС, еще что-то. Однако, самая распространенная ОС - RT-11 - использует для номера блока СЛОВО (16 бит), причем код 0177777 кое-где используется в специальных целях и как размер диска не годится, поэтому для RT-11 могут быть использованы диски с максимальным числом блоков 0177776, т.е. 65534 блока (33553408 байт или 32767 К байт). Поэтому команды установки номера блока две: установить младшие биты номера блока - код 002 и установить старшие биты номера блока - код 012. Если номер блока помещается в 16 разрядов (для RT-11 - всегда), достаточно использовать команду установки младших битов номера блока, старшие биты при этом очищаются. Если номер не помещается в 16 разрядов, то сначала надо выдавать младшие биты, а потом старшие. Если попытаться сразу передать старшие биты без предварительной передачи младших, выдается ошибка. Если переданный адрес выходит за границу файл-образа, также выдается ошибка, не важно, на каком этапе - хоть при передаче младших 16 битов номера блока, хоть при передаче старших.
115 \\Для выполнения этих действий следует переслать требуемую часть битов номера блока в DR и затем переслать в CSR код команды, после чего следует проверить на ошибку. Команды мгновенные, т.е. выполняются за один цикл обращения по МПИ.
116 \\Пример программы в 16-разрядном варианте:
117
118 {{code language="assembler"}}
119 ;.......................................
120
121 SetBlk=002; Символическое наименование команды
122 ; "Установить младшие 16 разрядов номера блока"
123
124 ; От предыдущего фрагмента в R3 остался адрес DR
125 ; (177222)
126 ; Считаем, что в ячейке с меткой BLCUR находится 16-
127 ; разрядный дисковый адрес (номер блока, подлежащего
128 ; вводу или выводу). Процедура получения этого номера не
129 ; показана
130
131 MOV BLCUR,@R3; Помещаем в DR номер блока,
132 ; подлежащего обмену.
133
134 MOV #SetBlk,-(R3); Посылаем команду в CSR
135 ; не забываем, адрес в R3 перед пересылкой уменьшится на
136 ; 2 и таким останется
137
138 TST @R3; Проверяем на ошибку
139
140 BMI ERR3
141
142 ; В 32-разрядном варианте те же действия следует
143 ; повторить для старших 16 разрядов (на самом деле,
144 ; старших 7, остальные должны быть нулями, ибо максимум
145 ; размера псевдодиска - 4Г) дискового адреса.
146
147 ; Обратите внимание, что в R3 остался адрес CSR, а не
148 ; DR, как в двух предыдущих фрагментах. Это сделано
149 ; специально.
150
151 ;.......................................
152 {{/code}}
153
154
155 == **003: Открыть оглавление HFS** ==
156
157 Последовательность действий
158 \\• сбросить контроллер
159 • подать в CSR команду "Принять блок данных в буфер" и передать пословно всю строку с полным текстом пути (Full Path) к требуемому оглавлению. Строка должна завершаться нулевым байтом (0х00) и быть не длиннее 384 байт (192 слов).
160 • переслать в CSR код команды "Открыть оглавление"
161 • дождаться ее окончания (команда длительная)
162 • проверить на ошибку
163
164 [[**//Пример утилиты - AZDIR//**>>url:https://forum.maxiol.com/index.php?s=&showtopic=5605&view=findpost&p=59418]]
165
166
167 Пример программы:
168
169 {{code language="assembler"}}
170 ;.............................
171 AZ$CSR = 177220
172 WrBuf = 016
173 OpnDir = 003
174
175 MOV #AZ$CSR,R3
176
177 ; Ячейка DirPtr содержит указатель на начало поля с Full
178 ; Path. Считаем, что строка завершается тремя нулевыми
179 ; байтами, чтобы распознать по нулю окончание пересылки
180 ; строки пословно. Действительно, если количество
181 ; символов в строке четное, то следующие два байта нулей
182 ; образуют нулевое слово; если же нечетное, то один ноль
183 ; уйдет вместе с последним символом строки, а нулевое
184 ; слово образуют второй и третий нулевые байты,
185 ; оканчивающие строку. То есть, такое окончание строки,
186 ; передаваемой пословно, вполне надежно.
187 MOV DirPtr,R2
188
189 MOV #WrBuf,(R3)+; Подаем команду "Запись в
190 ; буфер" и передаем строку
191 11$: MOV (R2)+,@R3; пословно, до тех пор,
192 BNE 11$ ; пока не перешлется ноль
193
194 MOV #OpnDir,-(R3); Подаем команду "Открыть
195 ; оглавление"
196
197 12$: TSTB @R3; и ждем, когда контроллер ее
198 BPL 12$; выполнит,
199 TST @R3; после чего проверяем на ошибку.
200 BMI Err10; Ошибка -->
201 ;.............................
202 {{/code}}
203
204 == **004: Монтировать диск** ==
205
206 Порядок действий:
207 • Сбросить контроллер
208 • Переслать в контроллер строку с записью, подобной строкам описания дисков в файле AZ.INI
209 • Выдать команду "Монтировать диск"
210 • Дождаться ее окончания (команда длительная)
211 • Проверить на ошибки
212 На выбранный накопитель AZnn НЕ ДОЛЖЕН быть смонтирован диск. Если он таки смонтирован, перед монтированием туда нового диска следует размонтировать старый - команда 014
213
214
215 Пример программы:
216
217 {{code language="assembler"}}
218 ;..................
219 AZMNT = 004
220 MDLEN = MDEND-MDTXT+2
221
222 MOV #AZ$CSR,R3
223
224 20$: CLR @R3;
225 TSTB @R3; Сбросим контроллер
226 BPL 20$;
227
228 MOV #WrBuf,(R3)+; Перешлем в него строку
229 MOV #MDTXT,R2; с командой назначения
230 MOV #MDLEN/2,R1;
231 21$: MOV (R2)+,@R3;
232 SOB R1,21$;
233
234 MOV #AZMNT,-(R3); и отдадим ее на
235 22$: TSTB @R3 ; исполнение
236 BPL 22$ ;
237
238 TST @R3; после чего проверим на ошибку
239 BMI Err11;
240 ;.........................
241
242 MDTXT: .ASCII "D04=0:/DISKS/SYSTEM/51SYS_DS.DSK"
243 MDEND: .BYTE 0,0
244 ;..................
245 {{/code}}
246
247 В этом фрагменте на диск AZ4 монтируется файл-образ 51SYS_DS.DSK, лежащий в папке SYSTEM, которая лежит в папке DISKS, лежащей в корневом оглавлении карточки микро-SD.
248
249
250 == **005: Чтение блока в буфер** ==
251
252 У контроллера имеется встроенный буфер на 256 слов (512 байт). Фактически, это часть оперативной памяти микроконтроллера STM32, выделенная в его программе под этот буфер. Весь обмен с Micro-SD идет через этот буфер.
253 \\Память дисков AZ представлена, как набор блоков объемом 512 байт каждый. Такой блок - единственная доступная единица для обмена данными с дисками AZ. Блоки пронумерованы от нуля до 65533 для 16-разрядного варианта или до 8388607 для 32-разрядного - это при использовании накопителей AZ максимально допустимой емкости. Никто не мешает использовать накопители меньшей емкости - фактический размер накопителя равен размеру файл-образа, смонтированного на этот накопитель. При попытке обратиться за пределы файл-образа будет зарегистрирована ошибка.
254 \\Команда 005 - чтение блока с микро-SD в буфер. С псевдодиска AZn, выбранного ранее командой "Выбор устройства" запускается на чтение блок, номер которого передан командой (командами) "Установка номера блока". Команда длительного действия.
255 \\Фактически, блок с карточки микро-SD читается, примерно, 500-800 мкс. На это время контроллер переходит в состояние, которое во время обсуждения проекта получило название "Думаю, прошу не мешать." А именно, на все время ее исполнения отключаются все регистры устройства, кроме CSR, в котором считывается ноль до тех пор, пока контроллер занят исполнением этой команды. По окончании считывания блока к МПИ подключаются остальные регистры контроллера, взводится бит D7 (готовность) в CSR и, если был установлен бит D6 (разрешение прерываний) в CSR, вырабатывается прерывание с вектором 0174.
256 \\Пример без прерываний тривиален:
257
258 {{code language="assembler"}}
259 ;...................................
260
261 CmdRea=005; символическое наименование команды "Читать
262 ; блок"
263
264 ; В R3 у нас от предыдущего фрагмента остался адрес CSR.
265 ; Пересылаем туда код команды чтения
266 MOV #CmdRea,@R3
267 2$: TSTB @R3 ; Проверим бит готовности
268 BPL 2$; Не готово -> уходим проверять еще
269 ; раз
270 TST @R3; Проверим на ошибку
271 BMI ERR4
272 ; Здесь у нас опять, в отличие от фрагментов пп. 3.1 и
273 ; 3.2, в R3 остался адрес CSR, а не DR.
274
275 ;...................................
276 {{/code}}
277
278
279 == **006: Записать блок из буфера на диск** ==
280
281 Код команды 006. Содержимое буфера пишется на выбранный псевдодиск по заданному дисковомк адресу (номеру блока). Перед записью выполняются проверки (1) "была ли запись в буфер?", если нет, выдается ошибка и (2) "заполнен ли буфер полностью?", если нет (для последнего укороченного блока файла), остаток буфера очищается нулями. Далее производится запись блока на носитель. Операция длительная, после ее запуска контроллер, как и при чтении переходит в состояние "Думаю, прошу не мешать". И так же, как и при чтении окончания этой операции надо дождаться, теми же средствами, как и при чтении.
282 \\Пример программы без прерываний:
283
284 {{code language="assembler"}}
285 ;...............................................................
286
287 CmdWri=006; символическое наименование команды "Писать
288 ; блок"
289
290 ; В R3 у нас от предыдущего фрагмента остался адрес DR.
291 ; Исправляем его на CSR и пересылаем туда код команды
292 ; записи
293 MOV #CmdWri,-(R3)
294 5$: TSTB @R3 ; Проверим бит готовности
295 BPL 5$; Не готово -> уходим проверять еще
296 ; раз
297 TST @R3; Проверим на ошибку
298 BMI ERR5
299
300 ;....................................................................
301 {{/code}}
302
303
304 == **007: Получить размер псевдодиска** ==
305
306 Есть две команды получения размера псевдодиска, т.е. смонтированного на выбранный псевдопривод AZn файл-образа.
307 \\Если используемая ОС (или программа, работающая с дисками без ОС) умеет работать с большими (больше 32М) дисками, следует пользоваться командой с кодом 017. Последовательность действий: сбросить контроллер (команда 000), выбрать накопитель (п. 3.2) и переслать в CSR код 017, а затем, без каких-либо ожиданий, считать из DR сначала младшее, и следом за ним старшее слово размера выбранного накопителя (файл-образа).
308 \\Если используемая ОС не умеет работать с дисками бОльшими, чем 32М (RT-11), следует пользоваться командой 007 - получить размер псевдодиска с ограничением до 32М. Действия похожие: сбрасываем контроллер, выбираем диск, посылаем в CSR код 007 и считываем из DR одно слово размера псевдодиска. Если размер файл-образа, смонтированного на выбранный псевдопривод, больше 65534 блоков, вместо этого "большого" размера, контроллер возвращает число 65534. Напоминаем, что число 65535 кое-где используется в специальных целях и не может быть размером диска.
309 \\Также напоминаем, что если на этот накопитель не смонтирован файл-образ, последовательность действий не пройдет (команда 001 выбор устройства) и исполнение программы до этого места просто не дойдет. Поэтому ошибок у этих команд не предусмотрено.
310
311 Пример программы с "малыми" дисками
312
313 {{code language="assembler"}}
314 ;......................................
315
316 GetSiz=007; Получить "малый" размер диска
317
318 ; От фрагмента 3.2 (выбор диска) у нас в R3 остался
319 ; адрес DR (177222)
320
321 MOV #GetSiz,-(R3); пошлем команду
322 TST (R3)+; вернем адрес в R3 назад, на DR
323 MOV @R3,DskSiz
324 ;......................................
325 {{/code}}
326
327 == **010: Разрешить работу сети** ==
328
329 Код команды 010. Закончив последовательность действий по передаче очередной порции данных, и ожидая, что следующий запрос последует не сразу же, можно "утилизировать" процессорное время микроконтроллера STM32, составляющего основу AZ - занять его обслуживанием сети. В той же RT-11 это можно сделать перед выходом из драйвера AZ, перед макрокомандой .DRFIN, завершающей исполнение запроса ввода-вывода.
330 \\Действительно, операция ввода-вывода завершена, программа ЦП в системе будет готовить новую порцию данных для вывода, или соображать (на основании предыдущих прочитанных данных), где ей еще что-то прочитать, или вообще размышлять о чем-то своём. [[image:https://forum.maxiol.com/style_emoticons/default/smile.gif||alt="smile.gif"]] Другими словами, после окончания запроса ввода-вывода, довольно высока вероятность того, что последует пауза в работе с дисками AZ. Вот, время этой паузы и можно отдать на обслуживание сети. Для этого, перед исполнением макрокоманды .DRFIN в RT-11 или ее аналога в других ОС следует отправить в CSR код 110 (разрешить сеть плюс разрешить прерывания).
331 \\Прерывание в этом случае не произойдет, оно активируется только по завершении "длительных" операций, которые переводят контроллер в состояние "Думаю, прошу не мешать", а установленный в "1" триггер разрешения прерываний, кроме этого, разрешает еще и работу сети, если она активирована. При запуске следующей операции ввода-вывода действия в п. 3.1 (сброс контроллера) сбросят и этот триггер, после чего программа обслуживания сети, обнаружив сброс этого триггера, прекратит (приостановит) свою работу и вернет управление основной программе обслуживания дисков AZ. Максимум, что можно заметить со стороны ЦП - это небольшая (10-20 мкс) задержка исполнения команды сброса, но это вполне умеренная плата за сетевые возможности.
332
333
334 == **011: Получить таблицу назначений приводов AZn** ==
335
336 Код команды 011. Получив эту команду, контроллер переключается с буфера для блока на свою внутреннюю таблицу назначений (32 строки по 140 байт каждая)* . Перед выдачей этой команды следует сбросить контроллер. После выдачи этой команды следует выдать команду 015 (чтение буфера), но в этом случае будет читаться не буфер, а та самая таблица, последовательно, слово за словом.
337 \\* начиная с версии v17, длина имени файла уже не 130 байт, а 386 байт (последнее слово - нулевое, для окончания строки)
338
339 [[**//пример утилиты AZSMNT//**>>url:https://forum.maxiol.com/index.php?s=&showtopic=5605&view=findpost&p=59420]]
340
341
342 Пример программы:
343
344 {{code language="assembler"}}
345 ;...................................
346 AZ$CSR = 177220; CSR контроллера
347 RdBuf = 012; Команда "Читать из памяти контроллера"
348 RdTbl = 011; Команда "Читать таблицу назначений"
349 TblSiz = 1120.; Длина таблицы в байтах (десятичная)
350
351 ; Считаем, что в R2 находится адрес первого слова
352 ; области памяти для таблицы назначений. Процедуру
353 ; получения этого адреса не показываем.
354
355 MOV #AZ$CSR,R3; Готовим CSR контроллера
356 10$: CLR @R3;
357 TSTB @R3; Сбросим контроллер
358 BPL 10$;
359
360 MOV #RdTbl,@R3; Команда "Передать
361 ; таблицу"
362
363 MOV #RdBuf,(R3+); Команда "Читать из
364 ; памяти контроллера. Одновременно передвинем адрес в R3
365 ; на DR контроллера (177222).
366
367 MOV #TblSiz/2,R1; Готовим счетчик слов
368
369 11$: MOV @R3,(R2)+; Перешлем текущее слово
370 SOB R1,11$; и повторим 560 раз
371 ;...................................
372 {{/code}}
373
374 == **012: Установка номера блока, старшие биты номера блока** ==
375
376 Контроллер предоставляет машинке с МПИ в качестве дисков AZ0 - AZ7 файл-образы типа DSK на карточке микро-SD. Размер этих файл-образов и, соответственно, псевдодисков, может быть любым, вплоть до 4Г каждый. Адресация на этих псевдодисках прямая - полученный по МПИ номер блока, после сдвига, используется в качестве смещения от начала соответствующего файл-образа. Фактически, это нечто, вроде LBA на PC.
377 \\Существуют операционные системы PDP-11, поддерживающие такие диски - RSX-11, ДИАМС, еще что-то. Однако, самая распространенная ОС - RT-11 - использует для номера блока СЛОВО (16 бит), причем код 0177777 кое-где используется в специальных целях и как размер диска не годится, поэтому для RT-11 могут быть использованы диски с максимальным числом блоков 0177776, т.е. 65534 блока (33553408 байт или 32767 К байт). Поэтому команды установки номера блока две: установить младшие биты номера блока - код 002 и установить старшие биты номера блока - код 012. Если номер блока помещается в 16 разрядов (для RT-11 - всегда), достаточно использовать команду установки младших битов номера блока, старшие биты при этом очищаются. Если номер не помещается в 16 разрядов, то сначала надо выдавать младшие биты, а потом старшие. Если попытаться сразу передать старшие биты без предварительной передачи младших, выдается ошибка. Если переданный адрес выходит за границу файл-образа, также выдается ошибка, не важно, на каком этапе - хоть при передаче младших 16 битов номера блока, хоть при передаче старших.
378 \\Для выполнения этих действий следует переслать требуемую часть битов номера блока в DR и затем переслать в CSR код команды, после чего следует проверить на ошибку. Команды мгновенные, т.е. выполняются за один цикл обращения по МПИ.
379
380
381 == **013: Прочитать запись оглавления HFS** ==
382
383 Код команды 013, команда читает запись оглавления во внутреннюю область памяти и переключает на нее указатель для передачи данных через DR. Оглавление перед этим должно быть открыто. Порядок действий следующий:
384 • Сбросить контроллер.
385 • Выдать в CSR команду "Прочитать запись оглавления" и дождаться ее окончания.
386 • Выдать в CSR команду "Прочитать из памяти контроллера"
387 • Прочитать из DR 11 слов записи оглавления
388 \\Запись оглавления имеет формат:
389 \\См. Имя Значение
390 0 fSize Размер файла в байтах, младшее слово
391 2 старшее слово
392 4 fDate Дата в формате MS-DOS
393 6 fTime Время в формате MS-DOS
394 10 fAttr Атрибуты 1 байт
395 11 fName ИМЯ.ТИП файла, 8+1+3+1 = 13 байт
396 \\Смещения указаны восьмеричные. Формула в строке fName означает, что там сначала должно быть имя, максимально из восьми символов, далее должна быть точка, далее тип, до трёх символов, и завершающий нулевой байт 0х00. Если тип не указан, точка тоже не нужна.
397 \\Атрибуты файлов в байте fAttr (восьмеричные):
398 \\001 - Read Only
399 002 - Hidden
400 004 - System
401 020 - Directory
402 040 - Archive
403 \\Пример программы.
404
405 {{code language="assembler"}}
406 ;......................................
407 RdDir = 013; код команды "Читать запись оглавления"
408 RdBuf = 015
409
410 MOV #AZ$CSR,R3
411
412 15$: CLR @R3;
413 TSTB @R3; Сбросим контроллер
414 BPL 15$;
415
416 MOV #RdDir,@R3; Попросим контроллер
417 16$: TSTB @R3; прочитать в свою память
418 BPL 16$; запись оглавления
419
420 MOV @RdBuf,(R3)+;
421 MOV DIRREC,R2; И перенесем ее к себе в
422 MOV #11.,R1; область памяти, указатель
423 17$: MOV @R3,(R2)+; на которую лежит в ячейке
424 SOB R1,17$; DIRREC.
425
426 ;......................................
427 {{/code}}
428
429
430 == **014: Размонтировать диск** ==
431
432 Код команды 014, чтобы размонтировать диск, следует сбросить контроллер, переслать в DR контроллера номер привода AZ, который следует размонтировать, и послать в CSR контроллера код 014, после чего дождаться окончания операции (она длительная) и проверить на ошибку. Ошибка выдается, если привод не был смонтирован.
433 [[**//пример утилиты AZUMNT//**>>url:https://forum.maxiol.com/index.php?showtopic=5605&st=0&p=59418&#entry59418]]
434
435
436 == **015: Начать передачу считанного блока** ==
437
438 Код команды - 015. Получив эту команду, контроллер настраивается на пословную выдачу содержимого того самого встроенного буфера на 256 слов, которые будут выданы последовательно через регистр DR. Никаких ожиданий не требуется, просто пересылаем 256 раз слово из DR в последовательные ячейки памяти, и все. Если нужно меньше, чем 256 слов (последний укороченный блок файла), то остаток можно просто бросить, не считывая, сброс контроллера в начале следующей операции сбросит и этот остаток.
439 \\Пример программы:
440
441 {{code language="assembler"}}
442 ;..................................
443 RdBuf=015; символическое наименование команды
444
445 ; В R3 от предыдущего фрагмента остался адрес CSR
446 ; (177220)
447
448 ; Считаем, что у нас в R2 находится адрес первого слова
449 ; памяти, куда следует разместить прочитанный блок.
450 ; Программа получения этого адреса не приводится.
451
452 MOV #400,R1; Готовим счетчик слов
453 ; 0400 oct = 256 dec
454
455 MOV #RdBuf,(R3)+; и пересылаем команду
456 ; RdBuf в CSR. Адрес в R3 укажет на DR (177222).
457
458 3$: MOV @R3,(R2)+;перешлем очередное слово в
459 ; память
460 SOB R1,3$; и повторим это 256 (0400)
461 ; раз
462 ;..................................
463 {{/code}}
464
465 Всё, чтение закончено.
466 \\Для записи наоборот, требуется сначала перенести весь блок данных из памяти ЦП в контроллер и потом выдать команду "Записать содержимое буфера на диск"
467
468
469 == **016: Принять блок данных в буфер** ==
470
471 Код команды 016. Команда настраивает контроллер на прием блока данных и помещении его в буфер. Следующие 256 циклов записи в DR поместят данные, переданные через МПИ, в буфер.
472 \\Пример программы.
473
474 {{code language="assembler"}}
475 ;..................................
476
477 WrBuf=016; Символическое наименование команды
478
479 ; Перед записью нужно выполнить те же действия, что и в
480 ; пп. 3.1.-3.3. Обычно, это одна и та же программа,
481 ; просто после пункта 3.3. выполняется проверка "Что
482 ; требуется: чтение или запись?" и разветвление на
483 ; программу чтения или записи.
484
485 ; После фрагмента в п. 3.3. в R3 остался адрес CSR
486 ; (177220). Будем считать, что в R2 находится адрес в
487 ; памяти ЦП, где находится блок, подлежащий записи.
488 ; Программа получения этого адреса не показана.
489
490 MOV #400,R1; Готовим счетчик
491
492 MOV #WrBuf,(R3)+; Перешлем команду в CSR и
493 ; переключим адрес в R3 на
494 ; DR
495
496 4$: MOV (R2)+,@R3; Перешлем очередное слово
497 ; данных
498 SOB R1,4$; и повторим это 256 раз
499 ;..................................
500 {{/code}}
501
502 == **017: Получить размер псевдодиска, большой** ==
503
504 Есть две команды получения размера псевдодиска, т.е. смонтированного на выбранный псевдопривод AZn файл-образа.
505 \\Если используемая ОС (или программа, работающая с дисками без ОС) умеет работать с большими (больше 32М) дисками, следует пользоваться командой с кодом 017. Последовательность действий: сбросить контроллер (п. 3.1), выбрать накопитель (п. 3.2) и переслать в CSR код 017, а затем, без каких-либо ожиданий, считать из DR сначала младшее, и следом за ним старшее слово размера выбранного накопителя (файл-образа).
506 \\Если используемая ОС не умеет работать с дисками бОльшими, чем 32М (RT-11), следует пользоваться командой 007 - получить размер псевдодиска с ограничением до 32М. Действия похожие: сбрасываем контроллер, выбираем диск, посылаем в CSR код 007 и считываем из DR одно слово размера псевдодиска. Если размер файл-образа, смонтированного на выбранный псевдопривод, больше 65534 блоков, вместо этого "большого" размера, контроллер возвращает число 65534. Напоминаем, что число 65535 кое-где используется в специальных целях и не может быть размером диска.
507 \\Также напоминаем, что если на этот накопитель не смонтирован файл-образ, последовательность действий не пройдет (команда 001 выбор устройства) и исполнение программы до этого места просто не дойдет. Поэтому ошибок у этих команд не предусмотрено.
508 \\Пример программы с большими дисками
509
510 {{code language="assembler"}}
511 ;......................................
512
513 GetBig=017; Получить "большой" размер диска
514
515 ; От фрагмента 3.2 (выбор диска) у нас в R3 остался
516 ; адрес DR (177222)
517
518 MOV #GetBig,-(R3); пошлем команду
519 TST (R3)+; вернем адрес в R3 назад, на DR
520 MOV @R3,BigSiz
521 MOV @R3,BigSiz+2
522 ;......................................
523 {{/code}}
524
525
526 == **020: Получить расширенный код диагностики** ==
527
528 Код команды 020, после сброса контроллера следует выдать эту команду в CSR и затем прочитать два слова расширенной диагностики из DR. Команда мгновенная, ожидание не требуется.
529
530
531 == **027**: Получить версию firmware AZ STM32 ==
532
533
534 Код команды 027, возвращает 2 слова
535 \\первое слово - 06404 = старший байт 13. это версия прошивки, младший байт 4. это версия железа - те AZБК в данном случае
536 второе слово - 037 = это максимальный монтируемый диск - 31.
537
538
539 {{code language="assembler"}}
540 ;-------------------------------------------------------------
541 ; получение версии прошивки STM32 - результат в R1 R1=0 ошибка
542 GTSTMV: MOV #AZ$CSR,R1
543 1$: CLR (R1) ; Пошлем команду "Сброс"
544 TSTB (R1) ; Проверим готовность контроллера
545 BPL 1$ ; Если не готов, сбрасываем еще
546 mov #27,(R1)
547 TST (R1)+ ; Проверяем на ошибку
548 BMI 2$
549 mov (R1),R1
550 return
551 2$: CLR R1
552 return
553 ;-------------------------------------------------------------
554 {{/code}}
555
556
557 == **030:  Нет операции** ==
558
559 Основное назначение этой команды - устанавливать бит разрешения прерываний от контроллера. Команда передает бит разрешения прерывания, который находится с ней в одном слове, но не входит в ее состав (напоминаем, команда располагается в битах D0 - D5, а бит разрешения прерываний - D6), в соответствующий триггер контроллера и больше никак не влияет на процессы в контроллере. Управление этим триггером работает даже в состоянии "Думаю, прошу не мешать", и это главная особенность команды "нет операции".
560 \\Команда имеет код 0030. Посылка в CSR кода 0130 разрешит прерывания от контроллера, посылка кода 0030 запретит их. Пример не приводится вследствие тривиальности его.
561
562
563 Пример программы
564
565 = **Блок команд работы с энергонезависимой памятью** =
566
567 Интерфейс предоставляет любому AZ-контроллеру доступ к 255 словам энергонезависимой памяти, все команды устанавливают бит готовности по завершению. Это позволяет сохранять пользовательские настройки в энергонезависимой памяти, к примеру это используется в AZБК - там сохраняются настройки для более комфортной работы контроллера.
568
569 Все команды этого блока используют буфер энергонезависимой памяти для своей работы.
570
571 == **021: Cчитать блок энергонезависимой памяти в буфер энергонезависимой памяти** ==
572
573 (% class="wikigeneratedid" %)
574 Код команды 021, данная команда вызывает чтение блока энергонезависимой памяти в буфер энергонезависимой памяти.
575
576 == ==
577
578 == **022: Отдать на шину считанный блок энергонезависимой памяти из буфера энергонезависимой памяти** ==
579
580 (% class="wikigeneratedid" %)
581 Код команды 022, данная команда обеспечивает передачу буфера энергонезависимой памяти в регистр DR для считывания.
582
583 (% class="wikigeneratedid" %)
584 Пример программы
585
586 {{code language="assembler"}}
587 AZ$CSR = 177220; регистр команд и состояния (CSR)
588 AZ$DR = 177222; регистр данных (DR)
589
590
591 ; trap 50 - cброс AZ
592 ; результат в R1 =0 ok
593 AZreset: MOV #AZ$CSR,R1
594 1$: CLR (R1); Пошлем команду "Сброс"
595 TSTB (R1); Проверим готовность контроллера
596 BPL 1$; Если не готов, сбрасываем еще
597 ; раз и проверяем снова
598 TST (R1); Проверим на ошибку,
599 BMI 0ERR$
600 CLR R1
601 return
602 0ERR$: CLR R1
603 COM R1
604 return
605
606
607 ; trap 54 - чтение энергонезависимой памяти блока 1 EEPROM в буфер с адреса ADREEPROMMEM
608 ; результат R3 - адрес, если R3=0 ошибка
609 ; статус чтения в R1 0 - ok
610 ; 1 - размер не соответствует сохраненному
611 ; 2 - oшибка версии
612 ; 3 - oшибка контрольной суммы
613 ReadEEPROM: push R2
614 call AZreset; сбросим
615 tst R1
616 bne 0ERR$
617 ; теперь читаем
618 MOV #AZ$CSR,R1
619 mov #21,(R1); считать блок 1 энергонезависимой памяти в буфер
620 0$: TSTB (R1); проверяем результат выполнения
621 BPL 0$; ждем
622 mov #22,(R1); отдать на шину считанный блок энергонезависимой памяти из буфера
623 1$: TSTB (R1); проверяем результат выполнения
624 BPL 1$; ждем
625 TST (R1)+; инкрементируем
626 mov #ADREEPROMMEM,R3
627 mov #256.,R2; читаем 256. слов; первое слово - результат чтения
628 2$: mov (R1),(R3)+; читаем блок слов в память
629 sob R2,2$
630 mov #ADREEPROMMEM,R3; успешно
631 mov (R3),R1
632 br 0END$
633 0ERR$: CLR R3
634 0END$: pop R2
635 return
636 {{/code}}
637
638 очевидно, после считывания памяти необходимо проверить код результата в первом слове - см расшифровку кодов ошибок
639 \\Примеры возвращаемых данных по командам
640 \\последовательная подача команды 021 и затем 022 позволит считать 256. слов
641 из энергонезависимой памяти
642 первое слово это будет статус успешности чтения
643 коды ошибок
644 ~; 0 - ok
645 ~; 1 - размер не соответствует сохраненному
646 ~; 2 - oшибка версии
647 ~; 3 - oшибка контрольной суммы
648 \\
649
650 == **023: Принять с шины в буфер данные для последующей записи в буфер** ==
651
652 Код команды 023, данная команда позволяет наполнить буфер энергонезависимой памяти
653
654 == **024: Записать из буфера энергонезависимой памяти в блок энергонезависимой памяти** ==
655
656 Код команды 024, данная команда вызывает запись блока энергонезависимой памяти из буфера энергонезависимой памяти.
657
658 Пример программы
659
660 {{code language="assembler"}}
661 AZ$CSR = 177220; регистр команд и состояния (CSR)
662 AZ$DR = 177222; регистр данных (DR)
663
664
665 ; trap 50 - cброс AZ
666 ; результат в R1 =0 ok
667 AZreset: MOV #AZ$CSR,R1
668 1$: CLR (R1); Пошлем команду "Сброс"
669 TSTB (R1); Проверим готовность контроллера
670 BPL 1$; Если не готов, сбрасываем еще
671 ; раз и проверяем снова
672 TST (R1); Проверим на ошибку,
673 BMI 0ERR$
674 CLR R1
675 return
676 0ERR$: CLR R1
677 COM R1
678 return
679
680 ; trap 55 - запись энергонезависимой памяти из буфера с адреса ADREEPROMMEM в блок 1 EEPROM
681 WriteEEPROM: push R1
682 push R2
683 push R3
684 call AZreset; сбросим
685 tst R1
686 bne 0ERR$
687
688 MOV #AZ$CSR,R1
689 mov #23,(R1); командуем что будем писать данные в буфер
690 0$: TSTB (R1); проверяем результат выполнения
691 BPL 0$; ждем
692 TST (R1)+; инкрементируем
693 mov #ADREEPROMMEM+2,R3
694 mov #255.,R2; пишем 255. слов; первое слово пропускаем - результат чтения
695 1$: mov (R3)+,(R1); отдаем в контроллер
696 sob R2,1$
697 tst -(R1); декрементируем
698 mov #24,(R1); записать из буфера в блок 1 энергонезависимой памяти
699 2$: TSTB (R1); проверяем результат выполнения
700 BPL 2$; ждем
701 br 0END$
702 0ERR$: CLR R3
703 0END$: pop R3
704 pop R2
705 pop R1
706 return
707 {{/code}}
708
709 **Обращаю внимание**, при записи, буфер идет сразу с данными, те нет первого слова со статусом.
710
711
712
713