STM32 новичку в ARM что к чему

Кто любит RISC в жизни, заходим, не стесняемся.
Аватара пользователя
КРАМ
Друг Кота
Сообщения: 25121
Зарегистрирован: Чт янв 10, 2008 22:01:02
Откуда: Московская область, Фрязино

Re: STM32 новичку в ARM что к чему

Сообщение КРАМ »

[uquote="Eddy_Em",url="/forum/viewtopic.php?p=4353270#p4353270"]деление на 10 через сдвиги[/uquote]
Деление на константу легко преобразуется в умножение. Сдвиг там используется однократно или вообще не используется, если речь идет о степени двойки 8, 16 или 32.
Например:
Y=X/10=X*6554/65536=X/9.99939
или
Y=X/10=X*429496730/4294967296=X/9.99999999
Аватара пользователя
Eddy_Em
Собутыльник Кота
Сообщения: 2516
Зарегистрирован: Пт июл 12, 2019 22:52:01
Контактная информация:

Re: STM32 новичку в ARM что к чему

Сообщение Eddy_Em »

Да, почти первый вариант: для uint8 или uint16, чтобы не выходить за пределы uint32, т.к. арифметика uint64 тоже связана с накладными расходами (хотя, все равно быстрей, чем совтовое деление).
Linux rules! Windows must die. Здравомыслящий человек добровольно будет пользоваться мастдаем лишь в двух случаях: под дулом автомата или под влиянием анального зонда.
Я на гитхабе, в ЖЖ
Аватара пользователя
Eddy_Em
Собутыльник Кота
Сообщения: 2516
Зарегистрирован: Пт июл 12, 2019 22:52:01
Контактная информация:

Re: STM32 новичку в ARM что к чему

Сообщение Eddy_Em »

В общем, с RTC завел вот такую структуру:

Код: Выделить всё

typedef struct{
    uint8_t second;
    uint8_t minute;
    uint8_t hour;
    uint8_t weekday;
    uint8_t day;
    uint8_t month;
    uint8_t year;
} rtc_t;
Дальше - под спойлером, чтобы не загромождать.
СпойлерДля сеттеров вот так:

Код: Выделить всё

static uint8_t div10b(uint8_t i, uint8_t *r){ // divide by 10
    uint32_t u = i;
    u *= 52429;
    u >>= 19;
    if(r) *r = i - 10*u;
    return (uint8_t)u;
}

static uint8_t DEC2BCD(uint8_t x){
    uint8_t d, r;
    d = div10b(x, &r);
    return (d << 4 | r);
}

int rtc_setdate(rtc_t *d){
    if(d->year > 99) return FALSE;
    if(d->month > 12 || d->month == 0) return FALSE;
    if(d->day > maxdays[d->month - 1] || d->day == 0) return FALSE;
    if(d->month == 2 && d->day == 29){
        uint8_t test = (d->year >> 2) << 2;
        if(d->year != test) return FALSE; // not leap year
    }
    if(d->weekday > 7 || d->weekday == 0) return FALSE;
    RTC->ICSR |= RTC_ICSR_INIT;
    WAITWHILE(!(RTC->ICSR & RTC_ICSR_INITF));
    RTC->DR = DEC2BCD(d->year) << RTC_DR_YU_Pos | d->weekday << RTC_DR_WDU_Pos | DEC2BCD(d->month) << RTC_DR_MU_Pos | DEC2BCD(d->day) << RTC_DR_DU_Pos;
    RTC->ICSR &= ~RTC_ICSR_INIT;
    return TRUE;
}

int rtc_settime(rtc_t *t){
    if(t->hour > 23) return FALSE;
    if(t->minute > 59) return FALSE;
    if(t->second > 59) return FALSE;
    RTC->ICSR |= RTC_ICSR_INIT;
    WAITWHILE(!(RTC->ICSR & RTC_ICSR_INITF));
    RTC->TR = DEC2BCD(t->hour) << RTC_TR_HU_Pos | DEC2BCD(t->minute) << RTC_TR_MNU_Pos | DEC2BCD(t->second) << RTC_TR_SU_Pos;
    RTC->ICSR &= ~RTC_ICSR_INIT;
    return TRUE;
}
Геттер на все:

Код: Выделить всё

void get_curtime(rtc_t *t){
    WAITWHILE(!(RTC->ICSR & RTC_ICSR_RSF));
    register uint32_t r = RTC->TR;
    #define BCDu(shift)     ((r >> shift) & 0xf)
    t->second = BCDu(RTC_TR_SU_Pos) + 10 * BCDu(RTC_TR_ST_Pos);
    t->minute = BCDu(RTC_TR_MNU_Pos) + 10 * BCDu(RTC_TR_MNT_Pos);
    t->hour = BCDu(RTC_TR_HU_Pos) + 10 * BCDu(RTC_TR_HT_Pos);
    r = RTC->DR;
    t->day = BCDu(RTC_DR_DU_Pos) + 10 * BCDu(RTC_DR_DT_Pos);
    t->month = BCDu(RTC_DR_MU_Pos);
    if(r & RTC_DR_MT) t->month += 10;
    t->weekday = (r >> RTC_DR_WDU_Pos) & 0x7;
    t->year = BCDu(RTC_DR_YU_Pos) + 10 * BCDu(RTC_DR_YT_Pos);
}
И сеттер/геттер калибровки:

Код: Выделить всё

int rtc_setcalib(int calval){
    if(calval < -511 || calval > 512) return FALSE;
    uint32_t calp = 0, calm = 0;
    if(calval < 0)  calm = -calval;
    else if(calval > 0){
        calp = RTC_CALR_CALP;
        calm = 512 - calval;
    }
    // unlock RCC
    RTC->WPR = 0xCA;
    RTC->WPR = 0x53;
    RTC->CALR = calp | calm;
    return 1;
}

int rtc_getcalib(){
    int calval = (RTC->CALR & RTC_CALR_CALP) ? 512 : 0;
    calval -= RTC->CALR & 0x1ff;
    return calval;
}
А уж из полученного времени легко построить в формате утилиты date:

Код: Выделить всё

static const char *weekdays[] = {"Mon", "Tue", "Wed", "Thur", "Fri", "Sat", "Sun"};
static const char *months[] = {"Jan", "Feb", "Mar", "Apr", "May", "June", "July", "Aug", "Sept", "Oct", "Nov", "Dec"};

static void prezero(uint8_t x){
    if(x < 10){ putch('0'); putch('0' + x);}
    else USND(u2str(x));
}

void print_curtime(){
    rtc_t t;
    get_curtime(&t);
    USND(weekdays[t.weekday - 1]);
    putch(' ');
    USND(months[t.month - 1]);
    putch(' ');
    USND(u2str(t.day));
    putch(' ');
    prezero(t.hour);
    putch(':');
    prezero(t.minute);
    putch(':');
    prezero(t.second);
    USND(" 20"); prezero(t.year);
    putch('\n');
}
Еще у меня там есть сеттеры даты/времени из введенного пользователем, но это уж на гитхабе у меня смотрите.
Добавлено after 4 minutes 9 seconds:
А, блин, проверку деления на 4 неправильно сделал. Только сейчас заметил!
исправил
Последний раз редактировалось Eddy_Em Сб янв 14, 2023 16:58:34, всего редактировалось 1 раз.
Linux rules! Windows must die. Здравомыслящий человек добровольно будет пользоваться мастдаем лишь в двух случаях: под дулом автомата или под влиянием анального зонда.
Я на гитхабе, в ЖЖ
Martian
Друг Кота
Сообщения: 12867
Зарегистрирован: Сб дек 18, 2021 19:25:32
Контактная информация:

Re: STM32 новичку в ARM что к чему

Сообщение Martian »

какая неэкономичная структура
Аватара пользователя
Eddy_Em
Собутыльник Кота
Сообщения: 2516
Зарегистрирован: Пт июл 12, 2019 22:52:01
Контактная информация:

Re: STM32 новичку в ARM что к чему

Сообщение Eddy_Em »

