30 Нояб., 2020, 09:58

Не важно, есть ли у тебя стиль, репутация, или деньги, если у тебя нет доброго сердца, ты ничего не стоишь.

Луи де Фюнес


STM32 :: пытаемся разобраться

Автор zenon, 22 Окт., 2020, 00:20

« предыдущая - следующая »

zenon

Начал. :)
Вот только не пойму BOOT1 тут есть?

Slabovik

22 Окт., 2020, 16:51 #1 Последнее редактирование: 22 Окт., 2020, 20:29 от Slabovik
Да, надо бы тему по STM32 поиметь. Контроллеры популярные, а для тех, кто хочет на них перейти, необходимы ответы на самые дилетантские вопросы.

Например, о выборе способа внутрисхемного программирования. Достаточно ли сигналов SWDIO и SWCLK, которые имеются на дешёвом ST-Link v2.

STM32_pgm.png

Мнения разные, вот, например, одно из таких: Как прошить чип STM32
скрытый текст
Для подключения ST-LINK на STM32F103RB задействованы следующие выводы:

    SWDIO (Serial Wire Data Input/Output) - PA13
    SWCLK (Serial Wire Clock) - PA14
    TRACESWO (Trace of Serial Wire Output, та самая SWO) - PB3

Для работы через SWIM/SWD нужно-то всего два проводка, не забываем про обязательное соединение земли по всем подключенным устройствам. TRACESWO можно не подключать, особенно если данной функцией вы не пользуетесь, да и для отладки она, а не для загрузки прошивки.
[свернуть]
BOOT1 на PB2, похоже, выведен, а BOOT0 - он отдельной ногой. Хотя вот, насколько я понимаю, он всего лишь область памяти подставляет под "старт", как это делали, например, Радио-86, Орион-128 и многие другие. Чтобы там стал быть загрузчик, его надо туда записать? Или что-то там есть?
скрытый текст
При загрузке микроконтроллера, необходимо на вывод Boot0 микроконтроллера подать высокий уровень (3.3 В), а на вывод Boot1 низкий (0 В, соединить с землей). При выполнении этих двух условий микроконтроллер запустит прошитый на заводе в чип загрузчик.
[свернуть]
Аппнот говорит, что там что-то есть
Цитата: undefinedThe bootloader is stored in the internal boot ROM (system memory) of STM32 devices, and is programmed by ST during production.
А есть ли какое-то стандартизированное расположение пинов у разъёма программирования SWD/SWC

Также добавлю ссылку на простейший ликбез о то, чем отличаются процессоры с индесами A, R, M, а также версии ядер 0, 3, 4 и 4F

Получается, наш вариант - это процики ветки M (микроконтроллеры), а версия ядра (скорее, набора исполняемых команд) 0.

зы. Не вытерпел, обзавёлся такой платой, самоё дешёвой, что была в магазине
STM32_NUCLEO-F091RC.jpg
На борту STM32F091RCT6U (RAM:32k, Prog:256k - более чем достаточно для простых применений) + ST-Link, который можно юзать отдельно. Вот описательный даташит на эту серию плат - там расписаны коннекторы (на плате надписей недостаточно).
Общением на форуме подпитываю свою эгоистичную, склонную к самолюбованию сущность.

zenon

Даже не ожидал, что так быстро приедут.
Плату ещё не делал.
Корпус LQFP - практически тоже самое что и TQFP приложил к макетке для меги:

Slabovik

Похоже, это единственный вариант кузовов (32-ногие), у которых шаг вывода 0.8
Мне по-быстрому доступен только такой вариант.
Вопрос ещё в том, что пока я готовлю тот макет, никаких мыслей не пришло, где бы мог быть нужен именно STM...
Лично мне хочется зацепить большой экранчик (точек на 400), например e-ink, но для вывода на такое надо всё-таки ОЗУ иметь значительных размеров. Ну или внешнее подцеплять, а для внешнего надо ноги, ноги... ATMega ведь тоже прекрасно умеет с внешним ОЗУ работать (64 или 100-ногие корпуса)
Общением на форуме подпитываю свою эгоистичную, склонную к самолюбованию сущность.

zenon

