STM32F103 & Arduino IDE

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

b707, ну с прерываниями оно, наверное, так и должно быть. Но можно и без прерываний тоже самое сделать. Один таймер "мастер" считает некоторое кол-тактов  разрешая в это время работу другому, а потом некоторое кол-во запрещая. Другой просто генерит 1МГц, подчиняясь указанием "мастера" когда можно генерить, когда нельзя. Пример, тут 10 микросекунд разрешено и 5 запрещено. На осцилле аккуратные пачки по 10 импульсов.

void setup() {
pinMode(PB0, PWM); // описываем пин PB0( Timer3 CH3) как PWM
TIMER4_BASE->SMCR=1<<7;
TIMER4_BASE->PSC=0; 
TIMER4_BASE->ARR=720+360 -1;//10 тактов разрешать работу tim3, 5 Тактов нет
TIMER4_BASE->CCR1=360-1;
TIMER4_BASE->CR2=(1<<6);  //MMS:001(Enable)
TIMER4_BASE->CCMR1=(1<<6)|(1<<5)|(1<<4);//PWM mode 
TIMER3_BASE->PSC=0; 
TIMER3_BASE->SMCR=(1<<5)|(1<<4)|(1<<2)|(1<<0);//TS:011  SMS:101
TIMER3_BASE->ARR=71;
TIMER3_BASE->CCMR2=(1<<6)|(1<<5)|(0<<4);//PWM mode 
TIMER3_BASE->CCER=(1<<9)|(1<<8);//cc3e enable default
TIMER3_BASE->CCR3=36;
TIMER4_BASE->CR1=(1<<0);// старт 
TIMER3_BASE->CR1=(1<<0);//start timer3

}

void loop() {}

 

b707
Offline
Зарегистрирован: 26.05.2017

dimax, спасибо, о таком варианте не подумал.

Попробовал, все отлично, четкие пачки по 138 импульсов. Отмечу только важные нюансы в верхнем коде:

- для точной синхронизации слейв  должен запускаться до Мастера (строчки 15 и 16 нужно поменять местами)

- значение регистра сранения задется точно, а не N-1, в отличии от прескалера или ARR. В данном случае это важно. так как разница в единицу дает рассинхронизацию мастера и слейва, которая накапливается от цикла к циклу, меняя фазу сигнала

Когда это поправил - все работает очень четко, число импульсов строго одинаковое, все задержки стабильные.

 

Но проблемы еще остались. По ходу программы мне нужно эту связку таймеров включать и выключать. Если просто выключить мастер таймер, а потом запустить заново, обнулив при старте счетчики мастера и слейва - в первой пачке будет 141 импульс. Не знаю почему так, но видимо придется при каждом рестарте таймера конфигурировать все регистры заново.

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

b707, а можно и на одном таймере и ДМА. Таймер тактирует ДМА, а тот кидает ему в регистр CCR каждый раз новое значение, задающее скважность. Когда сигнал не нужен даём нулевую скважность. В итоге имеем ровные пачки импульсов:

 

#include <dma_private.h>
uint32_t mass_ccr[]{36,36,36,36,36,36,36,36,36,36,0,0,0,0,0}; //
void setup() {
pinMode(PB0, PWM); // описываем пин PB0( Timer3 CH3) как PWM
TIMER3_BASE->DIER=(1<<8);//Update DMA request enable
TIMER3_BASE->PSC=0; 
TIMER3_BASE->ARR=71;
TIMER3_BASE->CCMR2=(1<<6)|(1<<5)|(1<<3);//PWM mode, Preload CCR3 
TIMER3_BASE->CCER=(1<<8);//cc3e enable default
TIMER3_BASE->CCR3=36;
TIMER3_BASE->CR1|=(1<<0);//start timer3
dma_init(DMA1);
dma_setup_transfer(DMA1,DMA_CH3,(uint32_t*)&TIMER3_BASE->CCR3,DMA_SIZE_32BITS, (uint32_t*)mass_ccr, DMA_SIZE_32BITS, (DMA_MINC_MODE|DMA_CIRC_MODE|DMA_FROM_MEM) );
dma_set_num_transfers(DMA1, DMA_CH3, 15);
dma_enable(DMA1, DMA_CH3);
}