Martian, с чего бы неэкономичная? Все, что нужно. При желании можно даже упаковать (но мне это не нужно: памяти в G0, как грязи).
Linux rules! Windows must die. Здравомыслящий человек добровольно будет пользоваться мастдаем лишь в двух случаях: под дулом автомата или под влиянием анального зонда.
Я на гитхабе, в ЖЖ
Аватара пользователя
VladislavS
Собутыльник Кота
Сообщения: 2562
Зарегистрирован: Вт май 01, 2018 19:44:47

Re: STM32 новичку в ARM что к чему

Сообщение VladislavS »

Eddy_Em, на Cortex-M0 можно через div, на Cortex-M4 компилятор сам умеет.
Изображение
изображение_2023-01-14_174541286.png
(63.37 КБ) 358 скачиваний
Аватара пользователя
Eddy_Em
Собутыльник Кота
Сообщения: 2516
Зарегистрирован: Пт июл 12, 2019 22:52:01
Контактная информация:

Re: STM32 новичку в ARM что к чему

Сообщение Eddy_Em »

VladislavS, библиотечная div через умножение и сдвиги что ли работает? В любом случае, чаще всего нужно лишь деление на 10, а оно легко реализуется.
Linux rules! Windows must die. Здравомыслящий человек добровольно будет пользоваться мастдаем лишь в двух случаях: под дулом автомата или под влиянием анального зонда.
Я на гитхабе, в ЖЖ
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18544
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

Re: STM32 новичку в ARM что к чему

Сообщение ARV »

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

Мой уютный бложик... заходите!
Аватара пользователя
Eddy_Em
Собутыльник Кота
Сообщения: 2516
Зарегистрирован: Пт июл 12, 2019 22:52:01
Контактная информация:

Re: STM32 новичку в ARM что к чему

Сообщение Eddy_Em »

Бред - флоаты пихать в 8-битную аврку. А деление оптимизировать — вполне нормально, даже если эта функция и вызывается нечасто. Ведь Cortex-M0 не умеет деление. А уж если нужно часто что-то делить на константу, так тем паче оптимизация хорошо сэкономит такты.
Это ардуинщикам наплевать, что там "под капотом" происходит. Они спокойно могут аж на пару миллисекунд вызвать какую-нибудь блокирующую операцию и не париться… А то и вообще блокирующими вызовами в течение аж сотни миллисекунд ногодрыгом перегонять изображение из буфера памяти на экранчик (хотя даже если нет DMA, это на прерываниях таймера можно сделать — будет между посылками хоть время на что-нибудь полезное).
Linux rules! Windows must die. Здравомыслящий человек добровольно будет пользоваться мастдаем лишь в двух случаях: под дулом автомата или под влиянием анального зонда.
Я на гитхабе, в ЖЖ
Аватара пользователя
КРАМ
Друг Кота
Сообщения: 25121
Зарегистрирован: Чт янв 10, 2008 22:01:02
Откуда: Московская область, Фрязино

Re: STM32 новичку в ARM что к чему

Сообщение КРАМ »

[uquote="Eddy_Em",url="/forum/viewtopic.php?p=4354166#p4354166"]чаще всего нужно лишь деление на 10[/uquote]
КОМУ нужно чаще всего? Я вот прикинул для своих проектов и не нашел деления на 10 вообще. Правда нашел множество делений на переменную, но посчитать сколько там делений на 10, а сколько на другую величину не представляется возможным...
Аватара пользователя
VladislavS
Собутыльник Кота
Сообщения: 2562
Зарегистрирован: Вт май 01, 2018 19:44:47

Re: STM32 новичку в ARM что к чему

Сообщение VladislavS »

[uquote="ARV",url="/forum/viewtopic.php?p=4354168#p4354168"]да не бред ли это?![/uquote]Бред это блинк на 5 кБ. А когда пишешь библиотечный код, чем Eddy_Em и занимается, надо писать оптимально даже ценой усложнения.
Dimon456
Мудрый кот
Сообщения: 1849
Зарегистрирован: Вс дек 25, 2016 08:34:54

Re: STM32 новичку в ARM что к чему

Сообщение Dimon456 »

VladislavS, имеет ли право на жизнь такой вариант, поморгать светодиодом?
СпойлерЧип f100