Подключил SWDIO, SWCLK, питание.
Проект тестовой платы в кикаде.
> .\ST-LINK_CLI.exe -C
STM32 ST-LINK CLI v3.0.0.0
STM32 ST-LINK Command Line Interface

ST-LINK SN : 57FF6E064984485758262287
ST-LINK Firmware version : V2J23S4
Connected via SWD.
SWD Frequency = 4000K.
Target voltage = 3.3 V.
Connection mode : Normal.
Device ID:0x444
Device flash Size : 32 Kbytes
Device family :STM32F030x4/F030x6

zenon

Сегодня попробовал поморгать через Куб, - блин почти 5 килобайт для дёрганья ногой... но отладка.
Решил что надо копнуть. Вот в эту сторону.
Для линукса там всё нативно, минимум изменять надо, только:
LDSCRIPT = stm32f030f.ld
MCU = F030x6
Но у меня всё как не у людей, мне сейчас windows нужна, блин, ну и пришлось make flash сделать вот так:
flash: $(BIN)
 @echo "  FLASH  $(BIN)"
 C:\STU\ST-LINK_CLI.exe -P $(BIN) 0x8000000 -Rst
Ну и тулчейн arm конечно нужен.
А так - собрал тот файл - морзянкой мигает на PB3, 1130 байт, lss могу кинуть, нужен?
make flash у меня прикручен в Geany к F5.
Сборка F9...
Остальное пока - тёмный лес :)  :o

zenon

Всё туго пока... :)
Сижу пытаюсь понять.
Дело ещё в том, что на F030 примеров не так-то много.
Использую CMSIS.
Ну конечно ногодрыг первым делом.
В общем вот так вышло, используя задержку, которая "dummy"... назвал её delay.
#include "stm32f0.h"
void delay(uint32_t k) {
    volatile uint32_t i;
    for (i=0; i != 0x200*k; i++);
}

int main() {
    sysreset();

    RCC->AHBENR |= RCC_AHBENR_GPIOBEN;
    //    #define  RCC_AHBENR_GPIOBEN                  ((uint32_t)0x00040000)        // GPIOB clock enable

    GPIOB->MODER |= GPIO_MODER_MODER3_0;
    //      #define GPIO_MODER_MODER3          ((uint32_t)0x000000C0)
    //      #define GPIO_MODER_MODER3_0        ((uint32_t)0x00000040)
    //      #define GPIO_MODER_MODER3_1        ((uint32_t)0x00000080)
    // __IO uint32_t MODER;        /*!< GPIO port mode register,              Address offset: 0x00 */
    GPIOB->OSPEEDR |= GPIO_OSPEEDR_OSPEEDR3;
    //        #define GPIO_OSPEEDR_OSPEEDR3    ((uint32_t)0x000000C0)
    //        #define GPIO_OSPEEDR_OSPEEDR3_0  ((uint32_t)0x00000040)
    // #define GPIO_OSPEEDR_OSPEEDR3_1  ((uint32_t)0x00000080)
    // __IO uint32_t OSPEEDR;      /*!< GPIO port output speed register,      Address offset: 0x08 */

  while(1) {

        GPIOB->BSRR = GPIO_BSRR_BR_3;
        delay(1000);
        GPIOB->BSRR = GPIO_BSRR_BS_3;
        delay(1000);

  }
}

// SysTick Interrupt
void SysTick_Handler(void) {
}
В комментах немного расшифровал дефайны из stm32f030x6.h
На PB3 частота 3,76 Hz.
Надо SysTick_Handler задействовать и посмотреть как можно с ним общаться.

zenon

03 Нояб., 2020, 20:38 #7 Последнее редактирование: 03 Нояб., 2020, 20:54 от zenon
Блин, все грабли собрал, spi хардварный завёл только в кубе, и то - видеть его вижу на осциллографе - понять что он выводит - не могу... бред какой-то.
Но я его добью.
В итоге плюнул - написал всё ногодрыгом. :)
// дефайним ноги
#define latch_low()  GPIOA->BSRR |= GPIO_BSRR_BR_6; // reset
#define latch_high() GPIOA->BSRR |= GPIO_BSRR_BS_6; // set
#define data_low()  GPIOA->BSRR |= GPIO_BSRR_BR_7; // reset
#define data_high()  GPIOA->BSRR |= GPIO_BSRR_BS_7; // set
#define clock_low()  GPIOA->BSRR |= GPIO_BSRR_BR_5; // reset
#define clock_high() GPIOA->BSRR |= GPIO_BSRR_BS_5; // set