void loop() {}

 

b707
Offline
Зарегистрирован: 26.05.2017

dimax пишет:

b707, а можно и на одном таймере и ДМА.

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

Komandir
Komandir аватар
Offline
Зарегистрирован: 18.08.2018

b707 пишет:

...максимально быстро ... ДМА ...

Знак "=" поставить никак нельзя к сожалению ...

b707
Offline
Зарегистрирован: 26.05.2017

Komandir пишет:

b707 пишет:

...максимально быстро ... ДМА ...

Знак "=" поставить никак нельзя к сожалению ...

да, знаю.... ногодрыгом быстрее.

Вопрос - а почему у меня упорно засело в голове, что сконфигурировать ДМА-перенос из памяти в GPIO можно только на таймере1 ? - сиху читаю даташит, не вижу таких ограничений

 

добавка - запустил на таймере3 - все отлично работает. Еще раз спасибо dimax за пример.

Все-таки не понятно, почему "в интернетах" упорно натыкаюсь на сообщения, что работать с GPIO можно тактируя ДМА исключительно первым таймерм?

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

b707, касательно  мк F401 я и сам про это писал , а вот с F103 уже не помню была ли такая особенность.

b707
Offline
Зарегистрирован: 26.05.2017

dimax пишет:

b707, касательно  мк F401 я и сам про это писал , а вот с F103 уже не помню была ли такая особенность.

На F103 работает. Надо будет на 401 проверить.

В даташите на F401 вроде тоже не вижу запрета на использование DMA1 для загрузки данных в регистры GPIO.

b707
Offline
Зарегистрирован: 26.05.2017

вопрос про F401.

Черная плата BlackPill с Али, контроллер STM32F401CC

Вот такой простенький скетч


#define pin_A PC13
uint8_t   *aa;
uint16_t allocsize = 60000;


void scan_running_dmd_R() {
  digitalWrite(pin_A, !digitalRead(pin_A));
}

void setup() {
  pinMode(pin_A, OUTPUT);
  aa = (uint8_t*)malloc(allocsize);
  memset(aa, 0, allocsize);

}

void loop() {
 scan_running_dmd_R();
 delay(200);
}

нормально работает(мигает лампочкой), пока размер куска отведенной динамической памяти не превышает примерно 61-62к, потом виснет, что вполне согласуется с заявленным обьемом RAM 64к

Но если мигать лампой через прерывание таймера:

#define MY_TIM Timer3
#define pin_A PC13
uint8_t   *aa;
uint16_t allocsize = 600;


void scan_running_dmd_R() {
  digitalWrite(pin_A, !digitalRead(pin_A));
}

void setup() {
 pinMode(pin_A, OUTPUT);
 aa = (uint8_t*)malloc(allocsize);
 memset(aa, 0, allocsize);
 MY_TIM.init();
 MY_TIM.pause(); 
 MY_TIM.setPeriod(200000); 
 MY_TIM.attachInterrupt(0, scan_running_dmd_R); 
 MY_TIM.refresh(); 
 MY_TIM.resume(); 
}

void loop() {
 
}

все виснет уже при попытке выделить динамическю память всего в 1к ! 800 байт работает - 1000 - уже нет.

WTF?

аддон Кларка.

У кого есть F401 - прверьте в обоих аддонах, плиз

b707
Offline
Зарегистрирован: 26.05.2017

Итак, дополнение по проблемам из сообщения #509.

Пытаюсь запустить готовый проект, работающий на F103 - на MK F401.

1 malloc() не работает. Попытки выделить функцией malloc() динамическую область памяти более чем 50-100 байт - терпят неудачу. Причем сама функция, как водится, ошибок не вызывает - но попытки обращения к выделенной памяти приводят к зависанию программы. При этом статически можно выделить память практически любого размера вплоть до полного размера RAM.

2. функция pinMode() не работает в конструкторе глобального обьекта, при этом в setup() и в основной программе работает. Возможно, причина в том, что в конструкторе еще "слишком рано" и инициализация портов GPIO не закончена, а к сетапу она завершается. Пробовал вставлять свою инициализацию шины и GPIO порта до первого pinMode() - не помогло.

это не считая несовместимости по регистрам BRR и BSRR, которую я легко обошел.

