Доступ к периферийным регистрам из Паскаля
Jun. 3rd, 2019 04:16 pmСейчас к периферийным регистрам можно обращаться из Паскаля через указатели. К примеру, код:
Есть более эффективный способ, если чуть улучшить линкер в юниксном стиле. Объявляем внешнюю структуру, которая по адресам сооветствует расположению периферийных регистров. Обращение к полям этой структуры будет превращаться в чтение/запись регистров. При этом будет использоваться команда UTC, чуть более эффективная, и не нужна дополнительная память на указатели. Пример:
program test();превращается в:
var
src, dst: @integer;
begin
src := ptr(77755B);
dst := ptr(77756B);
repeat
dst@ := src@
until false;
end.
c2: 10 010 0000 xta (8) ; =77755
01 000 0050 atx 050(1) ; src
c3: 10 010 0001 xta 1(8) ; =77756
01 000 0051 atx 051(1) ; dst
c4: 01 23 00050 wtc 050(1) ; src@
00 010 0000 xta
c5: 01 23 00051 wtc 051(1) ; dst@
00 000 0000 atx
c6: 00 30 00004 uj 4
00 22 00000 utc
Команда WTC выполняет косвенное обращение к периферийному регистру через указатель. При этом нужно выделять память на указатели.Есть более эффективный способ, если чуть улучшить линкер в юниксном стиле. Объявляем внешнюю структуру, которая по адресам сооветствует расположению периферийных регистров. Обращение к полям этой структуры будет превращаться в чтение/запись регистров. При этом будет использоваться команда UTC, чуть более эффективная, и не нужна дополнительная память на указатели. Пример:
program test(gpio);Результат:
var
gpio: record { периферийные регистры блока GPIO }
unused0, { 77750 - на будущее }
unused1, { 77751 }
unused2, { 77752 }
unused3, { 77753 }
CNEN, { 77754 - маска отслеживаемых пинов }
CNIE, { 77755 - вкл. прерывание по изменению сигнала }
PORT, { 77756 - запись - выдача, чтение - прием }
TRIS: integer { 77757 - направление данных }
end;
begin
repeat
gpio.PORT := gpio.CNIE
until false;
end.
c2: 00 22 77750 utc 77750
00 010 0005 xta 5 ; gpio.CNIE
c3: 00 22 77750 utc 77750
00 000 0006 atx 6 ; gpio.PORT
c4: 00 30 00002 uj 2
00 22 00000 utc
Надо только научить линкер привязывать внешние common-блоки к фиксированным адресам, но это нетрудно.
no subject
Date: 2019-06-05 04:41 pm (UTC)При достижении конца программы, она перезапускается.
С ком-портом нормально, а вот для vga нужны битовые операции, а с ними какие-то странности.
Пользуюсь тем хитрым типом union
type union = record case integer of 0: (i:integer); 1: (s:set of 0..47) end;Вот такой процедурой пытаюсь выдать точку:
procedure plot_xy(x,y: integer); var addr, bit: integer; pix: union; begin addr := (x div 8) + 40 * y; bit := 40 + x mod 8; vga_al@ := addr; pix.i := vga_data@; pix.s := pix.s + [bit]; vga_al@ := addr; vga_data@ := pix.i; end;Но ставятся биты как-то странно, с "дырками" когда перебираешь x от 0 до 7.
Завтра буду смотреть внимательно еще раз.
В первом приближении показалось, что при определенных вызовах этой процедуры из разных мест кода (из цикла, не из цикла, из под условия) как-то целые аргументы портятся. Буду изучать.
no subject
Date: 2019-06-06 05:05 am (UTC)вот такое выражение считается неправильно, где bit и x integer
bit := 40 + (x mod 8);
Причем bit := x mod 8;
no subject
Date: 2019-06-06 09:38 am (UTC)Дело в том, что у целых чисел в экспоненте стоит всегда 064 (в старших разрядах), поэтому в этом выражении:
bit := 40 + (x mod 8)
когда X приходил из ком-порта в старших разрядах был 0-лик до той поры пока к нему не применить операцию сложения или вычитания. Как применишь так в ответе мусор.
Любопытно что операции умножения эти биты не трогают.
Переделал немного UART чтобы при чтении байта читалось 064 в старших разрядах а принтяй байт в младших и все сразу же заработало.
Из питона посылаются случайные координаты:
Там где линии алгоритм Брезенхейма (точнее его частный случай, но на Паскале)
Пример №1 https://youtu.be/1qtg4VCXjYU
Пример №2 https://youtu.be/62jhjpRayWc
Любопытно, но похоже в нашем Паскале нет "else".
no subject
Date: 2019-06-06 09:28 pm (UTC)В Паскале if-else есть, как же без него. Только перед else нельзя ставить точку с запятой.
no subject
Date: 2019-06-07 03:34 am (UTC)plotLine(x0,y0, x1,y1) if abs(y1 - y0) < abs(x1 - x0) if x0 > x1 plotLineLow(x1, y1, x0, y0) else plotLineLow(x0, y0, x1, y1) end if else if y0 > y1 plotLineHigh(x1, y1, x0, y0) else plotLineHigh(x0, y0, x1, y1) end if end ifи сходу не получилось... ну это ладно попробую еще раз.
Добавление 064 можно избежать, если сделать например на мадлене те самые peek/poke c AOX , а на оборудовании не использовать биты с 40 по 48-й.
no subject
Date: 2019-06-07 04:57 am (UTC)procedure pltln(x0, y0, x1, y1: integer); begin if abs(y1 - y0) < abs(x1 - x0) then if x0 > x1 then pltlo(x1, y1, x0, y0) else pltlo(x0, y0, x1, y1) else if y0 > y1 then plthi(x1, y1, x0, y0) else plthi(x0, y0, x1, y1) end;no subject
Date: 2019-06-07 05:05 am (UTC)Как можно инициализировать массив:
Ошибку выдает.
Error 103: Required token not found: SEMICOLON
00001 23 1 data: array[0..9] of integer = (10,20,30,40,50,60,71,80,90,91);
^^^^^ 0
IN 216 LINES 1 ERRORS
no subject
Date: 2019-06-07 06:14 am (UTC)Вот так:
program test(output); var data: array[0..9] of integer; begin writeln(data[0], data[1], data[2], data[3], data[9]); end.data data[0] = 10; data[1] = 20; data[2] = 30; data[3] = 40; data[4] = 50; data[5] = 60; data[6] = 71; data[7] = 80; data[8] = 90; data[9] = 91; endno subject
Date: 2019-06-07 06:16 am (UTC)no subject
Date: 2019-06-07 06:21 am (UTC)https://github.com/besm6/mesm6/blob/master/toolchain/pascompl/test/pascompl/pascompl.pas#L8555