USB WatchDog Pro2 Forth
Программируемый сторожевой таймер: встроенный язык программирования Forth позволяет модифицировать логику под самые разные задачи.

USB для управления и программирования без IDE.
Для сильных духом.
Общее описание

Сторожевой таймер USB WatchDog Pro2 Forth представляет собой компактную программируемую платформу с интерфейсом USB и 3 доступными пинами для подключения различной периферии: 2 опторазвязанных выхода и один неизолированный с подтяжкой для подключения термодатчика или сухого контакта.
Устройство программируется на языке Forth (Mecrisp-Stellaris), что обеспечивает интерактивную разработку непосредственно через USB-соединение. Контроллер может использоваться для автоматизации, управления устройствами, сбора данных и различных DIY-проектов.

Характеристики контроллера

  • Микроконтроллер: STM32F042 (ARM Cortex-M0)
  • Тактовая частота: 48 МГц
  • USB интерфейс: CDC (виртуальный COM-порт)
  • Доступные пины: 3
  • Питание: через USB
  • Поддержка PWM
  • Возможность сохранения настроек во флэш-памяти
  • Сторожевой таймер (IWDG)
  • Системный таймер (SysTick)
Как это работает?
Сторожевой таймер подключается через USB интерфейс к ПК. Проводом он напрямую соединяется с контактами Reset или Power материнской платы.
Программа-монитор запускается на ПК и переодически передает сигнал устройству. Если компьютер завис, то зависает и программа: watchdog перестаёт получать сигнал. Через заданное время USB WatchDog автоматически подает сигнал на контакт Reset материнской платы, чтобы перезагрузить систему.
Если Reset не сработал, активируется канал Power, который выключает и снова включает компьютер.
Чем отличается от WatchDog Pro2
Благодаря встроенному языку программирования Forth (Mecrisp-Stellaris) пользователь может изменять алгоритм работы в очень широких пределах.
Стандартными средствами устройства можно стереть текущий алгоритм и написать свой.
Микроконтроллер имеет 32 КБ flash-памяти. Наша прошивка занимает 25 КБ.
Пользователю остается ~7 КБ для реализации своей логики.
Установка USB WatchDog Pro2
Это краткая инструкция, полную версию можно посмотреть на примере обычного USB WatchDog Pro2. Открыть.

1. Перед установкой необходимо выключить ПК.
2. Так как устройство бескорпусное, будьте с ним предельно острожны - не допускайте касания металлических поверхностей. Это может привести к порче устройства!
3. Провода Reset и Power необходимо подключить вместо кнопок от системного блока.
4. Как подключать PBD10

Для при установке устройства в материнскую плату убедитесь, что вы подключаете именно к разъему USB. Некоторые интерфейсы (например ieee1394 или COM-порт) имеют на плате такие же 10-выводные разъемы.

Подключение к интерфейсу, отличному от USB, приведет к порче устройства
(возможно с дымом и запахом)!


  • На плате с PBD10 разъемом на плате имеется точка. При подключении к материнской плате ПК она должна быть совмещена со стороной разъема где отсутствует 1 металлический контакт
5. Сами кнопки можно подключить к сторожевому таймеру, чтобы ими тоже можно было пользоваться.
WatchDog Pro2 PBD10
Осн.1 и Доп.1. - параллельно соединённые контакты канала 1. По-умолчанию, подключаются к контактам Reset: например, Осн.1 - на reset мат.платы и Доп.1 - на кнопку reset.
Осн.2 и Доп.2. - параллельно соединённые контакты канала 2. По-умолчанию, подключаются к контактам Power: например, Осн.2 - на power мат.платы и Доп.2-
на кнопку power.
Пример подключения к материнской плате
Драйвер
Работа в ОС ниже Windows7 не поддерживается.
В Windows7 понадобится установить драйвер CDC.
В Windows 8, Windows 10, Linux, macOS установка драйвера не требуется.
Если в Windows8 не заработал системный драйвер CDC, воспользуйтесь инструкцией.
Руководство программиста
Начало работы

  1. Подключите контроллер к компьютеру по USB
  2. Используйте любой терминал для COM-порта (PuTTY, TeraTerm, Minicom и т.д.)
  3. После подключения вы увидите приглашение Forth ok.