Интересно, кто-нибудь еще с пп 1 и 2 сталкивался?

 

 

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

b707 пишет:

2. функция pinMode() не работает в конструкторе глобального обьекта, при этом в setup() и в основной программе работает. Возможно, причина в том, что в конструкторе еще "слишком рано" и инициализация портов GPIO не закончена, а к сетапу она завершается.

Именно.

Собственно, не "не закончена", а "еще не начиналась". По стандарту сначала происходит инициализация всех глобальных переменных, и только потом - выполняется первый исполняемый оператор программы, в данном случае - блока инициализации железа.

Поэтому инициализацию железа в Ардуино принято производить не в конструкторе, а в специальном методе init() или setup().

 

PS. Кстати, malloc() часом вызывается не из конструктора?

rkit
Offline
Зарегистрирован: 23.11.2016

andriano пишет:

По стандарту сначала происходит инициализация всех глобальных переменных, и только потом - выполняется первый исполняемый оператор программы, в данном случае - блока инициализации железа.

Нет. Порядок запуска программы полностью под контролем программиста. Ничто не мешает написать что угодно перед "call static constructors"

/* Call the clock system initialization function.*/
  bl  SystemInit   
/* Call static constructors */
    bl __libc_init_array
/* Call the application's entry point.*/
  bl  main
  bx  lr    

 

b707
Offline
Зарегистрирован: 26.05.2017

andriano пишет:

Собственно, не "не закончена", а "еще не начиналась". По стандарту сначала происходит инициализация всех глобальных переменных, и только потом - выполняется первый исполняемый оператор программы, в данном случае - блока инициализации железа.

Поэтому инициализацию железа в Ардуино принято производить не в конструкторе, а в специальном методе init() или setup().

как ни странно, на F103 внутри конструктора pinMode() отрабатывает нормально

Мне, конечно, нетрудно всю инициализацию железа перетащить в class.init() - но хотелось бы понять, почему и на ардуино Нано/Мега. и на обычном блюпилле это все работало и в конструкторе, а в F401 нет

 

Цитата:
PS. Кстати, malloc() часом вызывается не из конструктора?

именно там.

 

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

rkit пишет:

Нет. Порядок запуска программы полностью под контролем программиста. Ничто не мешает написать что угодно перед "call static constructors"

/* Call the clock system initialization function.*/
  bl  SystemInit   
/* Call static constructors */
    bl __libc_init_array
/* Call the application's entry point.*/
  bl  main
  bx  lr    

 

И что это было?

 

Для тех, кто в танке: в Ардуино используется язык программирования С++, и речь в данном контексте шла именно о нем.

rkit
Offline
Зарегистрирован: 23.11.2016

andriano пишет:

И что это было?

 

Для тех, кто в танке: в Ардуино используется язык программирования С++, и речь в данном контексте шла именно о нем.

в Ардуино используется ядро, написанное программистом, и содержащее такой фрагмент кода. Если бы программист напряг мозги, он бы настроил ядро правильно.

rkit
Offline
Зарегистрирован: 23.11.2016
b707
Offline
Зарегистрирован: 26.05.2017

andriano пишет:

PS. Кстати, malloc() часом вызывается не из конструктора?

все-таки уточните, что вы имели в виду?

b707
Offline
Зарегистрирован: 26.05.2017

сорри, но видимо я до этого еще не дорос... Единственное, что мне пришло в голову - сравнить этот файл из ветки STM32F4 с аналогичным для STM32F1, чтобы попытаться понять, почему проблема с инициализацией возникает только в STM32F4.

Но в ветке STM32F1 аналогичного файла вообще нет... или этот код где-то еще, или как-то обходятся без указания порядка инициализации...

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

rkit пишет:

andriano пишет:

И что это было?

 

Для тех, кто в танке: в Ардуино используется язык программирования С++, и речь в данном контексте шла именно о нем.

в Ардуино используется ядро, написанное программистом, и содержащее такой фрагмент кода. Если бы программист напряг мозги, он бы настроил ядро правильно.

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

 

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

b707
Offline
Зарегистрирован: 26.05.2017

andriano, нафига вам ругаться с РКИТом?