// функция отправки байта
void sspi_send_byte (uint8_t data) {
    for(int i=0; i<8; i++) {
        if  (((data>>i)&0x01)==1) data_high() else  data_low();
        clock_low();
        clock_high();
  }
}

...
    while(1) {
      latch_low();
      sspi_send_byte (0b11111110); // нижний правый
      sspi_send_byte (0b11111110); // восемь же!
      latch_high();
    }
...
Отправка восьмёрки выглядит так:
ы. Инит забыл:
    RCC->AHBENR |= RCC_AHBENR_GPIOAEN;  // GPIOA clock enable

    GPIOA->MODER    |= GPIO_MODER_MODER6_0;  // 6 = вход, 6_0 = выход, 6_1 =
    GPIOA->OSPEEDR  |= GPIO_OSPEEDR_OSPEEDR6_0; // 6 low / 6_0 medium / 6_1 high
    GPIOA->BSRR    |= GPIO_BSRR_BR_6; // Установка низкого уровня

    GPIOA->MODER    |= GPIO_MODER_MODER5_0;  // 6 = вход, 6_0 = выход, 6_1 =
    GPIOA->OSPEEDR  |= GPIO_OSPEEDR_OSPEEDR5_0; // 6 low / 6_0 medium / 6_1 high
    GPIOA->BSRR    |= GPIO_BSRR_BR_5; // Установка низкого уровня

    GPIOA->MODER    |= GPIO_MODER_MODER7_0;  // 6 = вход, 6_0 = выход, 6_1 =
    GPIOA->OSPEEDR  |= GPIO_OSPEEDR_OSPEEDR7_0; // 6 low / 6_0 medium / 6_1 high
    GPIOA->BSRR    |= GPIO_BSRR_BR_7; // Установка низкого уровня

zenon

Про выбор IDE.
Поставил System Workbench for STM32.
Основана на базе Eclipse.
Посмотрю приживётся или нет.

Slabovik

Целые выходные читал ИзиЭлектроникс - там целая подборка про STM32
http://we.easyelectronics.ru/blog/STM32/page1/
Жаль, что пока ни к чему не пришёл...
Общением на форуме подпитываю свою эгоистичную, склонную к самолюбованию сущность.

zenon

19 Нояб., 2020, 23:28 #10 Последнее редактирование: 20 Нояб., 2020, 00:13 от zenon
В общем два варианта запуска TM1637 у меня получились, хард и софт.
Хардверный отсюда.
Софтверный вот тут.
Естественно переделал чуть.
Никакого open-drain как оказалось не надо, просто настроить пины как выход и скорость их работы.
Чтение клавиатуры фэйковое, вот тут есть ещё один вариант, но его перевести в читабельный вид не осилил.
И ещё на HAL вариант.
Вот софт вариант:
#include "stm32f0.h"

// PIN PB6 = Clk // PIN PB7 = Dio
#define _tm1637ClkLow()  GPIOB->BSRR |= GPIO_BSRR_BR_6; // reset
#define _tm1637ClkHigh()  GPIOB->BSRR |= GPIO_BSRR_BS_6; // set
#define _tm1637DioLow()  GPIOB->BSRR |= GPIO_BSRR_BR_7; // reset
#define _tm1637DioHigh()  GPIOB->BSRR |= GPIO_BSRR_BS_7; // set

volatile uint32_t Tms = 0;
uint32_t cntr;

const char segmentMap[] = {
    0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, // 0-7
    0x7f, 0x6f, 0x77, 0x7c, 0x39, 0x5e, 0x79, 0x71, // 8-9, A-F
    0x00
};

#define FDEL 10

void _tm1637DelayUsec(unsigned int i) {
    for (; i>0; i--) {
        for (int j = 0; j < FDEL; ++j) {
            __asm__ __volatile__("nop\n\t":::"memory");
        }
    }
}