Forth - это интерактивный стековый язык программирования:
  • Операнды помещаются в стек
  • Операции извлекают операнды из стека и помещают результат обратно
  • Слова (функции) разделяются пробелами
  • Определение новых слов начинается с : имя_слова и заканчивается ;
Что такое Mecrisp-Stellaris
Mecrisp-Stellaris — это высокоэффективная реализация языка программирования Forth для микроконтроллеров на базе ARM Cortex-M.
Mecrisp-Stellaris отличается компактностью, надёжностью и оптимизированной производительностью. Эта среда позволяет запускать интерактивный интерпретатор Forth непосредственно на микроконтроллере, что открывает возможности для быстрой разработки и отладки кода без необходимости в перепрошивке устройства.

Forth — это уникальный стековый язык программирования, созданный Чарльзом Муром в 1970-х годах. Он предлагает:
  • Интерактивное программирование с мгновенной обратной связью
  • Минимальное потребление ресурсов памяти и процессора
  • Возможность расширения системы "на лету"
  • Прямой доступ к аппаратному обеспечению
  • Высокую портативность кода между разными платформами
  • Модульный подход к написанию программ
Forth идеально подходит для встраиваемых систем, где критичны размер кода и скорость выполнения.
Пример базовых операций
2 3 + .           \ Сложение 2+3 и вывод результата
: double 2 * ;  \ Определение слова для умножения на 2
5 double .       \ Результат: 10
Компиляция кода и управление памятью
Mecrisp-Stellaris Forth позволяет компилировать код как в оперативную память (RAM), так и во flash-память. Это важная особенность, которая определяет, будет ли ваш код сохранен после перезагрузки устройства.
\ Переключение в режим компиляции в RAM (будет потеряно при перезагрузке)
compiletoram

\ Переключение в режим компиляции во Flash (сохранится после перезагрузки)
compiletoflash
Создание точек восстановления
Система поддерживает механизм создания точек восстановления (cornerstone), который позволяет откатить состояние программы до определенного момента:
\ Создание точки восстановления с именем "basic_image"
compiletoflash    \ Важно: cornerstone работает только во Flash
: basic_image
  begin here dup flash-pagesize 1- and while 0 h, repeat
  does> begin dup dup flash-pagesize 1- and while 2+ repeat
  cr eraseflashfrom ;
После создания точки восстановления вы можете в любой момент вернуться к этому состоянию, вызвав её имя:
basic_image   \ Откат всех изменений, сделанных после создания cornerstone
Полный сброс пользовательской программы
Для полного удаления всего пользовательского кода из флэш-памяти используйте:
eraseflash   \ Полная очистка пользовательской программы
Рекомендации по компиляции
  1. Используйте compiletoram при разработке и отладке кода. Это позволит быстро вносить изменения без износа flash-памяти.
  2. После отладки переключитесь на compiletoflash и скомпилируйте окончательную версию для сохранения программы.
  3. Создавайте точки восстановления (cornerstone) после важных этапов разработки, чтобы можно было вернуться к рабочей версии.
  4. Делайте резервные копии кода на компьютере для сохранения важных программ.
Пример рабочего процесса
\ Начало разработки
compiletoram    \ Компиляция в RAM для тестирования

\ Тестирование базовых функций
: test-led IO3 iox! ;

\ После отладки, сохранение во Flash
compiletoflash
: test-led IO3 iox! ;

\ Создание точки восстановления
: basic_image
  begin here dup flash-pagesize 1- and while 0 h, repeat
  does> begin dup dup flash-pagesize 1- and while 2+ repeat
  cr eraseflashfrom ;

\ Продолжение разработки...
: more-functions
  \ ... дополнительный код

\ В случае проблем возврат к базовой версии
basic_image
Работа с GPIO
Настройка режимов пинов
\ Настройка пина на вывод (push-pull)
OMODE-PP IO3 io-mode!

\ Настройка пина на ввод с подтяжкой вверх
IMODE-HIGH IO7 io-mode!

\ Настройка пина на ввод с подтяжкой вниз
IMODE-LOW IO2 io-mode!

\ Настройка пина для аналогового ввода
IMODE-ADC IO6 io-mode!
Управление выводами
\ Установка высокого уровня
1 IO3 io!

\ Установка низкого уровня
0 IO3 io!

\ Инверсия состояния пина
IO3 iox!