Я, смотрите, старательно вас развожу, задаю каждому вопрос отдельно :) Ответьте лучше мне про malloc() в конструкторе...

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

b707 пишет:

andriano, нафига вам ругаться с РКИТом?

Я, смотрите, старательно вас развожу, задаю каждому вопрос отдельно :) Ответьте лучше мне про malloc() в конструкторе...

Ну, стартовая настройка МК предполагает помимо инициализации периферии также настройку стека, кучи и пр. Опять же, при инициализации аппаратуры, как правило, возникает необходимость в выделении памяти. А выделение памяти стандартным образом из кучи сопровождается накладными расходами. Почему бы, скажем, не зафиксировать буфер Serial по стандартному адресу в обход менеджера кучи?

В общем, нужно либо разбираться с тонкостями реализации, а они, эти тонкости, могут существенно различаться для разных камней (хотя бы потому, что авторы кода - разные), либо попытаться выработать общие подходы, которые будут работать независимо от того, как реализовал блок инициализации тот или иной автор. Отказ от инициализации и распределения памяти в конструкторе и применение вместо этого явные методы инициализации (init или setup) я рассматриваю в качестве таких подходов. Потому как считаю, что следует выбирать камень под задачу, а задачи у меня бывают ох какими разными. Следовательно, детальное изучение особенностей реализации блока инициализации для каждого конкретного камня, на мой взгляд, непроизводительная трата времени.

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

rkit
Offline
Зарегистрирован: 23.11.2016

b707 пишет:

сорри, но видимо я до этого еще не дорос... Единственное, что мне пришло в голову - сравнить этот файл из ветки STM32F4 с аналогичным для STM32F1, чтобы попытаться понять, почему проблема с инициализацией возникает только в STM32F4.

Но в ветке STM32F1 аналогичного файла вообще нет... или этот код где-то еще, или как-то обходятся без указания порядка инициализации...

Надо детально смотреть весь код. Это много где может быть реализовано, на самом деле. Я просто привел пример того, что можно элементарно выполнять код до инициализации глобальных переменных.

ssss
Offline
Зарегистрирован: 01.07.2016

b707 пишет:

Все-таки не понятно, почему "в интернетах" упорно натыкаюсь на сообщения, что работать с GPIO можно тактируя ДМА исключительно первым таймерм?

Патамушта в тырнетах тупо копировали у друг друга... без малейшего понимания... что к чему...

Смотреть надо референс... а не даташит... Там есть таблица эвентов для ДМА...

И кстати... Там хоть и написано... что можно юзать только один эвент на канал... но на самом деле... если эвенты синхронизированы и не одновременны... то можно юзать и несколько... если это нужно и соответствует задаче...

И ещё... из того что ещё помню... В Ф4хх... два модуля ДМА... один из них не работает с ЖПИО по определению...

Серия 32Ж тоже не работает по ДМА с ЖПИО... от рождения своего...

+++++++++

И да... ДМА не тактируется таймером... он получает эвенты от таймера...

b707
Offline
Зарегистрирован: 26.05.2017

Такой вопросик - отладку в каком-нибудь из аддонов есть возможность использовать? Ну там расставить точки останова, посмотреть значения переменных во время выполнения?

Понятно, что не в Ардуино ИДЕ, а например в V-Micro ?

nik182
Offline
Зарегистрирован: 04.05.2015

В родном STMовском отлаживает. А мне больше нравиться в IAR. Там вообще всё можно смотреть и менять на любом шаге.  

xDriver
xDriver аватар
Offline
Зарегистрирован: 14.08.2015

да по моему во всех есть, кроме Ардуино ИДЕ, я вот родной CubeIDE пользуюсь, не понимаю что все так от нее плюются.

b707
Offline
Зарегистрирован: 26.05.2017

nik182 пишет:

В родном STMовском отлаживает. А мне больше нравиться в IAR. Там вообще всё можно смотреть и менять на любом шаге.  

вчера весь вечер протрахался с этим, в V-micro c кларковским аддоном так и не смог запустить... То OpenOCD сервер не запускается, пишет "неверные аргументы", Как ни искал - не нашел, где эти аргументы менять...

Потом вообще Ст-линк перестал определяться, насилу вылечил...

