STM8 встречает Интернет


В целом ничего нового тут не ожидается. Уже всем знакомое семейство STM8 в качестве мозга. ENC28J60 в качестве Ethernet контроллера и PHY. И немного модифицированный код от Lifelover’а в качестве примера.
Тов. Lifelover’у ещё раз огромное спасибо за его труды.


Вода-вода

Решил таки в коем то веке помучить Ethernet на контроллерах. Но LPC1768 я не увлекаюсь, а в LPC1343 Ethernet’а и нету. И так выбор пал на купленную с год назад плату с ENC28J60. В качестве ядра же было решено задействовать дешёвый (35р. на момент покупки) контроллер STM8S103F3 (есть и портированная на STM8S-Discovery версия). Ну а в качестве среды разработки у нас выступает бесплатная версия IAR, имеющая ограничение в 8кБайт кода (это важно, запомните это).
Задачей было собрать некое подобие tinyhttp, но так как последний был написан на ассемблере, в основу лег пример webif2. Главным условием было использование языка Си, для возможности легкой переделки проекта. Главной целью – освоить SPI микроконтроллеров STM8.
Надо заметить что SPI не вызвал совершенно никаких сложностей, в отличие от запуска ENC’и. Ну кто же ожидал что Си код окажется не универсальным, отвык я уже от граблей, привык к рабочим библиотекам. Странно только откуда, на работе и то кривые библиотеки. Но всё же надо отдать должное Lifelover’у, код перенёсся в касание, проблема была только в незнании архитектуры.

Код

Я человек ленивый, по этому за основу взят пример webif2.zip, хранящийся еще со времён прошлого конкурса (а второй тур то и заглох, не?). Поскольку код написан для AVR, хоть и на Си, потребовалась небольшая работа напильником.
В первую очередь, и самое очевидное, это единое линейное адресное пространство STM8. Нам совершенно нет никакой разницы, находятся ли данные во флэш-памяти или же в оперативной памяти. Так что ни какие prog_char нам не нужны.
Настройка SPI не вызывает никаких проблем: выставляем нужные биты и..., всё описано в datasheet’е. Функция обмена ничем практически не отличается от AVR версии, разве что именами регистров и битов:
uint8_t enc28j60_rxtx(uint8_t data)
{
  SPI_DR = data;
  while(!(SPI_SR & MASK_SPI_SR_RXNE));
  return SPI_DR;
}

Вот за что я люблю аппаратные интерфейсы. Настроил, запустил – и они работают (конечно не всегда бывает такое счастье). Да к тому же более качественно нежели ножкодрыгство.
Ну и в завершении убираем PWM со светодиода. Это тема для отдельного рассмотрения, не зачем лепить всё и сразу.
Собираем, запускаем и … облом. Кто заметил, что не правильно?

Роутер линк показывает, пакеты ходят, но пинга нет, и эксплорер молчит.
Святая вещь отладчик, без него бы просто плюнул и забил бы. А так, лезем в отладку и видим что при извлечении пакета получается какой-то мусор.
enc28j60_read_buffer((void*)&enc28j60_rxrdpt, sizeof(enc28j60_rxrdpt));
enc28j60_read_buffer((void*)&rxlen, sizeof(rxlen));
enc28j60_read_buffer((void*)&status, sizeof(status)); 

А мусор ли?
Одинокая мысль в тёмном углу пустой черепной коробки не решительно выползла на свет. Интересно, вот почему в описании архитектуры STM нет ни слова о порядке байт? Почему ответ на данный вопрос находится только в районе 28 страницы PM0044? Вот этот упущенный момент. В архитектуре STM8 для много байтовых величин старший байт находится по младшему адресу, Это так называемый сетевой порядок байт. В то время как у ENC28J60 (и у AVR, и у x86) старший байт расположен по старшему адресу.
Заменяем упомянутые строки на вызовы функции, не чувствительной к порядку байт целевой платформы:
uint16_t enc28j60_read_buffer_u16()
{
       	uint16_t val;
	enc28j60_select();
	enc28j60_tx(ENC28J60_SPI_RBM);
	val =	enc28j60_rx() |
		(uint16_t)enc28j60_rx() << 8;
	enc28j60_release();
	return val;
}

Ну и по сколько порядок байт у нас сетевой, то не забудем и про группу функций htons.

Повторный запуск дает уже положительный результат.


DHCP?

Надо заметить, что отладочная версия собиралась без DHCP и успешно поместилась в 8кБайт flash-памяти stm8s103f3. И это притом, что было напичкано ещё достаточно отладочного вывода на консоль. Так же 1кБайта оперативной памяти вполне достаточно для работы программы. Ну вот чем вам не замена ATmega8?
С использованием же DHCP код по-прежнему помещается на контроллер, но вот только в релиз сборке и без отладочного вывода на консоль. В прочем не велика беда, но нам же всегда хочется чего-то большего.
Вспоминаем, что программируем то мы через STM8S-Discovery, а в ней контроллер на 32кБайта. Их то нам хватит на 3 DHCP версии.
Правим конфиг, собираем, и … вспоминаем что студия то у нас халявная (внезапно). Мдя. Можно было бы конечно написать библиотечку, но стало как-то лень.
Так что переключаемся в релиз, возвращаем отладочный вывод, убираем дублирование кода, делаем непростительную оптимизацию (быдлокод жив), и всё-таки помещаемся в 8кБайт и более того, ещё 2 байта свободно!

