Ретро-компьютер (BASIC) на STM32

UPDATE:

PC приложение (под Линукс):
PC

OK после операций с SD картой:
loadOKsaveOKUPDATE:
Работа с SD-картой:

UPDATE:
Работают SAVE и LOAD Бейсик-программ на SD-карточку. Ниже скриншоты загрузки программы TEST.BAS и трассировка запуска из тестовой UART-консоли:
LOADtraces

Еще около 8000 байт во флеш-памяти для разных улучшалок прошивки:

** Programming Finished **
** Verify Started **
...
verified 55744 bytes in 0.836388s (65.086 KiB/s)
** Verified OK **
** Resetting Target **

TODO список:

  1. Изменение названия Stm32BASIC на stm32f1BASIC Done
  2. Рефакторинг кода Done
  3. Поддержка SD карточки Done
  4. Скроллинг программы кнопками курсора
  5. Выкладывание проекта в Гитхаб
  6. Разработка печатной платы и заказ первой партии плат

--------------------------------- Далее архив -------------------------------

UPDATE:
Подзаточил код stm32BASIC до состояния работы с клавиатурой PS2:

UPDATE:
Кнопочная клавиатура работает. На очереди - SD-карточка
stm32 basic
Прогнал тест 8-ферзей на Бейсике, который, напомню, на Arduino-Nano занял 3.4 секунды. Результат на stm32f1: 0.8 секунды или примерно в 10 раз быстрее МК161 (измерял ручным секундомером, не timestamps). Далее под катом старый текст про NodeMCU.

==========================================================
Cей эксперимент задвинут в дальний ящик из-за своеобразного подхода архитектуры esp8266 к работе с памятью. Разбираться, как выравнивать работу с данными разной размерности в памяти мне лень.

Архив --------------------------------------------
Попробовал сбилдить Ардуино-Васик под сабж (в конфигурации Serial Terminal Input), выделив под Васик 32Кб.

nodemcu-basic
Выглядит многообещающе:

Sketch uses 268212 bytes (25%) of program storage space. Maximum is 1044464 bytes.
Global variables use 67280 bytes (82%) of dynamic memory, 
    leaving 14640 bytes for local variables. Maximum is 81920 bytes

В общем, надо I2C подзапилить и подключить к дисплею.

UPDATE: Навскидку дисплей от NodeMCU не заработал. Скорее всего, проблема в 3в питании - дисплею надо 5. Либо NodeMCU у меня проблемная, доберусь до осцилла, проверю

UPDATE_2: Дисплей подключился (таки надо 5 вольт ему), Васик стартовал:

Однако при попытке ввести строку Васика с сериал терминала 8266 выпадает в exception:

Fatal exception 9(LoadStoreAlignmentCause):
epc1=0x402036f8, epc2=0x00000000, epc3=0x00000000, excvaddr=0x3ffeef3d, depc=0x00000000

Exception (9):
epc1=0x402036f8 epc2=0x00000000 epc3=0x00000000 excvaddr=0x3ffeef3d depc=0x00000000

ctx: cont
sp: 3fff04e0 end: 3fff0700 offset: 01a0

>>>stack>>>
3fff0680:  0000001f 3ffef438 3fff0e14 402036e0 
3fff0690:  40100031 3ffef3f0 00000000 3ffef3fc 
3fff06a0:  00000031 3ffef3f0 00000028 40205556 
3fff06b0:  00000001 3ffef6d8 40205fb8 3ffef6d8 
3fff06c0:  3fffdad0 00000000 3ffeef38 40203943 
3fff06d0:  3fffdad0 00000000 3ffeef38 40202706 
3fff06e0:  feefeffe feefeffe 3ffef6d0 40206004 
3fff06f0:  feefeffe feefeffe 3ffef6e0 40100108 
<<
Метки публикаций: 

Комментарии

Там же Lua и MicroPython есть. Хотя если нужны BCD операции,
библиотека то уже готовая есть для C++, то может стоит встроить в бейсик

Бейсик чтобы вот. Если мне нужен был бы Питон, я взял бы Распберри Пи Зиро. Тот же размер платы.

Из-за чего такой эксепшн может быть?

Общение с последовательным портом барахлит? Там может быть что-то, зависящее от железки. А Бейсик же универсальный, железки пока не знает.