void _tm1637Start(void) {
    _tm1637ClkHigh();
    _tm1637DioHigh();
    _tm1637DelayUsec(2);
    _tm1637DioLow();
}

void _tm1637Stop(void) {
    _tm1637ClkLow();
    _tm1637DelayUsec(2);
    _tm1637DioLow();
    _tm1637DelayUsec(2);
    _tm1637ClkHigh();
    _tm1637DelayUsec(2);
    _tm1637DioHigh();
}

void _tm1637ReadResult(void) {
    _tm1637ClkLow();
    _tm1637DelayUsec(5);
    // while (dio); // We're cheating here and not actually reading back the response.
    _tm1637ClkHigh();
    _tm1637DelayUsec(2);
    _tm1637ClkLow();
}

void _tm1637WriteByte(unsigned char b) {
    for (int i = 0; i < 8; ++i) {
        _tm1637ClkLow();
        if (b & 0x01) {
            _tm1637DioHigh();
        }
        else {
            _tm1637DioLow();
        }
        _tm1637DelayUsec(3);
        b >>= 1;
        _tm1637ClkHigh();
        _tm1637DelayUsec(3);
    }
}

// Valid brightness values: 0 - 8.
// 0 = display off.
void tm1637SetBrightness(char brightness) {
    // Brightness command:
    // 1000 0XXX = display off
    // 1000 1BBB = display on, brightness 0-7
    // X = don't care
    // B = brightness
    _tm1637Start();
    _tm1637WriteByte(0x87 + brightness);
    _tm1637ReadResult();
    _tm1637Stop();
}

void tm1637Init(void) {
    RCC->AHBENR    |= RCC_AHBENR_GPIOBEN;  // GPIOB clock enable
    // PB6 Clk
    GPIOB->MODER  |= GPIO_MODER_MODER6_0;
    GPIOB->OSPEEDR |= GPIO_OSPEEDR_OSPEEDR6_1;
    // PB7 Dio
    GPIOB->MODER  |= GPIO_MODER_MODER7_0;
    GPIOB->OSPEEDR |= GPIO_OSPEEDR_OSPEEDR7_1;
    tm1637SetBrightness(8);
}

void tm1637DisplayDecimal(int v, int displaySeparator) {
    unsigned char digitArr[4];
    for (int i = 0; i < 4; ++i) {
        digitArr[i] = segmentMap[v % 10];
        if (i == 2 && displaySeparator) {
            digitArr[i] |= 1 << 7;
        }
        v /= 10;
    }
    _tm1637Start();
    _tm1637WriteByte(0x40);
    _tm1637ReadResult();
    _tm1637Stop();
    _tm1637Start();
    _tm1637WriteByte(0xc0);
    _tm1637ReadResult();
    for (int i = 0; i < 4; ++i) {
        _tm1637WriteByte(digitArr[3 - i]);
        _tm1637ReadResult();
    }
    _tm1637Stop();
}

void sys_tick_handler(void) { // Called when systick fires
    ++Tms;
}

void my_start_hse48_pll_3x16();

int main() {
    uint32_t TLED = 0;
    uint32_t counter = 0;
    sysreset();

    // На PA12 сидит мигалка
    RCC->AHBENR    |= RCC_AHBENR_GPIOAEN;  // GPIOA clock enable
    GPIOA->MODER  |= GPIO_MODER_MODER12_0;
    GPIOA->OSPEEDR |= GPIO_OSPEEDR_OSPEEDR12_0;

    SysTick_Config(6000, 1);

    tm1637Init();
    tm1637SetBrightness(3);

    while(1) {
        if(Tms - TLED > 99){
            if (counter<9999) counter++; else counter=0;
            TLED = Tms;
            pin_toggle(GPIOA, 1<<12);
            tm1637DisplayDecimal(counter, 0);
            if (counter==50)  tm1637SetBrightness(8);
            if (counter==100) tm1637SetBrightness(7);
            if (counter==150) tm1637SetBrightness(5);
            if (counter==200) tm1637SetBrightness(4);
            if (counter==250) tm1637SetBrightness(3);
            if (counter==300) tm1637SetBrightness(2);
            if (counter==350) tm1637SetBrightness(1);
           
        }
    } //while(1)
} // main()

