/STM32_RTOS_CANFestival

Slave client CANFestival on STM32F103 in FreeRTOS and HAL lib

Primary LanguageC

Тестовый проект СANFestival для STM32F103 на HAL с FreeRTOS в VSCODE


За основу проекта взято

  1. Форк fbsder/canfestival т. к. похоже это самый живой форк оригинала.

  2. Проект ZhiyangZhou24/CANopen-STM32F1 - основные изменения это переделка на поддержку библиотек HAL

  3. При разбирательствах как "ОНО" работает очень помогла статья CAN + CANOpen + CANfestival + STM32. Часть первая.

  4. Для настройки проекта в VScode использованы различные материалы найденные на просторах интернета.

⚠️ Важное примечание: Если нарушены чьи-то авторские права, то это не специально, укажите, тут же исправлю / добавлю ссылку.

  1. Описание проекта и комментарии в коде в первую очередь сделаны в качестве памятки, чтобы легче было вспомнить как оно работает и имплементировать данные наработки в друой проект.

Краткое описание

  • Шаблон Slave устройства для STM32F103. Проект сделан в VScode. На текущий момент работает:

  • отправка Heartbeat сообщений.

  • получение и отправка SDO сообщений.

  • регулярная отправка PDO сообщений.

  • возможность смены CAN_Id устройства из тела программы или по команде из сети через SDO.

  • перезагрузка по команде NMT.

  • аппаратный CAN фильтр по индивидуальному и групповому адресу (автоматически перестраивается при смене ** can_ID **).

  • реализован обработчик callback функции на изменение параметров PDO/SDO по сети.

  • Подправлен генератор словаря ObjdicEdit, теперь он работает с текущими библиотеками Python. Включена возможность указать ** can_ID ** устройства при генерации словаря.

  • Вывод отладочной информации может быть в main.h и can_driver.h легко отключен или перенастроен с SWD на UART (в этом случае надо через STM32СubeMX активировать соответствующий порт). К контроллеру подключён одноразрядный 7-сегментный индикатор, через него так же можно выводить отладочною информацию (цифры от 0 до F, точку, символ ошибки "Е").

  • Проект тестировался на STM32F103CB, в качестве can драйвера использовался SN65HVD230, корреспондентом на шине являлся модуль mcp2515 -> arduino -> программа CANHacher.

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

  • Проект содержит MX файл, по этому данный шаблон легко использовать для других более сложных проектов.

  • Включен вывод отладочной информации по использованию задачами стека и кучи.

  • Используется библиотека printf-stdarg для подмены стандартных функций printf/sprintf.

Листинг использования памяти по результатам компиляции

Memory region         Used Size  Region Size  %age Used
             RAM:        9432 B        20 KB     46.05%
           FLASH:       37612 B       128 KB     28.70%
   text    data     bss     dec     hex filename
  36268    1340    8100   45708    b28c build/RTOS_CANOpen2.elf

при этом, при работе микроконтроллера:

  • в среднем использование стека для задач:
    • CAN_Tx_Task Free Stack:166
    • CAN_Rx_Task Free Stack:156
  • FreeHeapSize/MinimumEverFreeHeapSize: 1160/536

Отключение вывода диагностической информации не уменьшает использования RAM, но размер программы во FLASH становится заметно меньше.

Я думаю, минимальное значение кучи 536 зафиксировано до удаление стартовой задачи, и при недостатке памяти в системе можно немного уменьшить HeapSize (хотя он может быть фрагментированный и это не спасет).

STM32СubeMX

Для таймеров CanFestival используется TIM2 (вы можете использовать другой), в нем для отладки делитель установлен в значение ** 7099 ** (**TIM2. Init. Prescaler = 7100-1 **) вместо значения ** 709 **, т. к в этом случае периоды отправки CAN пакетов увеличивается в 10 раз и это удобно для отладки.

Объектный словарь (Object dictionary)

ObjdicEdit.py

откорректированный ObjdicEdit.py протестирован с:

Python 2. 7. 13 (v2. 7. 13:a06454b1afa1, Dec 17 2016, 20:53:40) [MSC v. 1500 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.

>>> import wx
>>> wx. __version__

'4. 0. 7. post2'

>>> quit()

также ObjdicEdit.py должен работать в debian10.

slave.od

В настройках объектного словаря ** can_ID ** установлен в значение ** 0x00 *, это позволяет на лету менять сетевой адрес устройства через глобальную переменную ** can_ID ** (в проекте ей задано значение *** 0x04 **, что и будет видно в примерах ниже). которая в свою очередь задается в словаре под индексом ** 0x2000sub0x00 **.

Если вам этого не требуется, то можете удалить данную переменную и задавать адрес устройства через Node ID объектного словаря.

Can_driver

Чтобы не править файлы CANFestival подмена Node ID производится в драйвере can_driver.c. Кроме того, для уменьшения размера используемой памяти между CANFestival и HAL используются сокращенные структуры ** CanRxMsg ** и ** CanTxMsg ** (возможно я не прав, и отказ от них позволит сократить использование памяти).

Как все работает

Общее описание

VSСode

Перед использованием необходимо поправить пути до GCC и OpenOCD в файле .vscode/settings.json после этого во всех скриптах должны правильно отработать ссылки на них. Там же надо установить частоту процессора и проверить значение swoFrequency в файле .vscode/launch.json (при указании в этом поле переменной скрипт не работает).

В STM32СubeMX

(в скобках указаны параметры принятые в проекте):

  • Настраиваем тактирование микроконтроллера (** 72 ** Mhz от 8Mhz кварца).
  • CAN интерфейс, определяем используемые порты (** PA 11|12 **), скорость (500kBPs), использование прерывания при приеме пакетов (для работы требуется только USB_LP_CAN1_RX0_IRQ, если надо отлаживать аппаратный CAN фильтр то включаем CAN1_RX1_IRQ)/
  • включаем таймеры для:
    • CANFestival (TIM2), устанавливаем делитель в значение ** 7099 **,
    • системных тиков (TIM4).
  • включаем SWD.
  • настаиваем прочие порты.
  • Включаем FreeRTOS, в нем:
    • настаиваем одну задачу (CAN_Start_Task) инициирующую все дальнейшие действия на CAN интерфейсе (она инициализирует CANFestival, создаст дочерние задачи и после этого будет удалена).
    • включаем функции необходимые для отслеживания использования стека и Heap.
  • настаиваем STM32СubeMX на генерацию Makefile.
  • в Makefile прописываем пути к библиотекам и *.с файлам, которые он не видит. Необходимо проверить, что TARGET в Makefile совпадает именем папки с проектом иначе не будет работать отладка в VScode Если есть желание можно добавить вывод диагностической информации при компиляции как в проекте (см. Lib/Debug/README.md)

В объектном словаре

Настаиваем требуемые объекты в разделе ** 0x2000 **, при необходимости делаем их mapping в PDO|SDO.

Загрузка устройства

После загрузки узел переходит в состояние Pre_operational отправляет Heartbeat сообщение о загрузке Send a Boot-Up msg в CAN очередь:

ID    0x704    - (0x700 + 0x4) cob_id=  1796
DLC   1 
data  0x00     - 0 - значит bootup

после чего узел приходит в режим ** Operational ** и отправляет следующее Heartbeat сообщение в CAN очередь:

ID    0x704    - (0x700 + 0x4) cob_id=  1796
DLC   1 
data  0x00     - 5 - режим Operational

и сразу за этим данные PDO указанные в индексе 0x1A00

** Heartbeat ** сообщения посылаются каждые 0,5с (период задан в объектном словаре, может быть оперативно изменен по сети).

ID    0x704 (0x700 + 0x04) cob_id= 1796
DLC   1
data  0x05

SD0

Пример запроса температуры по индексу 0х2002sub0х00

0x604 0x08 0x43 0x02 0x20 0x00 0xXX 0xXX 0xXX 0xXX, где:

ID        - 0x604     - 0x600 + Id 0x04
DLC       - 0x08      - всегда должно быть 8
Data [0]  - 0x43      - спецификатор команды, из них
                        биты 4-7  - в этом случае это 0х4 -  запрос чтения (если 0х2 - запрос записи)
                        биты 2-3  - b00 количество байт в сообщении, здесь 0
                        биты 0-1  - х.з. b11  в принципе работает если b00 (т.е в поле 0х40 вместо 0х43)
Data[1-2] - 0x02 0x20 - индекс 0х2002 запись битов идет в обратном порядке
Data[3]   - 0x00      - суб. индекс 0х00
Data[4-7] - неважно

Ответ:

0x584 0x08 0x43 0x02 0x20 0x00 0x00 0x00 0xC8 0x42, где:

ID        - 0x584     - 0x500 + Id 0x04
DLC       - 0x08      - количество бит, но пока все пакеты, что я видел 8
Data [0]  - 0x43      - спецификатор команды странно должно быть 0х60, из них

                        биты 4-7  - в этом случае это 0х4 -  запрос передачи (если 0х2 - запрос записи)
                        биты 2-3  - b00
                        биты 0-1  - х.з. b11  

Data[1-2] - 0x02 0x20 - индекс 0х2002 запись битов идет в обратном порядке
Data[3]   - 0x00      - суб. индекс 0х01
Data[4-7] - 0x00 0x00 0xc8 0x42 полезные данные глобальной переменной Temperature=100 (float) в обратном порядке 

Пример записи температуры по индексу 0х2002sub0х00

0x604 0x08 0x23 0x02 0x20 0x00 0x00 0x00 0xC9 0x42, где:

ID      - 0x604             - 0x600 + Id 0x04
DLC     - 0x08              - всегда должно быть 8 
Data[0] - 0x23              - спецификатор команды, из них:
                            биты 4-7  - в этом случае это 0х2 - запрос записи
                            биты 2-3  - b00 количество байт в записываемом значении здесь 4 бата, поэтому 0, если 2 байта то указываем 0x2B, если 1 байт то 0x2F соответственно
                            биты 0-1  - х.з. почему b11
Data[1-2] - 0x02 0x20   - индекс 0х2000 запись битов идет в обратном порядке
Data[3] - 0x00          - суб. индекс 0х00 Data[4-7] - 0x00 0x00 0xC9 0x42 -новое значение температуры 100.5

Ответ:

0x584 0x08 0x60 0x02 0x20 0x00 0x00 0x00 0x00 0x00

ID - 0x584          - 0x500 + Id 0x04
DLC - 0x08          - количество бит, но пока все пакеты, что я видел 8
Data [0] - 0x60     - спецификатор команды
                        биты 4-7  - в этом случае это 0х6  успешная запись в случае неуспеха 0х80
                        биты 2-3  - b00 
                        биты 0-1  - х.з. b11  
Data[1-2]           - 0x02 0x20 - индекс 0х2002 запись битов идет в обратном порядке
Data[3] - 0x00      - суб. индекс 0х00 Data[4-7] - 0x00 0x00 0x00 0x00 - пустое поле с данными

PDO

Чтобы данные через PDO отправлялись регулярно надо в словаре по индексу ** 0x1800 ** в:

  1. суб индекс ** 0x02 ** записать значение ** 0xFF ** - разрешаем спонтанную передачу.

  2. суб индекс ** 0x05 ** записать значение ** 0x01F4 ** - устанавливаем таймер на 500 mc. (если в данном регистре будет ** 0 **, то сообщение отправится только один раз).

Эти установки можно задать командами по сети (до следующей перезагрузки, т.к. значение возьмется из словаря указанное в прошивке), для этого:

  • разрешаем спонтанную передачу PDO: 0x604 0x08 0x2F 0x00 0x18 0x02 0xFF 0x00 0x00 0x00. В случае успеха получаем: 0x584 0x08 0x60 0x00 0x18 0x02 0x00 0x00 0x00 0x00, если получили: 0x584 0x08 0x80 - проверь число байт с команде на запись, команда должна быть ** 0x2F **.

  • устанавливаем таймер: 0x604 0x08 0x2F 0x00 0x18 0x025 0xF4 0x01 0x00 0x00.

После этого начинаем получать данные с температурой: 0x284 0x04 0x00 0x00 0xC9 0x42.

NMT

Реализована поддержка команд NMT, при этом они работают как при обращении по IDнепосредственно данному узлу, так и широковещательно лявсех узлов сети.

Пример команды для перезагрузки устройства:

ID      - 0x00
DLC     - 0x02          - количество бит
Data[0] - 0x81          - команда перезагрузки устройства
Data[1] - 0x04          - адрес устройства, если 0х00 - широковещательная команда на все устройства соответственно

Функционал реализован через функцию ** NMT_Slave_Node_Reset_Callback_Function() **.

Callback

В основном цикле, при инициализации CAN приложений (файл taskcan.c функция ** CAN_Start_App **) производится регистрация вызовов callback при изменении параметров по сети. В примере реализована всего одна функция callback которая анализирует контекст вызова и в зависимости от этого, производит различные действия (меняет ** can_id ** с пере инициализацией CAN фильтра, либо просто выводит на консоль информацию об изменении переменной ** Dac **).


Возможные баги

Если не отравляются CAN сообщения, а TX почтовый ящик забит, надо проверить слышит ли прием собственную передачу, иначе контроллер думает, что шина занята и блокирует передачу. У меня была неисправна микросхема Can драйвера и в режиме CAN Lookback все работало хорошо, но при переводе в нормальный режим, пакеты перестали отправляться.

Прочее

Проект включает файлы:

  • CANHack-TX-list.txl - список TX сообщений для программы CANHacher.
  • pulseView.pvs - конфигурационный файл для программы PulseView для анализатора протокола CAN.