Можно отладить свой терминал и сравнить с тем, как это делает Бейсик.

Для esp8266 в ардуину написали неплохой декодер exceptions.

Paste your stack trace hereException (9):
...
Exception 9: LoadStoreAlignmentCause: Load or store to an unaligned address
PC: 0x402034d0: nextToken() at /tmp/arduino_build_375645/sketch/basic.cpp line 804
EXCVADDR: 0x3ffeed9a

Проблема, похоже, связана с архитектурой esp8266:

The ESP8266 has limitations on accessing data through a pointer. Namely, 32 bit accesses need to be aligned on a 32 bit boundary, and 16 bit boundaries for a 16 bit access. If the lowest 2 bits of ptr (the actual address) are not zeroes, you get Exception (9).

Придётся, как с предыдущей архитектурой, писать свои функции по чтению и записи из памяти. Раз это C++, можно попробовать перегрузить операции. Но можно ещё изучить компилятор. Возможно, там уже есть опция для эмуляции отсутствия выравнивания.

но мне неохота ковыряться с этим. Переползаю на stm32.

Может проще соорудить транслятор в Lua ?

Если вы хорошо разбираетесь в lua или другом языке — пишите Бейсик на нём, никто не мешает.

Традиционно Бейсики писались на ассемблере, экономя ресурсы целевой системы. Позже стала востребована переносимость, Бейсики стали писать на Си. Видимо из-за того, что богатая AT&T сильнее распиарила юниксный подход к переносимости, чем Чак Мур фортовский.

Но если программист хорошо знает и свой инструмент, и Бейсик, написать транслятор для него относительно просто. Сложнее программиста мотивировать на работу, при этом её не оплатив — мечта класса эксплуататоров. :-)

...что кому то надо вас эксплуатировать. Начните лучше с простой и очевидной мысли, что бейсик на ESP нафиг никому не упёрся (как и Каллисто где либо), исключение составляют такие сообщества как наше, где люди просто радуют друг друга своими достижениями. Причём вообще заявления про эксплуатацию ? Напишете бейсик на Луа, а я им буду алчно пользоваться ? Вам не приходило в голову, что Луа гораздо лучше Бейсика ? :-)

Мыслите сами и говорите за себя, не-эксплуататор вы наш.

Уж большего любителя говорить за других, чем Вы, и не сыскать, скромный Вы наш !

Ну, за всех Вы уж тут не говорите. Есть несколько человек, которым Бейсик интересен, и один из них очень хочет, чтобы эксперимент Basic-Nano завершился полноценной печатной платой.

и зачем то повторяете практически слово в слово, то что я написал. Есть НЕСКОЛЬКО человек, которым Бейсик интересен, кроме НЕСКОЛЬКИХ человек, остальной массе людей оно не особо нужно (т.к. давно есть лучшие альтернативы). Это не умаляет ваших достижений, я лично восхищаюсь каждым вашим отчётом и сделанным устройством! И дай Бог чтобы оно вышло в серию, я бы тоже приобрёл как платформу :)

Прошу прощения :)

Бейсик это очень хороший язык для начального обучения, у меня есть даже бизнес идея по бейсику на мелком компе.

Договорились :)
Про бизнес-идею по Бейсику - кроме как конструктора для детских и школьных кружков, мне ничего в голову не приходит.

SD-карточка заработала на SPI порту 1:

Initializing SD card...Initialization done
SD card root directory:
SYSTEM~1/
	WPSETT~1.DAT		12
	INDEXE~1		76
README.TXT		142
Content of file "readme.txt":
readme.txt
------------------------
The GNU General Public License is a free,
copyleft license for software and other 
kinds of works.

Ok

Далее надо собрать в кучу с Бейсиком (придется код клавиатуры перенести на другие GPIO в свете занятости SPI)

А какая файловая система? FAT16/VFAT/FAT32? Много памяти ест?

Я на 0,5Мб диске МК-161 даже 25% ёмкости не добрал, а на SD карте кроме программ можно целую библиотеку книг хранить :) и читать их потом на ЖК-индикаторе :))

SD-карточка сейчас 4 Гб. Ардуино-библиотека стандартная, она поддерживает FAT16 и FAT32, но для экспериментов я форматировал карточку в FAТ16.