Код: Выделить всё

  RCC->APB2ENR |= RCC_APB2ENR_IOPCEN;
  
  GPIOC->CRH |= GPIO_CRH_CNF8_1 | GPIO_CRH_CNF9_1;
  GPIOC->CRH &= ~(GPIO_CRH_CNF8_0 | GPIO_CRH_CNF9_0);
  GPIOC->CRH &= ~(GPIO_CRH_MODE8_1 | GPIO_CRH_MODE9_1);
  GPIOC->CRH |= GPIO_CRH_MODE8_0 | GPIO_CRH_MODE9_0;
  
  RCC->APB2ENR |= RCC_APB2ENR_AFIOEN;
  AFIO->MAPR |= AFIO_MAPR_TIM3_REMAP;
  
  RCC->APB1ENR |= RCC_APB1ENR_TIM3EN;
  
  TIM3->CR1 = 0;
  TIM3->PSC = 0;
  TIM3->ARR = 0;
  TIM3->CCR3 = 0;
  TIM3->CCR4 = 0;
  TIM3->CCMR2 = TIM_CCMR2_OC3M_2 | TIM_CCMR2_OC3M_1;  
  TIM3->CCMR2 |= TIM_CCMR2_OC4M_2 | TIM_CCMR2_OC4M_1; 
  TIM3->CCER = TIM_CCER_CC3E | TIM_CCER_CC4E; 
  TIM3->CR1 |= TIM_CR1_CEN;

Код: Выделить всё

	TIM3->CCR3 ^= 1;	// 7 тактов    
	TIM3->CCR3 = 1;		// 2 такта   
	TIM3->CCR3 = 0;		// 2 такта
и соответственно TIM3->CCR4
У кого хороший осциллограф, проверьте будет ли там что либо, типа иголок или еще что?
Аватара пользователя
MLX90640
Опытный кот
Сообщения: 848
Зарегистрирован: Ср авг 03, 2022 05:22:56

Re: STM32 новичку в ARM что к чему

Сообщение MLX90640 »

Нормальная практика - генерация импульсов при помощи таймера и ШИМ-выхода. При 0 в регистре сравнения иголок на выходе не возникает, потому что переключение сигналов происходит в момент смены счетчика, синхронно по тактовому сигналу.
Чаще всего конечно этот вариант используется не для мигания отдельного светика, а для ШИМ-генерации или генерации меандра для "пищалки". Но можно организовать и ШИМ-мигание светика, подобное лампе накаливания, то есть с плавным зажиганием/выключением.
Последний раз редактировалось MLX90640 Сб янв 14, 2023 19:07:04, всего редактировалось 1 раз.
Аватара пользователя
VladislavS
Собутыльник Кота
Сообщения: 2562
Зарегистрирован: Вт май 01, 2018 19:44:47

Re: STM32 новичку в ARM что к чему

Сообщение VladislavS »

Мигает? Значит имеет. Хоть и отвратительно написано.
Dimon456
Мудрый кот
Сообщения: 1849
Зарегистрирован: Вс дек 25, 2016 08:34:54

Re: STM32 новичку в ARM что к чему

Сообщение Dimon456 »

MLX90640 писал(а):При 0 в регистре сравнения иголок на выходе не возникает
Меня интересует что будет при единице?
К сожалению у меня нету хорошего осциллографа, только аналоговый С1-72.
Только разве что ножку завести на внешнее прерывание, и в отладчике глянуть, если прерывание сработает - значит иголки присутствуют.
VladislavS писал(а):Хоть и отвратительно написано.
А как надо?
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18544
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

Re: STM32 новичку в ARM что к чему

Сообщение ARV »

[uquote="VladislavS",url="/forum/viewtopic.php?p=4354178#p4354178"][uquote="ARV",url="/forum/viewtopic.php?p=4354168#p4354168"]да не бред ли это?![/uquote]Бред это блинк на 5 кБ. А когда пишешь библиотечный код, чем Eddy_Em и занимается, надо писать оптимально даже ценой усложнения.[/uquote]
имхо, нормальная библиотека должна быть, во-первых, читаемой (без битовой магии и т.п. замен деления умножением), а во-вторых, не должна превращаться в тыкву при переходе на другой МК, иначе это не библиотека, а костыль индивидуального изготовления - уникальный, но никому, кроме одного инвалида, не подходящий.