При FDEL = 1 частота получилась 1.5 МГц - и оно таки работает на этой скорости. :)
Для 100 кГц FDEL = 10 у меня, тут всё зависит от тактовой частоты.
Видео.

Slabovik

20 Нояб., 2020, 09:47 #11 Последнее редактирование: 20 Нояб., 2020, 10:03 от Slabovik
http://itt-ltd.com/reference/ref_i2c.html
Цитата: undefinedпередача 8 бит данных от передатчика к приемнику завершаются дополнительным циклом (формированием 9-го тактового импульса линии SCL), при котором приемник выставляет низкий уровень сигнала на линии SDA, как признак успешного приема байта.
и даташит на TM о том же, страница 3
Цитата: undefinedTM1637 data transfer carries with answering signal ACK. For a right data transfer, an answering signal ACK is generated inside the chip to lower the DIO pin at the failing edge of the 8th clock. DIO interface wire is released at the end of the 9th clock.
Таким образом, оставляя высокий уровень на двутактном выходе в этот момент (а как его можно не оставлять?) можно получить в конце каждого байта короткое замыкание на линии SDA (DIO). Потому и используется открытый коллектор.

Выходов может быть несколько. Например, схемотехническое разделение направлений передачи сигнала на две ноги контроллера, примерно как здесь, либо перевод на время ожидания ACK вывода порта в состояние "вход с подтяжкой" (метод скользкий т.к. можно не успеть с переводом порта, да и лишние команды в цикле).
Общением на форуме подпитываю свою эгоистичную, склонную к самолюбованию сущность.

zenon

Дело в том, что если сконфигурировать порт как открытый сток нельзя подтянуть его к питанию (насколько я понял).
И если делаю так:
GPIOB->MODER  |= GPIO_MODER_MODER7_0; // пин как выход
GPIOB->OTYPER  |= GPIO_OTYPER_OT_7; // выход с открытым стоком
GPIOB->OSPEEDR |= GPIO_OSPEEDR_OSPEEDR7_1; // скорость
То получаю вот такую картинку, и естественно передача не работает.

Slabovik

Это говорит либо о наличии чрезмерной ёмкости на шине (SCL, SDA), либо о чрезмерности сопротивления резистора подтяжки.
Ёмкости, которые есть на схеме, надо бы удалить. 100 пФ оптимальны для 400 кГц, не более (по спецификации ёмкости на шине не нужны, их установка преследует другие цели).
Можно попробовать ткнуть измерителем ёмкости на линии шины (относительно Gnd) и посмотреть, сколько там. Если больше 20-25 пФ - это плохо.
Можно (нужно бы) сделать опыт.
 1. отцепить приёмник.
 2. Установить православные резисторы подтяжки с вывода шины на Vcc питания STM, сопротивлением 2,2~4,7 кОм
 3. Установить в качестве паразитных конденсаторы 100 пФ
 4. Посмотреть осциллографом, что там будет происходить при попытке вывода туда чего-либо. Должна быть достаточно красивая картина со сглаженным передним фронтом вплоть до мегагерца.
 5. Убрать конденсаторы, подключить TM и наблюдать, как изменится картинка. По результатам наблюдений делать выводы.

зы: https://qastack.ru/electronics/102611/what-happens-if-i-omit-the-pullup-resistors-on-i2c-lines
Общением на форуме подпитываю свою эгоистичную, склонную к самолюбованию сущность.

zenon

Да, согласен, опыт будет чуть позже.
По ссылке - какой ужасный перевод, аж читать сложно..  :o
И мысль пришла - мы же можем CLK сделать общую для двух линий, и повесить два модуля на три порта.

Slabovik

Можно. А шину данных нужно разделить.
Но если делать нормальную шину, нужно выбирать чипы с адресацией (если конечно нет цели работать с периферией параллельно).
Общением на форуме подпитываю свою эгоистичную, склонную к самолюбованию сущность.

zenon