На stm32 немного косячно работает, по-сравнению с Ардуино-Нано (тут, к примеру, большая дискуссия). У меня заработало только тогда, когда я занизил скорость SPI шины:

SPI.setClockDivider(SPI_CLOCK_DIV32);

Я, кстати, забыл, почему в МК152-161 не поставили SD-карту, а сделали то, что сделали. В фирмвари места не было?

В узвмк не 256 байт/сектор, а 264, дополнительные 8 байт позволяют отказаться от таблиц разбиения файлов, хотя файлы каталогов остаются, это позволяет упростить файловую систему и машинные затраты на её обслуживание. Думаю, делали, как можно проще.

В бейсик-недокомпе 4Гб для хранения программ... как самолётный ангар для мопеда :) хотя, сейчас в продаже карт памяти менее 512Мб днём с огнём не сыщешь...

Лет 8 назад неиспользование карты SD в МК-161-/152 было мотивировано нежеланием вступать в соответстувующую ассоциацию производителей и платить за членство 1-2К долларов в год.

Понять тоже можно, с другой стороны

http://basic.mindteq.com/index.php?i=full
может пригодится

насколько я понял:

Числа:
Все числа являются знаковыми целыми в диапазоне -32767 до +32767.
Допускаются три формы записи чисел:
- десятичная;
- шестнадцатеричная, числа имеют префикс &H;
- двоичная, числа имеют префикс &B;

Тот, что сейчас в stm32, float

Смысла прикручивать что-то другое пока не вижу

Похоже, с Бейсиком и SD-картой не влезаю в stm32f103 (это просто подключена SD библиотека с файловой системой, функции чтения/записи еще не написаны):

Build options changed, rebuilding all
Archiving built core (caching) in: /tmp/arduino_cache_936452/core/core_stm32duino_STM32F1_genericSTM32F103C_device_variant_STM32F103C8,upload_method_STLinkMethod,cpu_speed_speed_72mhz,opt_osstd_0e82247e1de16792242aa34ad90b88f2.a
Sketch uses 65512 bytes (99%) of program storage space. Maximum is 65536 bytes.
Global variables use 13712 bytes (66%) of dynamic memory, leaving 6768 bytes for local variables. Maximum is 20480 bytes.

Может есть смысл заменить SD карту микросхемой SPI Flash, например 25-й серии есть кристаллы 4, 8 и 16 МБ?
Вот, статейка про микросхему из УЗВМК

в первую очередь для обмена файлами с компьютером.

Вообще, размер прошивки поражает (много чего тянется за собой в ардуинских библиотеках). Я думал, влезет в 64 КБ. Такие бы ресурсы (72 МГц, 64 КБ ПЗУ) да во времена "Спектрума"...

В общем, challenge accepted :) Либо переползу из Ардуины на чистый GCC и останусь на нынешней stm32 (20КБ ОЗУ, 64КБ флеш), либо переползу на cortexM3 помощнее (64KB ОЗУ 512KB флеш), платка рядом валяется без дела.

Чистота - залог здоровья. Голосую за переползание на чистый GCC, чтобы не тянуть за собой наследство.

Обязательно буду переползать на "чистый" GCC. Хотя бы ради памяти предков, которым 64 КБ ПЗУ показалось бы роскошью :)
Тут пример, как реализована ардуинская функция записи в GPIO digitalWrite(). Цитаты:

void digitalWrite(uint8_t pin, uint8_t val)
{
    uint8_t timer = digitalPinToTimer(pin);
    uint8_t bit = digitalPinToBitMask(pin);
    uint8_t port = digitalPinToPort(pin);
    volatile uint8_t *out;

    if (port == NOT_A_PIN) return;

    // If the pin that support PWM output, we need to turn it off
    // before doing a digital write.
    if (timer != NOT_ON_TIMER) turnOffPWM(timer);

    out = portOutputRegister(port);

    uint8_t oldSREG = SREG;
    cli();

    if (val == LOW) {
        *out &= ~bit;
    } else {
        *out |= bit;
    } 

    SREG = oldSREG;
}
The Arduino-generated file (Blink.cpp.hex) was 2,918 bytes. The Atmel Studio file (blink.hex) was only 508 bytes – nearly six times smaller

