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.
Файлы: 103f3_nodhcp.zip, 105c6_dhcp.zip, ramexecute.zip, DSC03031_1.jpg