Подтянул к VCC 3 кОм, конденсаторы 68 пик только нашлись, следующий номинал 220 пик, поэтому взял меньший.
Картинка 12 = 100 кГц без модуля, 13 тоже 100 кГц, но с подключенным модулем, работает нормально.
15-ая картинка - частота больше 500 кГц, модуль работает, от подключения/отключения модуля картинка не изменяется, фронты конечно похуже.
В общем картинка стала больше похожей на хардверный i2c, у него фронты похуже чем на этих картинках, но работает же, может так и должно быть.
При настройке портов в push-pull фронт конечно значительно лучше, прямоугольник отличный.
ы. Забыл сказать - при измерениях на модуле конденсаторы на линиях убраны, резисторы (10 кОм) стоят, забыл про них.

Slabovik

20 Нояб., 2020, 20:22 #17 Последнее редактирование: 20 Нояб., 2020, 20:43 от Slabovik
Осталось выкинуть конденсаторы с шин SCL SDA и начать юзать (с резистором 3.3 кОм у STM) на типовой частоте 400 кГц.
А прямоугольник для I2C не упёрся т.к. фиксация SDA присходит по спаду импульса.

p.s. Добавил картинку
Общением на форуме подпитываю свою эгоистичную, склонную к самолюбованию сущность.

zenon


Slabovik

Потому что собственная входная ёмкость TM заявляется 15 пФ, что для цифровой микросхемы вообще-то очень много. Плюс ёмкости монтажа и пр. А на "типовой схеме" ещё плюс сотня и 10 кОм, которые и делают ситуацию катастрофической.
Именно поэтому I2C на больших скоростях не гоняют.
Общением на форуме подпитываю свою эгоистичную, склонную к самолюбованию сущность.

zenon

21 Нояб., 2020, 16:36 #20 Последнее редактирование: 21 Нояб., 2020, 22:54 от zenon
Переделанная функция инициализации для открытого стока:
void tm1637Init(void) {
    RCC->AHBENR    |= RCC_AHBENR_GPIOBEN;      // GPIOB clock enable
    // PB6 Clk
    GPIOB->MODER  |= GPIO_MODER_MODER6_0;      // пин как выход
    GPIOB->OTYPER  |= GPIO_OTYPER_OT_6;        // выход с открытым стоком
    GPIOB->OSPEEDR |= GPIO_OSPEEDR_OSPEEDR6_1;
    // PB7 Dio
    GPIOB->MODER  |= GPIO_MODER_MODER7_0;
    GPIOB->OTYPER  |= GPIO_OTYPER_OT_7;        // выход с открытым стоком
    GPIOB->OSPEEDR |= GPIO_OSPEEDR_OSPEEDR7_1;
    tm1637SetBrightness(4);
}
Едем дальше, сегодня мучал кнопку.
Повесить решил её на прерывние по спаду, называется оно EXTI.
Кнопка на PA0, подтянута к VCC через 10 кОм.
Опять наткнулся на то, что для F1 куча примеров, для F0 - нет.
Нашёл пример тут.
Но грабли у меня продолжились - стандартное название обработчика EXTI0_1_IRQHandler() - у меня не заработало, тут надо учитывать, что у меня не стандартная CMSIS, и рабочая среда - Geany.
В общем - решил, название обработчика у меня оказалось exti0_1_isr().
Вот такой получился рабочий вариант:
void EXTI_Init(void) {
    RCC->APB2ENR |=RCC_APB2ENR_SYSCFGCOMPEN;        // тактирование SYSCFG
    SYSCFG->EXTICR[0] = SYSCFG_EXTICR1_EXTI1_PA;    // PA0 // Bit definition for SYSCFG_EXTICR1 register @file stm32f030x6.h
    RCC->APB2ENR &= ~RCC_APB2ENR_SYSCFGCOMPEN;
    EXTI->IMR = EXTI_IMR_MR1;                      // демаскируем прервание по 1 линии
    EXTI->FTSR = EXTI_FTSR_TR1;                    // прерывание по спаду  //разрешаем срабатывание по переднему фронту
    EXTI->RTSR = EXTI_RTSR_TR1;                    // прерывание по фронту    //разрешаем срабатывание по заднему фронту
    NVIC_EnableIRQ(EXTI0_1_IRQn);                  // разрешаем прерывание в контроллере прерываний
    NVIC_SetPriority(EXTI0_1_IRQn,0);
}