measured the digitalWrite() performance, and approximated it at 100 clock cycles – or more than 60 times slower that the direct port manipulation

Ардуино IDE и вся инфраструктура вокруг удобны, безусловно, но за удобства надо платить

Российская платка на миландрокортексе для выводов битов в порты использует штатную функцию GPIO_DigitalWrite(), которая выполняется за 0,5мкс (~40 команд), а внутри неё происходит проверка на обращение к несуществующим контактам, и в дальнейшем вызов функции GPIO_SET(), которая выполняется за 0,11 мкс (~9 команд) и выводит бит в порт. Чтобы не переделывать софт, можно повырезать из библиотек всё лишнее, например, из GPIO_DigitalWrite() вырезать всё, кроме вызова GPIO_SET().

Кстати, да, в NetBeans используется GCC с оптимизацией О2, который нагло режет пустые циклы.

Я именно так и собираюсь сделать - взять за основу ардуинские библиотеки, вытащить их в тот же каталалог проекта и вырезать все лишнее. Так я уже сделал с I2C LCD библиотекой, на очереди - GPIO, I2C и SPI.

На грани влезания прошивки в stm32f103 заработали команды SAVE "filename", LOAD "filename" (команда DIR еще в разработке):

1. Cохранить программу TEST1 в файл TEST1.BAS:

save1
2. Cохранить программу TEST2 в файл TEST2.BAS:

save2
3. Список файлов на SD-карточке:

.../4GB_SD$ ls -l
total 192
-rw-r--r-- 1 vitali vitali 142 huhti 28 22:04 readme.txt
-rw-r--r-- 1 vitali vitali  26 tammi  1  2000 TEST1.BAS
-rw-r--r-- 1 vitali vitali  26 tammi  1  2000 TEST2.BAS


4. Загрузить программу TEST1 из файла и запустить:

load1
5. Загрузить программу TEST2 из файла и запустить:

load2

Поздравляю! Отличная интеграция с компом.

Спасибо! Ну, при наличии SD-карточки со стандартной файловой системой интеграция с компом идет "из коробки" :)

Подумалось, что надо будет потом написать оффлайн-конвертер (хотя бы на Питоне) для декодирования файлов .BAS в читаемый текст, и обратно.

Во многих Бейсиках такой конвертор встроен в транслятор. Для получения текста, читаемого человеком, надо использовать команду SAVE "FILE",A

Да и неохота тратить драгоценную флеш-память прошивки на то, что можно сделать на компе

Дело в том, что нужный код в трансляторе уже есть. Это команда LIST с перенаправлением вывода в файл. Конечно, можно сделать такое перенаправрение на стороне десктопа.

Да, LIST команда есть, можно ее использовать для этих целей. Но Бейсик придется допилить немного, а сейчас это практически невозможно - места для прошивки осталось байт 100

Ведь на компе можно блокнот настроить на чтение *.BAS ну или написать какой-нибудь BAS2TXT.BAT, который будет выполнять команду REN *.BAS *.TXT :)

А второй скрипт будет конвертить .TXT в .BAS, если вдруг понадобится конвертировать листинг программы в файл на SD карточке

Это если Бейсик использует текстовый формат. Некоторые Бейсики просто скидывают на диск область памяти, где хранится программа. В этом случае ключевые слова, такие как PRINT, кодируются 1-2 байтами.

файл .BAS это просто "слепок" буфера памяти Бейсика. PC конвертор .BAS -> .TXT может парсить хидер-файл исходника Бейсика для того, чтобы всегда иметь последний список токенов.

В теории всё так. На практике там несколько подводных камней, вроде кодирования числовых и строковых констант. Если Бейсик компилируется под десктоп, может быть достаточно простого LOAD:LIST с переназначением вывода.

А это даже еще лучше вариант. PC хост у меня опробован в билде под Винду (под Линукс еще нет). Но это потом, второй или третий приоритет

обстоят перспективы :)

Настало время небольшого дисклаймера :) - сей эксперимент с Бейсиком на платке с экранчиком не планировался расти ни во что мобильное. Только железные кнопки с экраном, только хардкор :)

PC хост и тот только для того, чтобы сам Бейсик отлаживать было удобнее.

Но проект на Гитхабе, поэтому все, кто хочет поковырять - добро пожаловать.