Стоит отметить, что отключение буферизованного вывода на COM-порт крайне негативно сказалось на быстродействии системы. Так пинг 450 байтовыми пакетами с 4мсек вырос до 9мсек:


Кто хочет проверить

Прошивка stm8s103f3 без DHCP (ip: 192.168.1.222) — тут.
Прошивка stm8s105c6 c DHCP — тут.
Подключение:
// PIN – discovery - stm8s103f3 - name
// ENC28J60
// pc5 - CN2.6  - 15 in TSSOP20 - sck
// pc6 - CN2.9  - 16 in TSSOP20 - mosi
// pc7 - CN2.10 - 17 in TSSOP20 - miso
// pa3 - CN1.9  - 10 in TSSOP20 – nss
// UART
// PD5 - CN4.10 - 2 in TSSOP20 - tx
// PD6 - CN4.11 - 3 in TSSOP20 - rx

Быдлокод желающие смогут найти самостоятельно.
Важно! Пинг из-под ОС Windows у меня не заработал вообще, я не стал разбираться почему (может Wi-Fi, может недосмотрел в коде что, может…).

UPD: Без каких либо изменений прошивка от STM8S103F3 работает и на STM8S003F3.
  • +2
  • 27 февраля 2012, 12:18
  • angel5a
  • 4

Комментарии (28)

RSS свернуть / развернуть
Привет! Молодца, давно не слышно было)
Что за быдлокод?)
0
В первую очередь, и самое очевидное, это гарвардская архитектура STM8. Нам совершенно нет никакой разницы, находятся ли данные во флэш-памяти или же в оперативной памяти. Так что ни какие prog_char нам не нужны.
Ты ничего не путаешь? Эта разница свойственна именно МК с гарвардской архитектурой, к которым относится и AVR. Правда, я все еще не удосужился выяснить, какая архитектура у STM8, но если гарвардская — то «никакие prog_char нам не нужны» заслуга компилятора, а не архитектуры.
В архитектуре STM8 для много байтовых величин старший байт находится по младшему адресу, Это так называемый сетевой порядок байт.
Т.е., они Big Endian? Кстати, для AVR эту инфу тоже не так просто найти оказалось, по крайней мере с полпинка в даташите не нашел инфу о порядке байт.
0
  • avatar
  • Vga
  • 27 февраля 2012, 13:44
Ты ничего не путаешь? ...
Виноват. Теорию подзапамятовал. Исправил формулировку.
… заслуга компилятора, а не архитектуры.
Всё же архитектуры. Для извлечения данных нет разницы что флеш, что оперативка, что порт переферии. Используются одни и те же команды доступа к памяти. В той же авр используются prog_mem_read (или как её, не помню). У стм8 же мы можем описать «абстрактный указатель на чар»
char *ptr;

и менять его на любую область.

Т.е., они Big Endian?
А вот тут вот простите, я в этих эндианах всегда путался, кто есть кто. Для меня привычнее понятия intel и сетевой порядок байт. Порядок сетевой, не как у x86 (это надо учитывать при обмене данными с компом).
0
Фон-Неймановская архитектура это называется. Данные и код в едином АП (линейность/сегментированность уже отдельное понятие, называемое «модель памяти»).
В той же авр используются prog_mem_read (или как её, не помню).
Если смотреть на уровне ассемблера — то LPM/STM, тогда как с ОЗУ работают LD/ST (ЕМНИП) и еще некоторые. prog_mem_read — это особенности AVR-GCC, в том же IAR EWAVR различие адресных пространств скрыто и с памятью программ можно работать точно так же, как и с ОЗУ (кроме, разумеется, записи туда).
А вот тут вот простите, я в этих эндианах всегда путался, кто есть кто.
У x86 — LE, сеть — BE.
0
а я за это и говорю, что в авр есть разница (про пики вообще молчу) и эта разница вынесена в Си. Вот в чем основная «притензия».
0
Меня опередили…
0
В енке опередили или в портирование?
И в том и в другом случае статья не будет лишней. Я писал «свои заметки» по ходу работы и ни чуть не претендовал на полноту материала. В частности описание SPI и прочей переферии были преднамеренно выброшены. Идея статьи «не наступайте на мои грабли».
0
Опередили в подключении ENC28J60 к STM8. Только писать буду на ассемблере (если хочется Си — есть STM32).

