Comments 24
#define dbgG ((dbg_t*)DBG_ADDR) // адрес задан жестко, в настройках линкера эта часть озу убирается из доступной
А в чем смысл было убирать в недоступную секцию?
А если отладчик будет работать еще и как booloader, могут возникнуть пересечения адресов переменных. Да и проще в настройках линкера убрать немного озу, чем еще и выделить отдельную секцию для отладчика.
А если отладчик будет работать еще и как booloader
А GDB разве позволяет грузить прошивку? Или вы отдельный протокол для этого будете делать?
Отдельный протокол нет смысла придумывать, когда он уже есть в openOCD.
В папке st-link utility есть примеры
st-link utility это вот эту утилиту имеет ввиду
Там в папке ExternalLoader подобное применяется, но я так понял это что бы прошивать внешние чипы памяти
Что-то похожее видел в PIC24 Programming Manual. Там можно либо вручную программатором писать флеш. Либо зашить загрузчик и работать с ним.
В той папке загрузчики внешней памяти, но никто же не мешает написать такой-же для внутренней.
Но в моей конфигурации breakpoint окончания операции не срабатывает по какой-то причине.
Можно вместо брейкпойнта и поллинг окончания операции сделать.
9 — шаг (не получилось реализовать)
А в чем возникла проблема сделать шаг? вроде бы просто поставить брейкпойнт на следующую ассемблерную инструкцию.
Можно вместо брейкпойнта и поллинг окончания операции сделать.
Поллинг будет забирать часть времени, что увеличит время заливки.
А в чем возникла проблема сделать шаг?
Тогда нужно реализовать определение текущей инструкции средствами МК. Ато вдруг это инструкция перехода?
Но есть другой способ: В регистре DEMCR есть бит MON_STEP. Но тут возникли проблемы. Если не выключить прерывания, программа всегда останавливается на первой инструкции любого из наступивших прерываний. А если их выключить, он больше не попадает в DebugMon_Handler
Единственно кажущийся рабочий вариант — эмулировать эту команду на стороне GDB сервера
Ато вдруг это инструкция перехода?
Про инструкцию перехода я как-то и забыл)
Если не выключить прерывания, программа всегда останавливается на первой инструкции любого из наступивших прерываний. А если их выключить, он больше не попадает в DebugMon_Handler
Выключать можно не все, а оставить только DebugMon_Handler, разве нет?
А вот это круто! Спасибо!
0хАА 0xFF — Start of frame
0xAA 0x00 — End of frame
0xAA 0xA5 — Interrupt
0xAA 0xAA — Заменяется на 0xAA
На мой взгляд, протокол странный. Никакого контроля ошибок, зато есть escape-кодирование.
Может быть, хотя бы чексумму добавить?
А если использовать CRC, то можно и без escape-кодирования обойтись...
Не представляю как можно используя CRC избавиться от escape-кодирования при условии что пакеты переменной длинны
Не представляю как можно используя CRC избавиться от escape-кодирования при условии что пакеты переменной длинны
- Делаем пакета вида START, SIZE, DATA....DATA, CRC
- Во входном потоке байт ищем START.
- Следующий байт (байты) — SIZE.
- Набираем SIZE байт
- Проверяем CRC, сошлась — хорошо, набираем новый пакет. Не сошлась — ищем в том, что уже собрали еще один START; если нашли — пляшем от него по новой.
UPD: Вроде как это называется https://en.wikipedia.org/wiki/CRC-based_framing
Он этот пакет пропустит, дальше отправитель будет дублировать этот пакет и приемник уже ни один пакет принять не сможет.
Если сделать правильно, то будет так:
- пропущен start, size
- в середине данных найден фиктивный start, size, пошло накопление пакета
- пакет набран по фиктивному размеру, crc не сошлось.
- в уже набранном наборе байт ищется следующий start — он настоящий, синхронизация восстановлена
Т.е. если crc не сходится, не нужно выбрасывать все накопленное.
Конечно, если пакеты могут быть очень длинными и в них очень часто встречается фиктивный стартовый байт, то это может затянуться. В таком случае можно сделать несколько стартовых байт или ограничить размер пакета.
Ведь в дата может быть:
«START, SIZE,START, SIZE,START, SIZE,START, SIZE...» =)
А несколько стартовых байт, по сути, не спасут от
«START, SIZE,START, SIZE,START, SIZE,START, SIZE...»
Про ограничить размер пакета, что вы имели ввиду?
С эскейп-кодированием нужно эскейп кодирование и контрольная сумма тоже! А так — только контрольная сумма.
Код проще? Спорный вопрос.
Для эскейп-кодирования отправляемого сообщения мне в худшем случае нужен буфер удвоенного размера, ведь я заранее не знаю, сколько байт нужно будет эскапировать.
Так — только фиксированный запас на CRC.
Да и в чем сложность? Crc не сошлось — цикл для поиска старта, сдвиг массива (один вызов std::rotate), запускаем основной автомат набора пакета.
«START, SIZE,START, SIZE,START, SIZE,START, SIZE...»
Это патологический случай. Если он возможен и вероятен, то нужно стартовую последовательность выбирать другую.
При эскейп-кодировании тоже не сахар будет, ведь такой пакет раздуется в полтора раза, а это увеличит вероятность некорректной передачи...
Про ограничить размер пакета, что вы имели ввиду?
Это и имел — сказать, что пакеты могут быть не более Х байт.
Лично мое мнение: эскейп-кодирование — это устаревшая, неудобная и ненужная штука. Огромное количество протоколов (в т.ч. Ethernet и TCP) живет без него и отлично себя чувствует.
Для эскейп-кодирования отправляемого сообщения мне в худшем случае нужен буфер удвоенного размера, ведь я заранее не знаю, сколько байт нужно будет эскапировать.
Можно и на лету эскапировать и не потребуется двойной буфер, если уж память жалко.
Про простоту кода, это мое субъективное мнение, доказать я её не пытаюсь. Однозначно crc нужно всегда это да.
Код проще? Спорный вопрос.
Для эскейп-кодирования отправляемого сообщения мне в худшем случае нужен буфер удвоенного размера, ведь я заранее не знаю, сколько байт нужно будет эскапировать.
Вы читали мой код, в частности функцию tx_cb? Всё кодирование при отправке реализуется средствами конечного автомата, при этом его алгоритм проще некуда. Так-же и при приеме. В буфере лежат только полезные данные.
Да и в чем сложность? Crc не сошлось — цикл для поиска старта, сдвиг массива (один вызов std::rotate), запускаем основной автомат набора пакета.
Сложность в объеме и скорости выполнения кода. На стороне ПК это рабочий вариант, но не в МК.
В некоторых МК у модуля UART есть прерывание IDLE, наступает когда обнаружена пауза в потоке данных. Можно было бы использовать его и не использовать Esc-кодирование, но в STM32F7 нет такого прерывания у UARTа.
Вы читали мой код, в частности функцию tx_cb? Всё кодирование при отправке реализуется средствами конечного автомата, при этом его алгоритм проще некуда. Так-же и при приеме. В буфере лежат только полезные данные.
Окей, тут согласен, сплоховал. Эта проблема была лично у меня, потому что я вынужден был пользоваться существующим интерфейсом для доступа к UART'у, который принимал массив и размер (т.е. массив должен быть эскапирован).
Сложность в объеме и скорости выполнения кода. На стороне ПК это рабочий вариант, но не в МК.
Как вы поняли, что для МК это не рабочий вариант?
Мы ведь с вами говорим про Cortex-M, а не про PIC восьмибитный; тут и памяти вполне достаточно и скорости.
Мой опыт показывает у кортекса вполне хватит сил сделать еще пару циклов, а разницу в сотни микросекунд вы вряд ли заметите. Я ведь такой подход предлагаю не из теоретических соображений, а потому что сам им вполне успешно пользуюсь.
А уж STM32F7 тактовые за 200 МГц! Это ж почти Пентиум 2 :)
Но не вижу ничего плохого в использовании таких алгоритмов в рабочих проектах.
Отладка микроконтроллеров ARM Cortex-M по UART Часть 2