Допилил клавиатурный тест Бейсик-железки на GCC. Разница в размерах прошивок между Arduino toolchain и GCC toolchain (на основе libopencm3 lowlevel Open-Source library for ARM cortex MCUs):

Arduino: 15528 байт

Sketch uses 15528 bytes (23%) of program storage space. Maximum is 65536 bytes.

GCC: 2092 байт

...Stm32Basic/kbd_test$ arm-none-eabi-size kbd_test.elf 
   text	   data	    bss	    dec	    hex	filename
   2076	     16	      0	   2092	    82c	kbd_test.elf

GCC прошивка меньше Ардуинской в 7.4 раза.

Поздравляю, я знал что ардуинокомпилятор плохо оптимизирует программу, но таких результатов я не ожидал! Думаю, ардуинокомпилятор сперва С++ портирует на Java, а его уже компилирует в машинный код.
Кстати, а как GCC по быстродействию по сравнении с ардуинокомпилятором? У меня выходило минимум в полтора раза, но я думаю тоже в разы быстрее работать будет.

Нет, в Ардуине не через java, там просто много чего подкдючено. Один Serial класс чего стоит.

Быстродействие интересно померять. Как только перенесу Бэйсик под GCC, прогоню 8 ферзей

Понемногу перепиливаю ардуинский I2C LCD драйвер на "чистый" С. Больше половины функционала уже работает (stm32 GCC toolchain).
Размер прошивки с драйвером дисплея пока радует (3024 байт):

&:~/GITprojects/Github/Stm32Basic/lcd_test$ arm-none-eabi-size lcd_test.elf 
   text	   data	    bss	    dec	    hex	filename
   3000	     12	     12	   3024	    bd0	lcd_test.elf

lcd driver

...
const char teststr[] = " Stm32Basic";
...
lcd_set_cursor(0, 0);
lcd_write_str("@0,0");
lcd_write_str(teststr);
lcd_set_cursor(1, 1);
lcd_write_str("@1,1");
lcd_write_str(teststr);   
lcd_set_cursor(2, 2);
lcd_write_str("@2,2");
lcd_write_str(teststr);     
lcd_set_cursor(3, 3);
lcd_write_str("@3,3");
lcd_write_str(teststr);

Бейсик переписался с "плюсов" на чистый Си. В процессе переписывания Бейсика допилил кроссплатформенный РС хост (проект под Code Blocks):
linwin

Это секунды или миллисекунды? Не думаешь допилить Бейсик, убрав номера срок и введя метки? :) Должно быть несложно, если транслятор толково написан.

Это секунды - сколько приложение проработало. Но это сам Code Blocks меряет.

Бейсик уже переписан из "плюсов" на чистый Си. На большее пока я не готов :) - и так надо допиливать - в "железяке" еще не работает.

И, опять же, ретро-фактор исчезнет, если убрать нумерацию :)

P.S. Хотя транслятор, в целом, написан неплохо. Вот причесанный "чистый Си" вариант (under construction). (Про фигурные скобки в однострочных условиях if(a < 0) a = 0; и циклах - мне нравится такой coding convention).

Spectrum-48 против пачки сигарет, каша из топора или что может STM32F103C8T6+video(update)
https://habr.com/post/412325/
Контроллер ускорен до 112 Мгц, Ресурс батарейки 50ч

P.S. Видео https://youtu.be/n4u6VNxCTdA

Давно уже время от времени всплывают обсуждения спектрума с ЖК экраном, оказывается сделали-таки! Можно спекбук собирать:) Идея видеопамять как своп на спектруме меня весьма удивила:) Миландровцы на опытах свои кортексы для счётчиков с 36МГц разгоняли до 90, так что ничего удивительного :) Интересно на нём Wolfenstein 2004 будет работать?

Заработала PS2 клавиатура.

Приехали ч/б 20х4 дисплеи с отражением. Это без подсветки, с настольной лампой:
BW, no backlight

А с этими ЖК индикаторами нет задержек в отображении символов? Смотрятся явно лучше старых синих :)

Не, тут все очень адекватно. И да, мне сильно больше такой экран нравится, по сравнению с синим

Шрифты намного лучше читаются. Хотя после МК-161 такие широкие точки и буква «i» выглядят очень необычно.