Возможно дело не в аддоне и не в Микро, а в том что у меня винда уже слишком замусорена... Например, у меня два компа, на одном СТ-линк работает, а на другом вообще никак

b707
Offline
Зарегистрирован: 26.05.2017

Запустил-таки отладку в Vmicro версии 19.30 для блюпила с кларковским аддоном.

Необходимые настройки для stm32F103C8 и St-link-v2

- В опциях проекта Vmicro включить Micro Debug - Full

- Поменять опции компиляции с оптимизации на Debug -g

 - В файл boards в папке ....Arduino\hardware\Arduino_STM32\STM32F1\ в секцию genericSTM32F103C добавить строчку:

genericSTM32F103C.build.openocdscript=board/stm32f103c8t6mini.cfg

(обратите внимание, что этот конфиг только для комбинации stm32F103C8 + St-link-v2, под другой МК и другой программатор нужно подбирать конфиг отдельно)

Единственное, что осталось не до конца понятным - после загрузки скетча и запуска отладчика обязательно нужно вручную нажать ресет на плате, иначе отладка не стартует. Кто пользуется отладкой в Вмикро - поделитесь, у вас тоже так? Может есть какой-то способ заставить плату перегружаться автоматом?

И еще - некоторые переменные в Watch посмотреть нельзя - пишет "optimezed out". Правильно ли я понял, что это означает что переменная выкинута оптимизатором как неиспользуемая? - странно, я думал в дебаг-режиме всякая оптимизация отключается...

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

b707 пишет:

И еще - некоторые переменные в Watch посмотреть нельзя - пишет "optimezed out". Правильно ли я понял, что это означает что переменная выкинута оптимизатором как неиспользуемая? - странно, я думал в дебаг-режиме всякая оптимизация отключается...

1. Переменная выкинута только из памяти, т.е. на нее не распределяется место в стеке/куче. Вместо этого переменная хранится в регистрах и, соответственно, не имеет адреса.

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

b707
Offline
Зарегистрирован: 26.05.2017

Да, насчет переменных уже разобрался, "optimized out" означает, что переменная относится к другому блоку программы и в этом недоступна. Сейчас столкнулся с другой проблемой - в режиме отладки выполнение программы происходит в сотни, а то и в тысячи раз медленнее, чем в релизе, реально просто не могу дойти до места, которое нужно отлаживать. О том, чтобы запускать отладку на том же коде, что и релиз - нечего и думать, приходится убирать все лишнее, сокращать циклы, выкидывать задержки и миллис.

Понимаю, что так быть не должно... пытаюсь найти причину.

nik182
Offline
Зарегистрирован: 04.05.2015

На этот случай в отладчиках есть точка останова. До неё обычно в режиме отладки программа добирается с нормальной скоростью.

b707
Offline
Зарегистрирован: 26.05.2017

nik182 пишет:

На этот случай в отладчиках есть точка останова. До неё обычно в режиме отладки программа добирается с нормальной скоростью.

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

Я уже все прерывания остановил - все равно . "Продолжить до сдедующей точки останова" - идет со скоростью примерно 10-20 ассемблерных инструкций в секунду. то есть очень медленно. Если идти по шагам - скорость нормальная, если не считать того, что каждую строчку пройти надо вручную.

Нашел описание этого бага в инете в паре мест, решения там нет

ссылка https://www.openstm32.org/forumthread1369

b707
Offline
Зарегистрирован: 26.05.2017

добил, все работает.

Для информации - в настройках аддона в режиме Debug стоит какая-то странная опция компилятора -Og

В мане GCC я такой опции не нашел, написано только, что опции оптимизации -Ox можно комбинировать с опциями дебага -gx. но что означает комбинация -Og - не написано.

В итоге поменял эту непонятную опцию на комбинацию -O0 -g3 -ggdb и все поехало.

Возможно опция -g3 избыточна в моем случае, но пока размер прошивки не превышает флеша МК - это не особо важно.

Надеюсь, кому-то эта информация будет полезной.

a5021
Offline
Зарегистрирован: 07.07.2013
-Og
Optimize debugging experience. -Og should be the optimization level of choice for the standard edit-compile-debug cycle, offering a reasonable level of optimization while maintaining fast compilation and a good debugging experience. It is a better choice than -O0 for producing debuggable code because some compiler passes that collect debug information are disabled at -O0.