// обработка внешнего прерывания у stm32f0 прерывания 0 и 1 вместе
void  exti0_1_isr(){
    if (EXTI->PR & EXTI_PR_PR1) {  // если бит прерывания установлен
        EXTI->PR |= EXTI_PR_PR1;    // сбрасываем флаг прерывания
        counter=5000;
    }
}
Тут counter у меня считает на дисплее, при нажатии кнопки просто устанавливает другое значение.
+++
Тут есть желание разобраться с IR пультом, насколько я понимаю тут тоже можно работать через это же прерывание?
Нужен PWM input mode.

zenon

Добрался до libopencm3.
Старт и мигалка из примеров, необходимые действия для stm32f030k6t6.
Подготавливаем каталог для библиотек, пусть будет ~/stm32 и клонируем библиотеки и примеры.
# cd ~
# mkdir stm32 && cd stm32
# git clone https://github.com/libopencm3/libopencm3.git
# git clone https://github.com/libopencm3/libopencm3-examples.git
Линкуем каталог с библиотеками в каталог для библиотек с примерами, сначала удалив пустой libopencm3/ в примерах (можно скопировать, но нужно ли плодить?).
# rm -r ~/stm32/libopencm3-examples/libopencm3/
# ln -s ~/stm32/libopencm3 ~/stm32/libopencm3-examples/libopencm3
Собираем библиотеку:
# cd ~/stm32/libopencm3
# make
Создаем каталог для нашего микроконтроллера и копируем каталог miniblink от stm32f0-discovery и линкер, который потом переименовываем.
# cd ~/stm32/libopencm3-examples/examples/stm32/f0/
# mkdir stm32f030k6t6
# cp -r stm32f0-discovery/miniblink stm32f030k6t6
# cp stm32f0-discovery/stm32f0-discovery.ld stm32f030k6t6.ld
Открываем линкер:
# vim stm32f030k6t6.ld
Изменяем rom и ram на наши (32К и 4K), те так:
MEMORY
{
 rom (rx) : ORIGIN = 0x08000000, LENGTH = 32K
 ram (rwx) : ORIGIN = 0x20000000, LENGTH = 4K
}
Все.
Заходим в каталог miniblink, правим в Makefile строчку LDSCRIPT = ../stm32f030k6t6.ld, смотрим код, компилируем, прошиваем и радуемся... :)))
# cd miniblink
# vim miniblink.c


# make miniblink.stlink-flash
  FLASH  miniblink.bin
/usr/bin/st-flash write miniblink.bin 0x8000000
st-flash 1.5.1
2020-11-22T18:07:27 INFO common.c: Loading device parameters....
2020-11-22T18:07:27 INFO common.c: Device connected is: F0 small device, id 0x10006444
2020-11-22T18:07:27 INFO common.c: SRAM size: 0x1000 bytes (4 KiB), Flash: 0x8000 bytes (32 KiB) in pages of 1024 bytes
2020-11-22T18:07:27 INFO common.c: Attempting to write 500 (0x1f4) bytes to stm32 address: 134217728 (0x8000000)
Flash page at addr: 0x08000000 erased
2020-11-22T18:07:27 INFO common.c: Finished erasing 1 pages of 1024 (0x400) bytes
2020-11-22T18:07:27 INFO common.c: Starting Flash write for VL/F0/F3/F1_XL core id
2020-11-22T18:07:27 INFO flash_loader.c: Successfully loaded flash loader in sram
  1/1 pages written
2020-11-22T18:07:27 INFO common.c: Starting verification of write complete
2020-11-22T18:07:27 INFO common.c: Flash written and verified! jolly good!

make V=1 - verbose output, можно опустить.
make flash хочет сразу работать через openocd, пока вываливается с ошибкой у меня...
make bin делает бинарник, make по умолчанию делает elf.

zenon

Прикрепляю рабочий вариант софт i2c для libopencm3, основное тут Makefile, в нём указывается путь для библиотеки и необходимые файлы...
Выдергивал из официальных примеров. Документация тут и тут.
Всё в одном каталоге, включая ld.
По умолчанию хочет Black magic probe, надо бы его сделать и попробовать отладку.
Как прошить в комментариях.

Slabovik

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

zenon

Нет, не пробовал. st-link не поддерживается... Надо в j-link перешиться.
Скачал, не пойму пока как стартанут чего-нибудь.