Конечно, моноширинные экраны программировать привычней. Мне пришлось многому переучиваться, делая Каллисто для пропорциональной командной строки. Но результат того стоит. Физический размер экрана ПМК крайне мал. Трюк с разной шириной символов позволяет втиснуть больше информации, причём с улучшением читаемости. Здесь я на стороне Новосибирска, хотя в 2007 принятое ими решение было не таким очевидным.

Если удастся закончить stm32f1BASIC. то я планирую перебраться с Бэйсиком на 320x240 графический экран, скорее всего на более мощный STM32F103RET6.

Только высота индикатора в два раза меньше и шрифт моноширинный. Ну и импорт, конечно.

Увы, не графический. А насчет импорта - вот у МЭЛТА почти один в один, это кто производит, "Ангстрем"? В нем прошит русский знакогенератор - это, конечно, плюс

Так и МК161 "идеологически не очень чистая", если про импорт :)

МК-161 — наиболее чистый русский ПМК, из современных. Отсутствие в «Электронике» более мощных финтифлюшек вполне объяснимо отсутствием русских аналогов. Сделать МК-161 ещё более чистокровным — от цен ещё сильней взвоем.

Альтернативы на Ардуино и других иностранных платках — значительно менее отечественные и вдохновляют меньше. Преимущества таких самоделок перед HP Prime обьяснить сложнее. Отечественностью пожертвовали, и всё равно рыночных высот не достигли.

Ну, если взять что-то вроде К1986ВЕ92QI и вышеупомянутый МЭЛТ дисплей, то stm32f1BASIC будет 100% отечественным. Или наличие "нерусского" ARM-GCC подточит чистоту? :)

Мне импортные системы команд не по нраву. Форт-процессор был бы круче.

Но музыку заказывает тот, кто платит. Если отечественные разрабочики решат использовать К1986ВЕ92QI, как им запретишь? Чтобы выпустить не маниловские замки, а готовый продукт, часто приходится идти на компромиссы.

Да, КБ145ВГ6 Ангстрем делает. А вот мэлтовские символьные ЖКИ с управлением по SPI уже с импортными кристаллами идут.

Заработали SAVE и LOAD на SD-карточку.

Почему-то нет Ok. Не видно, когда программа засэйвилась или загрузилась.

Добавил ОК в работу с SD картой.

Еще порядка 7900 байт во флеш-памяти остается для улучшалок:

verified 57560 bytes in 0.862142s (65.199 KiB/s)
** Verified OK **
** Resetting Target **

А что с русским языком? Знакогенератор, клавиатура… советую сделать кодировку, как в МК-161 (cp866). Может потом помочь с переносом Каллисто. Ну или Бейсика на МК-161, если прошивку вскроем.

Этот экран, что у меня, без русских символов в прошивке. Поэтому никак. МЭЛТ-овский экран покупать - дороговато и неудобно логистически.

Почему именно cp866, а не win1251?

Для совместимости с ЭКВМ.
Тема перенесена

При портировании своего проекта Terminal-BASIC на esp8266 я также столкнулся с проблемой повсеместного невыровненного доступа к памяти, которую и решил в последних версиях.
Также пытаюсь сделать на нём калькулятор: Terminal-BASIC programmable calculator

Он не такой компактный, как TinyBASIC или Arduino BASIC, но главная особенность - практически полная поддержка стандарта Minimal BASIC, что уже позволяет запускать много сложных программ из старых книг, а также поддержка матричных операций, как в Darthmouth BASIC.

А на чем Termimal-Basic калькулятор сделан - на esp8266?

Прототип железа, который на hackaday.io в блоге сфотографирован делает парень с ником ptrav.
Он планирует использовать esp32.

Сам я не очень силён в прототипировании железа и планировал использоватть ArduinoDUE с экраном 320x480
ввиде шилда для ArduinoMEGA/ArduinoDUE. Эта платформа (DUE+TFT32x480+SD) очень хорошо работает и протестирована с TB. Не хватает только клавиатуры.

Последние версии Terminal-BASIC работают как на esp8266, так и на esp32.
На них пока нет поддержки SD-карт, она сделана через Arduino-библиотеку SD и её PC эмулятор уровня API,
поэтому сохранение/загрузка программ из внешней памяти работает только на Arduino AVR8 и на ArduinoDUE, а также на Linux-версии.