Like -O0, -Og completely disables a number of optimization passes so that individual options controlling them have no effect. Otherwise -Og enables all -O1 optimization flags except for those that may interfere with debugging:

-fbranch-count-reg  -fdelayed-branch 
-fdse  -fif-conversion  -fif-conversion2  
-finline-functions-called-once 
-fmove-loop-invariants  -fmove-loop-stores  -fssa-phiopt 
-ftree-bit-ccp  -ftree-dse  -ftree-pta  -ftree-sra

 

b707
Offline
Зарегистрирован: 26.05.2017

продолжаю разбираться с F401 в аддоне Кларка. Хочется понять, почему при попытке выделить даже минимальный блок памяти с помощью malloc() все виснет?

Есть те, кто понимает в ld скриптах? Вот скрипт от F401 из аддона Кларка:

/*
 * Linker script for libmaple.
 *
 * Original author "lanchon" from ST forums, with modifications by LeafLabs.
 */

OUTPUT_FORMAT ("elf32-littlearm", "elf32-bigarm", "elf32-littlearm")

/*
 * Configure other libraries we want in the link.
 *
 * libgcc, libc, and libm are common across supported toolchains.
 * However, some toolchains require additional archives which aren't
 * present everywhere (e.g. ARM's gcc-arm-embedded releases).
 *
 * To hack around this, we let the build system specify additional
 * archives by putting the right extra_libs.inc (in a directory under
 * toolchains/) in our search path.
 */
GROUP(libgcc.a libc.a libm.a)
INCLUDE extra_libs.inc

/*
 * These force the linker to search for vector table symbols.
 *
 * These symbols vary by STM32 family (and also within families).
 * It's up to the build system to configure the link's search path
 * properly for the target MCU.
 */
INCLUDE vector_symbols.inc

/* STM32 vector table. */
EXTERN(__stm32_vector_table)

/* C runtime initialization function. */
EXTERN(start_c)

/* main entry point */
EXTERN(main)

/* Initial stack pointer value. Relocated to RAM */
EXTERN(__msp_init)
PROVIDE(__msp_init = ORIGIN(ram) + LENGTH(ram));

/* Reset vector and chip reset entry point */
EXTERN(__start__)
ENTRY(__start__)
PROVIDE(__exc_reset = __start__);

/* Heap boundaries, for libmaple */
EXTERN(_lm_heap_start);
EXTERN(_lm_heap_end);