\ Чтение состояния пина (результат: 0 или -1)
IO7 io@ .
Загрузим необходимые функции
: timer-base ( n -- addr )
  drop $40000000 ; \ Используем TIM2 для упрощения

\ Бит и адрес включения TIM2
: timer-enabit ( n -- bit addr )
  drop 0 bit RCC RCC_APB1ENR_OFFSET + ;

\ Инициализация таймера
: timer-init ( u n -- )  \ u = combined prescaler and auto-reload value
  dup timer-enabit bis!  \ Clock enable
  timer-base >r
  dup 16 rshift          \ Extract upper 16 bits (PSC)
  TIM.PSC r@ + !         \ Write to PSC register
  $FFFF and              \ Extract lower 16 bits (ARR)
  TIM.ARR r@ + !         \ Write to ARR register
  8 bit TIM.DIER r@ + bis!  \ Update event enable
  %010 4 lshift TIM.CR2 r@ + !  \ MMS = update
  0 bit TIM.CR1 r@ + bis!  \ Enable timer
  r> drop ;

: timer-deinit ( n -- )  \ disable timer n
  timer-enabit bic! ;

\ The following pins are supported for PWM setup on STM32F042:
\   TIM2:   PA0  PA1  PA2  PA3

\ Только TIM2
: p2tim ( pin -- n ) drop 2 ;

\ Получаем номер канала по пину (PA0=0, PA1=1, PA2=2, PA3=3)
: p2cmp ( pin -- n ) $3 and ;

\ Настройка альтернативных функций для всех поддерживаемых пинов
: pin-af2 ( pin -- )
  dup PA0 = if
    GPIO-BASE GPIO.AFRL + dup @
    $FFFFFFF0 and 2 or swap !  \ AF2 для PA0
  else dup PA1 = if
    GPIO-BASE GPIO.AFRL + dup @
    $FFFFF0FF and 2 4 lshift or swap !  \ AF2 для PA1
  else dup PA2 = if
    GPIO-BASE GPIO.AFRL + dup @
    $FFFF0FFF and 2 8 lshift or swap !  \ AF2 для PA2
  else dup PA3 = if
    GPIO-BASE GPIO.AFRL + dup @
    $FFF0FFFF and 2 12 lshift or swap !  \ AF2 для PA3
  then then then then drop ;

: pwm-init ( hz pin -- )
  >r
  OMODE-AF-PP r@ io-mode!
  r@ pin-af2
  
  \ Корректный расчет PSC и ARR для заданной частоты
  48000000 swap /                   \ Делитель для достижения нужной частоты
  
  \ Разделим на PSC и ARR (оба 16-битные)
  dup 65536 > if                    \ Если делитель > 65536, нужен предделитель
    dup 65536 / 1+ dup ( div div/65536+1 div/65536+1 )
    >r ( div div/65536+1 ) ( R: div/65536+1 )
    * r> ( div*div/65536+1 div/65536+1 )  
    swap over / 1-     \ ARR = (делитель / PSC) - 1
    swap 1-            \ PSC = div/65536+1 - 1
  else                  \ Если делитель <= 65536
    1 swap 1-           \ PSC = 0, ARR = делитель - 1
  then
  
  \ Установка PSC и ARR
  swap 16 lshift or    \ Создаем комбинированное значение PSC:ARR
  r@ p2tim timer-init
  
  \ Настройка режима PWM mode 1
  r@ p2cmp dup 2 < if
    \ Каналы 1 и 2 (PA0, PA1) используют CCMR1
    2 * 8 * $68 swap lshift
    r@ p2tim timer-base TIM.CCMR1 + bis!
  else
    \ Каналы 3 и 4 (PA2, PA3) используют CCMR2
    2 - 2 * 8 * $68 swap lshift
    r@ p2tim timer-base TIM.CCMR2 + bis!
  then
  
  \ Включение выхода
  r@ p2cmp 4 * bit r> p2tim timer-base TIM.CCER + bis!
;

\ Установка значения PWM
: pwm ( u pin -- )
  >r
  r@ p2tim timer-base TIM.ARR + @  \ Получаем значение ARR
  1+                              \ ARR+1 = полный период
  swap 10000 */                   \ Масштабирование: u * (ARR+1) / 10000
  r@ p2cmp cells                  \ Смещение для нужного канала CCR
  r> p2tim timer-base $34 + +     \ Адрес регистра CCRx
  !                               \ Записываем значение