а блинк на 5к за 5 минут, имхо, лучше, чем блинк в 0.5к за 20 лет...
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Dimon456
Мудрый кот
Сообщения: 1849
Зарегистрирован: Вс дек 25, 2016 08:34:54

Re: STM32 новичку в ARM что к чему

Сообщение Dimon456 »

ARV писал(а):а блинк на 5к за 5 минут, имхо, лучше, чем блинк в 0.5к за 20 лет...
Это хорошо когда флеша 128 К, а вот когда всего 16 К, стоит задуматься.
Аватара пользователя
КРАМ
Друг Кота
Сообщения: 25121
Зарегистрирован: Чт янв 10, 2008 22:01:02
Откуда: Московская область, Фрязино

Re: STM32 новичку в ARM что к чему

Сообщение КРАМ »

[uquote="ARV",url="/forum/viewtopic.php?p=4354231#p4354231"]читаемой (без битовой магии и т.п. замен деления умножением)...[/uquote]
Библиотека может содержать все что угодно. Ее задача скрыть некие относительно часто используемые сущности в функции. И все.
Переносимость библиотеки - это какое то недоразумение. Невозможно перенести библиотеку на совершенно другую вычислительную архитектуру без каких либо правок. Либо эта библиотека будет иметь безобразную реализацию для примитивных и не требовательных к ресурсам задач.
Не для того пользователь какого нибудь Blackfin платит 25 долларов за чип, чтобы не использовать особенности архитектуры, которые позволяют решить поставленную задачу именно на этом чипе, а не требуют другой - за 200 баксов.
Аватара пользователя
VladislavS
Собутыльник Кота
Сообщения: 2562
Зарегистрирован: Вт май 01, 2018 19:44:47

Re: STM32 новичку в ARM что к чему

Сообщение VladislavS »

[uquote="ARV",url="/forum/viewtopic.php?p=4354231#p4354231"]имхо, нормальная библиотека должна быть, во-первых, читаемой[/uquote]Читаемым и документированным должен быть интерфейс библиотеки. Что у неё внутри исключительно головняк автора.

[uquote="ARV",url="/forum/viewtopic.php?p=4354231#p4354231"](без битовой магии и т.п. замен деления умножением),[/uquote]Ну и где же нам деление на Cortex-M0 взять?

[uquote="ARV",url="/forum/viewtopic.php?p=4354231#p4354231"]а во-вторых, не должна превращаться в тыкву при переходе на другой МК,[/uquote]Согласен, если модуль есть на разных МК, то в идеале должен на них одинаково хорошо работать.

[uquote="ARV",url="/forum/viewtopic.php?p=4354231#p4354231"]иначе это не библиотека, а костыль индивидуального изготовления - уникальный, но никому, кроме одного инвалида, не подходящий.[/uquote]Библиотека под конкретный микроконтроллер тоже имеет право на существование. Лучше, конечно, писать универсально, но это и не всегда возможно, и зачастую тяжёлую артиллерию требует.

[uquote="ARV",url="/forum/viewtopic.php?p=4354231#p4354231"]а блинк на 5к за 5 минут, имхо, лучше, чем блинк в 0.5к за 20 лет...[/uquote]А ещё лучше блинк 0.4к за 4 минуты.
Аватара пользователя
MLX90640
Опытный кот
Сообщения: 848
Зарегистрирован: Ср авг 03, 2022 05:22:56

Re: STM32 новичку в ARM что к чему

Сообщение MLX90640 »

[uquote="Dimon456",url="/forum/viewtopic.php?p=4354205#p4354205"]Меня интересует что будет при единице?[/uquote]
Поправочка. Вы имеете ввиду при ARR = 1 и при CRRx = 1? Меандр получится, 50% ШИМ
Последний раз редактировалось MLX90640 Сб янв 14, 2023 20:24:30, всего редактировалось 1 раз.
Ответить

Вернуться в «ARM»