SECTIONS
{
    .text :
      {
        __text_start__ = .;
        /*
         * STM32 vector table.  Leave this here.  Yes, really.
         */
        *(.stm32.interrupt_vector)

        /*
         * Program code and vague linking
         */
        *(.text .text.* .gnu.linkonce.t.*)
        *(.plt)
        *(.gnu.warning)
        *(.glue_7t) *(.glue_7) *(.vfp11_veneer)

        *(.ARM.extab* .gnu.linkonce.armextab.*)
        *(.gcc_except_table)
        *(.eh_frame_hdr)
        *(.eh_frame)

        . = ALIGN(4);
        KEEP(*(.init))

        . = ALIGN(4);
        __preinit_array_start = .;
        KEEP (*(.preinit_array))
        __preinit_array_end = .;

        . = ALIGN(4);
        __init_array_start = .;
        KEEP (*(SORT(.init_array.*)))
        KEEP (*(.init_array))
        __init_array_end = .;

        . = ALIGN(0x4);
        KEEP (*crtbegin.o(.ctors))
        KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors))
        KEEP (*(SORT(.ctors.*)))
        KEEP (*crtend.o(.ctors))

        . = ALIGN(4);
        KEEP(*(.fini))

        . = ALIGN(4);
        __fini_array_start = .;
        KEEP (*(.fini_array))
        KEEP (*(SORT(.fini_array.*)))
        __fini_array_end = .;

        KEEP (*crtbegin.o(.dtors))
        KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors))
        KEEP (*(SORT(.dtors.*)))
        KEEP (*crtend.o(.dtors))
      } > REGION_TEXT

    /*
     * End of text
     */
    .text.align :
      {
        . = ALIGN(8);
        __text_end__ = .;
      } > REGION_TEXT

    /*
     * .ARM.exidx exception unwinding; mandated by ARM's C++ ABI
     */
    __exidx_start = .;
    .ARM.exidx :
      {
        *(.ARM.exidx* .gnu.linkonce.armexidx.*)
      } > REGION_RODATA
    __exidx_end = .;

    /*
     * Read-only data
     */
    .rodata :
      {
        *(.rodata .rodata.* .gnu.linkonce.r.*)
        /* .USER_FLASH: We allow users to allocate into Flash here */
        *(.USER_FLASH)
        /* ROM image configuration; for C startup */
        . = ALIGN(4);
        _lm_rom_img_cfgp = .;
        LONG(LOADADDR(.data));
        /*
         * Heap: Linker scripts may choose a custom heap by overriding
         * _lm_heap_start and _lm_heap_end. Otherwise, the heap is in
         * internal SRAM, beginning after .bss, and growing towards
         * the stack.
         *
         * I'm shoving these here naively; there's probably a cleaner way
         * to go about this. [mbolivar]
         */
        _lm_heap_start = DEFINED(_lm_heap_start) ? _lm_heap_start : __data_end__;
        _lm_heap_end   = DEFINED(_lm_heap_end) ? _lm_heap_end : __msp_init;
      } > REGION_RODATA

    /*
     * .data
     */
    .data :
      {
        . = ALIGN(8);
        __data_start__ = .;

        *(.got.plt) *(.got)
        *(.data .data.* .gnu.linkonce.d.*)

        . = ALIGN(8);
        __data_end__ = .;
      } > REGION_DATA AT> REGION_RODATA

    /*
     * .bss
     */
    .bss :
      {
        . = ALIGN(8);
        __bss_start__ = .;
        *(.bss .bss.* .gnu.linkonce.b.*)
        *(COMMON)
        . = ALIGN (8);
        __bss_end__ = .;
        _end = __bss_end__;
      } > REGION_BSS

    /*
     * Debugging sections
     */
    .stab 0 (NOLOAD) : { *(.stab) }
    .stabstr 0 (NOLOAD) : { *(.stabstr) }
    /* DWARF debug sections.
     * Symbols in the DWARF debugging sections are relative to the beginning
     * of the section so we begin them at 0.  */
    /* DWARF 1 */
    .debug          0 : { *(.debug) }
    .line           0 : { *(.line) }
    /* GNU DWARF 1 extensions */
    .debug_srcinfo  0 : { *(.debug_srcinfo) }
    .debug_sfnames  0 : { *(.debug_sfnames) }
    /* DWARF 1.1 and DWARF 2 */
    .debug_aranges  0 : { *(.debug_aranges) }
    .debug_pubnames 0 : { *(.debug_pubnames) }
    /* DWARF 2 */
    .debug_info     0 : { *(.debug_info .gnu.linkonce.wi.*) }
    .debug_abbrev   0 : { *(.debug_abbrev) }
    .debug_line     0 : { *(.debug_line) }
    .debug_frame    0 : { *(.debug_frame) }
    .debug_str      0 : { *(.debug_str) }
    .debug_loc      0 : { *(.debug_loc) }
    .debug_macinfo  0 : { *(.debug_macinfo) }
    /* SGI/MIPS DWARF 2 extensions */
    .debug_weaknames 0 : { *(.debug_weaknames) }
    .debug_funcnames 0 : { *(.debug_funcnames) }
    .debug_typenames 0 : { *(.debug_typenames) }
    .debug_varnames  0 : { *(.debug_varnames) }

    .note.gnu.arm.ident 0 : { KEEP (*(.note.gnu.arm.ident)) }
    .ARM.attributes 0 : { KEEP (*(.ARM.attributes)) }
    /DISCARD/ : { *(.note.GNU-stack) }
}

Обратите внимание на строчки 152 и 153, которые устанавливают границы кучи.  Верх кучи установлен на метку __msp_init, которая в строке 43 приравнена верху RAM. Тут вроде все хорошо.

А вот низ кучи указывает на окончание секции .data (на метку __data_end__) - а ведь секция data располается не в RAM. а во флеше, да к тому же весьма далеко от адресов, по которым в едином пространстве адресов СТМ расположена оперативка.  - Не ошибка ли это?