;

Настройка PWM
\ Инициализация PWM на пине IO3 с частотой 1000 Гц
1000 IO3 pwm-init

\ Установка заполнения 50% (5000 из 10000)
5000 IO3 pwm
Пример плавного изменения яркости светодиода
: led-fade
  1000 IO3 pwm-init  \ инициализация PWM
  10 0 do            \ 10 циклов
    i 1000 * IO3 pwm \ значение PWM от 0 до 9000
    500 ms-delay     \ пауза 500 мс
  loop
  0 IO3 pwm ;        \ выключаем в конце
Системный таймер
Использование системного таймера
\ Инициализация системного таймера
systick-init

\ Чтение текущего значения счетчика миллисекунд
ms_tick_cnt @ .
Пример использования для измерения времени
: measure-time
  systick-init
  ms_tick_cnt @
  \ выполняем измеряемую операцию
  1000 0 do loop
  ms_tick_cnt @ swap -
  ." Время выполнения: " . ." мс" ;
Сторожевой таймер
Настройка сторожевого таймера
\ Инициализация IWDG с таймаутом 1000 мс
1000 iwdg-init-timeout

\ Сброс сторожевого таймера (необходимо вызывать периодически)
iwdg-refresh
Пример использования сторожевого таймера
: safe-loop
  1000 iwdg-init-timeout
  begin
    \ Основной код
    ." Работаю... " cr
    500 ms-delay
    
    \ Сброс сторожевого таймера
    iwdg-refresh
  again ;
Работа с флэш-памятью
Для сохранения настроек мы предлагаем использовать последнюю страницу памяти: SETTINGS_PAGE = 0x8007c00. Не затрите ее кодом, если планируете использовать.

: settings-write ( value addr -- )
    SETTINGS_PAGE +     \ ( value abs_addr )
    2dup h@ = if       \ Check if value equals current value at abs_addr
        2drop          \ If equal, do nothing
    else
        $08000000 - hflash!  \ If different, write value
    then ;

: settings-read ( addr -- value )
    SETTINGS_PAGE + h@ ;  \ Read half-word from absolute address

\ Сохранение настроек во флеш
: settings-erase ( -- )
    SETTINGS_PAGE $08000000 - flashpageerase
;
Работа с флэш-памятью
\ Стирание страницы настроек
settings-erase

\ Запись значения в адрес
123 0 settings-write  \ Запись числа 123 по смещению 0 последнего блока 1 КБ

\ Чтение значения из адреса
0 settings-read .     \ Чтение значения по смещению 0
Пример сохранения конфигурации
\ Структура конфигурации
0 constant CFG_PWM_FREQ    \ смещение для частоты PWM
2 constant CFG_ADC_THRESH  \ смещение для порога ADC

: save-config ( pwm-freq adc-thresh -- )
  settings-erase
  CFG_ADC_THRESH settings-write
  CFG_PWM_FREQ settings-write ;

: load-config
  CFG_PWM_FREQ settings-read
  CFG_ADC_THRESH settings-read ;
Примеры программ
Мигание светодиодом
: blink
  10 0 do
    1 LED1 io!
    500 ms-delay
    0 LED1 io!
    500 ms-delay
  loop ;
Считывание состояния кнопки
: wait-button
  IMODE-HIGH IO7 io-mode!  \ Кнопка с подтяжкой вверх
  begin
    IO7 io@ 0=  \ Проверка на нажатие (0 = нажата)
  until
  ." Кнопка нажата!" ;
Расширенные возможности
Идентификатор устройства
: show-device-info
  ." Chip ID: " chipid drop drop drop .
  ." Hardware ID: " hwid .
  ." Flash size: " flash-kb . ." KB" ;
Ограничения и особенности
  1. Питание: Контроллер питается через USB, при автономной работе необходимо обеспечить стабильное питание 3.3В.
  2. USB питание: При потере USB-соединения или переходе компьютера в режим сна, контроллер переходит в режим приостановки. Учитывайте это при проектировании автономных приложений. Запитывайте устройство от постоянных источников напряжения 5В.
  3. Защита от сбоев: Для критичных приложений используйте сторожевой таймер и механизмы сохранения данных во flash-память.

Надеемся, что данное руководство поможет вам в работе с мини-контроллером. Удачной разработки!
Дополнительные ресурсы