Статья хорошая. Постараюсь обойти грабли.
0
И TCP стек на асме ??
или будет гибридный проект: хардваря на ASM, стек и юзерспейс на Си?
А чем вас не утсраивает Си для стм8? отчего сразу к стм32 отсыл? Компилятор довольно таки хорошо оптимизирует код. Да, есть местами недостатки, время разработки разлечается в разы.
У меня в целом получилось до 2-кратной разницы в скорости выполнения асм и си версий — вложенные циклы, когда каждый такт внутри на счету. Но всё равно склоняюсь в сторону Си, как более универсального средства. а асм только в критически важных местах, и то по завершении проекта (или от нефиг делать).
0
Для STM8 все на асме. Вообще STM8 мне не нравятся, закупил одно время по 20р… вот теперь сую куда только можно.
На асме пишу чтобы проникнуться кривизной архитектуры STM8 и в дальнейшем было проще освоить DSP (если придется столкнуться).
0
А в чем проявляется ее кривизна?
0
Хотя бы тем, что при хваленых 24х способах адресации отсутствует адресация по индексу с постинкриментом, которая есть у AVR, MSP430, ARM… Также некоторые инструкции выполняются неопределенное время (об этом были написаны несколько статей на сайте).
0
Я «рожден» на х86 архетектуре и такие понятия как конвеер и вытеснение для меня не чужды. не надо страдать хернёй типа ножкодрыгства и всё будет нормально.
0
Есть аргумент в оправдание адресации?
0
Что значит оправдание?
Я могу предположить почему такой команды не было реализовано:
— отказ от дополнительных кодов команд
— (бред) сокращение числа команд (да 24 много, многофункционально, но и не слишком много)
— (актуально) Набор команд ориентирован на С/С++ (уже устал это повторять), в котором есть структуры, массивы, и эти массивы этих структур. далеко не всегда массивы чаровские. Тот же инт просит уже 2 байта а инт это основной тип. Не говоря уже о структурах. Таким образом далеко не всегда нужен инкремент на единицу. Кому на сколько надо проинкрементит отдельно.

И как вы правильно заметили 24 способа адресации, а не модифицирования указателей.
0
На C/C++ ориентированы RISC архитектуры.
0
И чем Вам «кривизна» STM8 поможет освоить DSP?
0
И то и то для меня экзотика =).
0
где бы мне из по 20 закупить. у меня в этом и суть, что бы в копеечные девайсы их втыкать. Как выяснилось — эти копеечные могут быть вполне производительными. А для бОльших мощностей лпц-шка есть.
0
Поздравляю с выходом в сеть :) А вообще, big-endian и little-endian – известный гемор при портировании кода (а в теории существует еще экзотический Middle-endian ). В GCC есть предопределенное макроопределение __BYTE_ORDER__. Используя этот макрос можно писать портируемый (BE-LE) код в рамках GCC. Жаль, что подобно механизма (стандартного макроопределения для определения порядка байт на этапе компиляции) нет в самом стандарте С.
0
  • avatar
  • e_mc2
  • 27 февраля 2012, 21:53
Пинг из-под ОС Windows у меня не заработал вообще
Вы бы затрейсили IP трафик. Интересно, чем «виндовый» ICMP Ping пакет отличается от «не виндового».
0
Там скорее всего из-за вафли роутер срезает, хотя хз. найду второй шнурок — со стационарника гляну.
0
Подключил систему шнурком — нет пинга из под винды. На глазок разница в пакетах видна, но разбираться пока не стал. Если прижмет, перечитаю оригинальные статьи (помнится там были всевозможные правки, возможно у меня версия либы старая) и пойду в отладку. а пока не вижу смысла глубокого копания.
0
Спасибо.
Подобные дефайны есть и в других системах, только обычно они идут в хедере архетектуры (для никсов например) и особой определённости в них вроде нет. Это конечно печалит, но обычно не вызывает проблем ввиду наличия готовых htons'ов. Код приложения избавляется от условностей и получается портируемый, и библиотека «пишется 1 раз».
0
Поковырял STM8S003F3, собственно работает, добавлять в статью ни чего не требуется.
0
>>… единое линейное адресное пространство STM8. Нам совершенно нет никакой разницы, находятся ли данные во флэш-памяти или же в оперативной памяти. Так что ни какие prog_char нам не нужны.

Вопрос от новичка — что нам дает эта линейность адр. пр., какое преимущество перед иными архитектурами, и где можно об этом подробнее узнать!?
0
Там же сказано.
Во первых, пространство одно. В AVR строка, лежащая во флеше — это совсем другой тип данных, чем такая же строка в ОЗУ и скажем какой-нить printf ее просто не примет. Нужно заводить каждой функции по два экземпляра — один работает со строкой из флеша, другой со строкой из ОЗУ (на самом деле есть и другие варианты, но и такой не редкость). Ну и прочие неудобства.
А во вторых — можно выполнять программу из ОЗУ. Тоже зачастую полезно.
Вообще, с точки зрения программы эти МК имеют фоннеймановскую архитектуру, а не гарвардскую, со всеми вытекающими.
0
Насчет PING. Делаю переходник UART<->LAN на STM8S003. Использую стек от LifeLover. У него контрольная сумма для ответа ICMP берется как icmp->cksum += 8. Если в этом месте «правильно» считать контрольную сумму: icmp->cksum = ip_cksum(0, (uint8_t *)icmp, len);, то PING будет работать.
+1
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.