Если сравнить этот файл с аналогичным для блюпилл,(там malloc() работает) - у блюпилл куча располается между верхом  RAM и секцией bss - как описано во всех учебниках.

Короче, я просто взял и заменил в строке 152 метку __data_end__ на __bss_end__  :

_lm_heap_start = DEFINED(_lm_heap_start) ? _lm_heap_start : __bss_end__; 

и все заработало!

Теперь вопрос - мое исправление верное или это какой-то костыль?

 

 

b707
Offline
Зарегистрирован: 26.05.2017

a5021 пишет:

-OgOtherwise -Og enables all -O1 optimization flags except for those that may interfere with debugging:
-fbranch-count-reg  -fdelayed-branch 
-fdse  -fif-conversion  -fif-conversion2  
-finline-functions-called-once 
-fmove-loop-invariants  -fmove-loop-stores  -fssa-phiopt 
-ftree-bit-ccp  -ftree-dse  -ftree-pta  -ftree-sra

 

a5021, спасибо за инфо. Судя по выделенному куску, с использованием -Og некоторая оптимизация продолжает применяться. Вероятно, именно это и приводило к конфликту с дебаггером, раз при полном отключении оптимизации опцией -O0 дебаггер начал работать.

 

b707
Offline
Зарегистрирован: 26.05.2017

Напомните плиз, кто-то писал, что аддоны СТМ и Кларка не ставятся одновременно. Есть какие-то хаки, как их заставить не мешать друг другу?

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

b707, это я писал в начале темы, были глюки, не помню уже какие конкретно. Может за давностью времени уже не актуально..

b707
Offline
Зарегистрирован: 26.05.2017

dimax пишет:

b707, это я писал в начале темы, были глюки, не помню уже какие конкретно. Может за давностью времени уже не актуально..

Димакс, спасибо за отклик. Попробую сам.

А по линкер скриптам (сообщение 535) не подскажете?

nik182
Offline
Зарегистрирован: 04.05.2015

У меня стоят оба рядом. Работает тот что выбрал. Глюки связаны только с разной семантикой выражений. НАL не дружит с Кларком.

b707
Offline
Зарегистрирован: 26.05.2017

nik182. спасибо

Atamanu
Offline
Зарегистрирован: 07.12.2021
Добрый вечер.
Пытаюсь перевести код с Arduino Nano для запуска на STM32F103... Может кто поможет...!
Заранее спасибо.
#include <iBUStelemetry.h>

iBUStelemetry telemetry(4);

byte i;

void setup(){
  telemetry.begin(115200);
  telemetry.addSensor(2);
}

void loop(){
  telemetry.setSensorMeasurement(1, i++);
  delay(1000);
}

 

 

nik182
Offline
Зарегистрирован: 04.05.2015

Не получится легко это сделать. Библиотека завязана на хардверные прерывания и их надо переопределять с авр на стм. Или искать библиотеку где это уже сделали.

Atamanu
Offline
Зарегистрирован: 07.12.2021
Спасибо за ответы.
Кто-то сделал. Но... секрет.
ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

ssss пишет:

Бред околособачий! CPU в гаджетах это одно, а MCU в новых разработках это другое. Пройдёт ещё 3-5 лет и атмэла в новых разработках вообще не будет, от слова совсем.

...прошло 3-5 лет...

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

вопрос, кому-нибудь удалось адаптировать библиотеку UTFT под STM32F103?

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

А что, разве она еще не адаптирована?

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

andriano пишет:

А что, разве она еще не адаптирована?

из тех, что нашёл, нет, сам удивляюсь

 #error "Unsupported ARM MCU!"

 

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

Ну, не знаю, в своих проектах я пользуюсь исключительно своими библиотеками, поэтому опыта работы с более или менее стандартными не имею.

Хотя, стандартные я нередко использую, когда надо быстро убедиться в работоспособности только что полученного экрана. А т.к экраны я последнее время покупаю в основном 3-вольтовые, думаю, что поддержка stm32f103 мне, скорее всего, где-то попадалась. На чем-то же я их проверял!

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

andriano пишет:

На чем-то же я их проверял!

я что за UTFT вцепился, там поддержка большого количества контроллеров, лёгкость перехода на экран иного размера