STM Урок 131. LAN8742A. LWIP. SOCKET. UDP Server. Часть 1

 

 

 

Немало времени мы изучали с вами интерфейс стека протоколов LWIP — NETCONN, который оказался не таким уж и простым в освоении, но тем не менее с помощью него нам стало гораздо проще решать непростые задачи по программированию передачи данных по сети, стоящие перед нами.

Теперь нам предстоит изучение ещё более совершенного интерфейса — SOCKET, который, надеюсь, позволит нам решать ещё более сложные и ответственные задачи более простыми путями, чем те, которые необходимо было бы проходить, используя другие интерфейсы.

Интерфейс (или API) SOCKET является представителем интерфейса сокетов Беркли (или более известных как сокеты BSD), которые представляют собой библиотеку для разработки приложений для сетевых интерфейсов межпроцессорного взаимодействия, которую Калифорнийский университет в Беркли начал выпускать в 1989 году. А появились данные сокеты ещё в 1982 году. Вот такая вот история, подтверждённая многолетним опытом использования в разных системах и языках.

Интерфейс сокета Беркли — API, позволяющий реализовывать взаимодействие между компьютерами или между процессами на одном компьютере. Данная технология может работать со множеством различных устройств ввода-вывода и драйверов, несмотря на то, что их поддержка зависит от реализации операционной системы. Подобная реализация интерфейса лежит в основе TCP/IP, благодаря чему считается одной из фундаментальных технологий, на которых основывается Интернет. Технология сокетов впервые была разработана в Калифорнийском университете Беркли для применения на UNIX системах. Все современные операционные системы имеют ту или иную реализацию интерфейса сокетов Беркли, так как это стало стандартным интерфейсом для подключения к сети Интернет.

Несмотря на то, что данный интерфейс разработан для взаимодействия между компьютерами, мы можем его использовать и для наших микроконтроллеров, благодаря библиотеке стека протоколов LWIP.

API SOCKET включает в себя ряд различных структур, функций, параметров, имена которых уже устоялись и не меняются, что позволяет пользоваться ими, изучая документацию, изданную для любых систем.

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

В принципе, для начала вышеизложенной информации будет вполне достаточно. Конечно, этого очень мало для понимания API SOCKET, у которого существует огромный ряд своих тонкостей и прелестей, с частью которых мы познакомимся уже в процессе создания наших проектов и написания их кода, что, как показала практика нашего общения, приносит гораздо большие плоды, нежели предварительное полное изучение без практики.

И, как всегда, как и при изучении любого интерфейса LWIP мы начнём с реализации простейшего сервера UDP. Это стало уже традицией, как «Hello World» в консольных приложениях.

Работать мы будем, как обычно, с отладочной платой STM32F746-Discovery.

А теперь, собственно, проект. Он был сделан из проекта прошлого занятия LAN8742_NTP_CLIENT_NETCONN и имя ему было дано LAN8742_UDP_SERVER_SOCKET.

Теперь откроем наш проект в Cube MX и отключим сначала RTC

Перейдём в Configuration и в FREERTOS в первом разделе выберем схему управления памятью heap_5, она мне больше понравилась чем четвёртая, так как позволяет работать с регионами памяти

Размер кучи менять не будем, впрочем от него теперь ничего не зависит.

Кстати, насчёт регионов памяти. Правда это к куче FREERTOS не относится, но в памяти SDRAM мы на вторую половинку предоставим несколько расширенный доступ. Поэтому перейдём в настройки Cortex_M7 и сначала исправим размер нулевого региона, вернув ему 4 мегабайта

Добавим ещё один регион с нужного адреса, назначим ему такой же размер и включим все опции

Сохраним настройки, сгенерируем проект для System Workbench и откроем его там. Установим уровень оптимизации в 1 и уберём при наличии отладочные настройки.

Файлы ntp.c и ntp.h из проекта удалим, они удалятся также и физически. Также удалим подключение данной библиотеки и из файла main.с

#include «ntp.h»

Подключение вот этого файла также можно удалить

#include «lwip/apps/fs.h»

Подключим библиотеки для работы с сокетами

 

Удалим вот этот идентификатор очереди

osMessageQId timeout_Queue;

Удалим также макрос для размера очереди и переменную счётчика времени

#define QUEUE_SIZE (uint32_t) 1

uint32_t time_count = 0;

А вот этот макрос поднимем выше, ему там будет лучше

 

Подправим шапку проекта в main()

TFT_DisplayString(0, 10, (uint8_t *)"UDP Server", CENTER_MODE);

Удалим создание очереди

osMessageQDef(timeout_Queue, QUEUE_SIZE, uint16_t);

timeout_Queue = osMessageCreate(osMessageQ(timeout_Queue), NULL);

 

 

Функцию netconn_thread переименуем в udp_thread и пока добавим в неё только задержку в бесконечном цикле

 

В глобальной структуре struct_sock изменим немного тело, поменяв в ней только одно поле

 

А переменную данной структуры оставим только одну

struct_sock sock01, sock02;

В задаче по умолчанию StartDefaultTask произведём инициализацию полей данной переменной

 

А также в создании задачи изменим имя задачи и добавим данную переменную в качестве параметра

sys_thread_new("udp_thread", udp_thread, (void*)&sock01, DEFAULT_THREAD_STACKSIZE, osPriorityNormal);

Проект у нас теперь скорей всего соберётся.

Но если мы его прошьём в контроллер, то у нас плата не будет даже пинговаться

А всё потому что у нас в FreeRTOS нет кучи, а соответственно нет и никаких стеков. Такова специфика схемы распределения памяти heap_5. Она работает уже не с помощью автоматического запроса кучи, а с регионами памяти, которые надо сначала объявить.

Для начала добавим глобальный массив в конце общей кучи

 

Пока это только объявление массива, а не инициализация самой кучи, это будет позже.

Чтобы проверить, что мы теперь можем объявлять кучу более 32 килобайт и причём распределять её в разных местах, добавим ещё один такой массив, но уже в другом месте, там, где нам автоматически выделит компоновщик

 

В самом начале функции main добавим следующую структуру

 

В данной структуре мы объединили наши регионы, чтобы с ними могла работать операционная система. Ноль в конце обязателен.

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

 

Вот теперь, если мы соберём наш проект и прошьём контроллер, то у нас отлично пойдут пинги

Откроем файл в папке «Имя проекта\Debug\» с именем output.map и посмотрим, как и где расположились в памяти наши регионы

А расположились они сразу после секции глобальных данных перед секцией bss.

А вот и второй регион, спрятавшийся где-то в общей секции COMMON

Объявить регионы можно было без массивов, с помощью физических адресов где-нибудь в верхних адресах памяти, но это, как вы понимаете не совсем безопасно. Так, как сделали мы, гораздо безопаснее. Компоновщик сам «знает», куда и как располагать массивы.

 

В следующей части урока мы создадим сокет и попробуем принять пакет от клиента, а также ответить ему пакетом UDP.

 

Предыдущий урок Программирование МК STM32 Следующая часть

 

Отладочную плату можно приобрести здесь 32F746G-DISCOVERY

 

 

Смотреть ВИДЕОУРОК (нажмите на картинку)

 

STM LAN8742A. LWIP. SOCKET. UDP Server

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

*