LINUX.ORG.RU

STM32 output <> input

 


1

2

Добрый день, как красиво поменять режим с выхода OD на вход ? Ну чтобы одной строчкой в виде макроса.

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


#define TM1637_DIO_IN()     {GPIOC->CRL&=0XFFFF0FFF;GPIOC->CRL|=8<<12;}
#define TM1637_DIO_OUT()    {GPIOC->CRL&=0XFFFF0FFF;GPIOC->CRL|=3<<12;}

Ну с GPIOC всё понятно, CRL может быть и CRH в зависимости от номера порта, правильно? А дальше меняется режим? не могу сообразить :(

CRL&=0XFFFF0FFF

Это GPIOC Pin 3 верно?

Если нужен Pin 9 то :

CRH=0XFFFFFF0F

?

★★★

Следим за руками

#define TM1637_DIO_IN()     {GPIOC->CRL&=0XFFFF0FFF;GPIOC->CRL|=8<<12;}

#define TM1637_DIO_IN()     {GPIOC->CRL &= ~0xF000; GPIOC->CRL |= 8 << 12;}

#define TM1637_DIO_IN()     {GPIOC->CRL &= ~0xF000; GPIOC->CRL |= 1 << 15;}

#define _BV(xArg) (1 << (xArg))
#define TM1637_DIO_IN()     {GPIOC->CRL &= ~0xF000; GPIOC->CRL |= _BV(15);}

#define setBit(destArg, bitArg) (destArg) |= _BV(bitArg) 
#define clearBit(destArg, bitArg) (destArg) &= ~_BV(bitArg)
#define TM1637_DIO_IN()     {GPIOC->CRL &= ~0xF000; setBit(GPIOC->CRL, 15);}

#define TM1637_DIO_BIT 15
#define TM1637_DIO_IN()     {GPIOC->CRL &= ~0xF000; setBit(GPIOC->CRL, TM1637_DIO_BIT);}

 
bga_ ★★★★
()

GPIOC->CRL&=0XFFFF0FFF;GPIOC->CRL|=8<<12;

тут GPIOC->CRL&=0XFFFF0FFF; происходит сброс битов с 12 по 15 а тут GPIOC->CRL|=8<<12 установка этих битов в значение 1000 (10(Вход, подтяжка к земле) 00 (вход))

ukr_unix_user ★★★★
()
Ответ на: комментарий от AUX

По вопросу подсказываю: советую не дрочить биты, а использовать функцию gpio_set_mode/gpio_mode_setup. Если очень хочется всё самостоятельно и «с нуля», просто посмотри реализацию этих функций в libopencm3. А так ты даже не написал, какого семейства у тебя микроконтроллер, чтобы даташит смотреть.

CYB3R ★★★★★
()

В даташите на контроллер все описано:

CRL отвечает за выводы 0-7, CRH за выводы 8-15. Каждому выводу соответствует четыре подряд идущих бита, то есть PC0 это [0,1,2,3], PC1 это [4,5,6,7], а PC10 это [8,9,10,11], но уже CRH. Чтобы режим поменять надо сначала снять все 4 бита, а потом поставить уже нужную комбинацию:

GPIOC->CRL = (GPIOC->CRL &~ (0b1111 << (num*4))) | (mode << (num*4));

num - номер порта, в данном случае 3

mode - новый режим работы:

0b0100 - высокоомный вход
0b0011 - push-pull выход, 50 МГц
0b0111 - open-drain выход, 50 МГц 

Собственно, лучше именно моим способом пользуйтесь, чем как ваш китаец биты ручками считать. Для себя я уже оформил все это в макросы: https://github.com/COKPOWEHEU/RISCV-ili9341-3D/blob/master/src/pinmacro.h

COKPOWEHEU
()
Ответ на: комментарий от CYB3R

gpio_set_mode … просто посмотри реализацию этих функций в libopencm3

посмотрел. не проникся. после компиляции с -O2:

gpio_set_mode:
	push	{r4, r5, r6, r7, r8, r9, lr}
	mov	ip, #0
	mov	r7, #1
	mov	r6, #15
	ldr	r5, [r0]
	ldr	r8, [r0, #4]
.L6:
	ands	lr, r3, r7, lsl ip
	beq	.L2
	lsl	lr, ip, #2
	add	r9, lr, #2
	lsl	r4, r1, lr
	cmp	ip, #7
	bic	lr, r5, r6, lsl lr
	orr	r4, r4, r2, lsl r9
	orrls	r5, r4, lr
	addls	ip, ip, #1
	bls	.L6
	lsl	r4, ip, #2
	sub	lr, r4, #32
	lsl	r9, r1, lr
	sub	r4, r4, #30
	bic	lr, r8, r6, lsl lr
	orr	r4, r9, r2, lsl r4
	orr	r8, r4, lr
.L2:
	add	ip, ip, #1
	cmp	ip, #16
	bne	.L6
	str	r5, [r0]
	str	r8, [r0, #4]
	pop	{r4, r5, r6, r7, r8, r9, lr}
	bx	lr

иногда, возможно, и удобно несколько пинов сразу настроить, но вот эти Calculate bit offset и Use tmp32 to either modify crl or crh ещё и в цикле вообще не нужны. что, настолько сложно посчитать ниблы? ведь это же куда лучше: открыть даташит, с условным дефайном написать clear_and_set_bits(GPIOC_CRL, 0x0000f0f0, 0x00007040) и получить 4-8 максимально эффективных инструкций без циклов. ещё пойди попробуй запомнить все эти GPIO_MODE_OUTPUT_2_MHZ и GPIO_CNF_OUTPUT_PUSHPULL в случае с libopencm3.

anonymous
()
Ответ на: комментарий от anonymous

а для чего там port?

Не понял вопрос. Чтобы задавать порты как

#define RLED B,8,1,GPIO_PP50

то есть буква - номер - активный уровень - режим

COKPOWEHEU
()
Ответ на: комментарий от anonymous

Плюсую. Такая ерунда как установка битов в порте должна быть жестким инлайном в 1 инструкцию. А тут получается хуже ардуины.

bga_ ★★★★
()
Ответ на: комментарий от COKPOWEHEU

я про то, что в дефайне #define _GPIO_CONFIG(port, bit, ctl, mode), на 39 строке, переменная port не используется.

anonymous
()
Ответ на: комментарий от anonymous

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

COKPOWEHEU
()
Ответ на: комментарий от bga_

Плюсую. Такая ерунда как установка битов в порте должна быть жестким инлайном в 1 инструкцию. А тут получается хуже ардуины.

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

Но все равно лучше нескольких десятков инструкций на заполнение структуры, потом вызов для нее функции, потом внутри проверки. А потом те же самые 4-6 инструкций.

Да, это не AVR, где все просто…

COKPOWEHEU
()
Ответ на: комментарий от AUX

Привет. Что-то меня тут долго не было. Типа новая работа и все такое…

Я в своих проектах сделал макросы типа:


#define IO_CONCAT(a,b) a##b
#define IO_CONCAT2(a,b) IO_CONCAT(a,b)
#define IO_CONCAT3(a,b) IO_CONCAT2(a,b)

#define IO_GPIO(A)          IO_CONCAT2(GPIO,                IO_CONCAT(A, _PORT))
#define IO_PIN(A)           IO_CONCAT2(LL_GPIO_PIN_,        IO_CONCAT(A, _PIN ))


#define IO_GPIO_SET_MODE(A, m) 	   LL_GPIO_SetPinMode(IO_GPIO(A), IO_PIN(A), m)
#define IO_GPIO_SET_PULL(A, m) 	   LL_GPIO_SetPinPull(IO_GPIO(A), IO_PIN(A), m)
#define IO_GPIO_SET_OUT_TYPE(A, m) LL_GPIO_SetPinOutputType(IO_GPIO(A), IO_PIN(A), m)
#define IO_GPIO_SET_OUT_FREQ(A, m) LL_GPIO_SetPinSpeed(IO_GPIO(A), IO_PIN(A), m)

#define IO_GPIO_SET_OUT(A, type, speed)           \
do{                                               \
    IO_GPIO_SET_MODE    (A, LL_GPIO_MODE_OUTPUT); \
    IO_GPIO_SET_OUT_TYPE(A, type);                \
    IO_GPIO_SET_OUT_FREQ(A, speed);               \
}while (0)

#define IO_GPIO_SET_INPUT(A, pull)           \
do{                                          \
    IO_GPIO_SET_MODE(A, LL_GPIO_MODE_INPUT); \
    IO_GPIO_SET_PULL(A, pull);               \
}while (0)

А в файле конфигурации проекта пишу так:

#define LED_RED_PORT A
#define LED_RED_PIN  5

Все функции LL заинлайнятся, так что насчет эффективности можно не волноваться.

Ещё раз сорян за догий ответ…

shkolnick-kun ★★★★★
()

Натыкай галочки в кубе. Нынче уже не нужно кувыркаться с битиками. Тык-тык и в продакшн. Заодно можно хорошенько поджечь жопы всяким Эдикам.

ox55ff ★★★★★
()
Ответ на: комментарий от ox55ff

Заодно можно хорошенько поджечь жопы всяким Эдикам.

TLDR: Эдикам это будет строго до лампочки. А вот ТС, натыкает галочек и хорошенько так подожжет жопу себе при попытке сопровождать результаты натыкивания.

А теперь более развернуто:

  1. Куб ИДЕ писали криворукие придурки, ломающие обратную совместимость даже в багфикс-релизах. Т.е., при сопровождении проекта нельзя обновлять куб (sad but true).

  2. Куб опирается на HAL, писанный альтернативно одаренными программистами со всеми вытекающими. Никогда не используй HAL без веских причин (отсутствие драйверов в LL и сторонних драйверов с подходящей лицензией)

  3. LL лучше но опирается на вот такие хеддеры, которые какбе относятся к CMSIS, но их писали примерно те же альтернативщики, что и HAL.

  4. В этих хеддерах есть вот такие дефайны

#define TIM2                ((TIM_TypeDef *) TIM2_BASE)

В сочетании вот с такими:

#define RCC_APB1RSTR_TIM2RST_Pos           (0U)                                
#define RCC_APB1RSTR_TIM2RST_Msk           (0x1UL << RCC_APB1RSTR_TIM2RST_Pos)  /*!< 0x00000001 */
#define RCC_APB1RSTR_TIM2RST               RCC_APB1RSTR_TIM2RST_Msk          
  1. В результате над всем этим безобразием невозможно построить нормальные абстракции, не сделав
#undef TIM2
  1. Соответственно, горе программисты, писавшие Куб, не смогли нормально абстрагироваться от железа, и в кубе можно задавать человекочитаемые имена только для выводов микроконтроллера, а для периферии - нельзя!

  2. В итоге, проект, сделанный в Кубе, прибит гвоздями к конкретной версии конкретной платы. При коррекции платы обязательно будут пляски с бубном вокруг Куба.

Таким образом, Куб - ярчайший пример Defective by design.

shkolnick-kun ★★★★★
()
Последнее исправление: shkolnick-kun (всего исправлений: 5)
Ответ на: комментарий от shkolnick-kun

Спасибо, что ответил :)

AUX ★★★
() автор топика
Ответ на: комментарий от shkolnick-kun

HAL и Cube IDE делали криворукие, однако у меня сложилось впечатление, что криворукие создавали и сам контроллер (использую stm32f446ze). После 8051 от Silabs, у которого мильтиплексор АЦП аккуратно по порядку выходит в один (или два) порта с совпадением номера ножки мультиплексора с битом порта, сложно понять, зачем распихивать ноги мультиплексора АЦП по одной в разные порты. Более того, зачем-то сделано 3 АЦП и два мультиплексора. Почему нельзя было сделать для каждого АЦП по мультиплексору?

Так же и таймеры распиханы и UART. В отладочных платах тоже месиво, когда части одного порта распиханы в случайном порядке по разъёмам.

Источник тактовой частоты идёт на два делителя, а от них на разную периферию расходится. По умолчанию делители настроены каждый по своему. Из-за этого приходится гадать, почему одинаково настроенный ШИМ в двух таймерах работает по разному. Зачем эти делители вообще нужны? Почему нельзя было использовать напрямую тактовую частоту в таймере? Или уж один делитель на все таймеры.

Kogrom
()
Ответ на: комментарий от Kogrom

Новый Stm32CubeIDE сейчас хотя как-то юзабилен, до это вообще от него было больше проблем чем пользы. Кстати SPL похоронили? Просто у меня старые проекты остались на нем.

AUX ★★★
() автор топика
Ответ на: комментарий от shkolnick-kun

do{
IO_GPIO_SET_MODE (A, LL_GPIO_MODE_OUTPUT);
IO_GPIO_SET_OUT_TYPE(A, type);
IO_GPIO_SET_OUT_FREQ(A, speed);
}while (0)

скомпилированный вариант — в студию!

насчет эффективности можно не волноваться

да, будет, наверное, эффективнее, чем с libopencm3 и её gpio_set_mode(), но меня удивляет, что для каждого бита или режима используется свой вызов. разве это эффективно?

anonymous
()
Ответ на: комментарий от anonymous

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

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

COKPOWEHEU
()
Ответ на: комментарий от COKPOWEHEU

Программный i2c например для пары-тройки штук индикаторов и кучи кнопок на tm1637 например. Там вроде i2c но не совсем.

AUX ★★★
() автор топика
Последнее исправление: AUX (всего исправлений: 1)
Ответ на: комментарий от ukr_unix_user

Насколько я понимаю, remap может перекинуть периферию (например вывод мультиплексора АЦП, UART, SPI и т.д.) на другую ножку, но не на любую, а одну из двух или трёх выделенных. Собрать все выводы мультиплексора АЦП в один порт не получится. Что касается портов, то они не перекидываются на другие вывода микросхемы.

Возьмём для примера NUCLEO-F446ZE и посмотрим разъём CN9:

1 - PA3 (A0)
2 - PD7
3 - PC0 (A1)
4 - PD6
5 - PC3 (A2)
6 - PD5
7 - PF3 (A3)
8 - PD4
...

Почему нельзя было сделать так:

1 - PA0 (A0)
2 - PA1 (A1)
3 - PA2 (A2)
4 - PA3 (A3)
5 - PA4 (A4)
...

И для CN9 ещё можно увидеть какой-то порядок. В CN11 все ноги портов просто перемешаны в случайном порядке.

Ну хорошо, можно было бы предположить, что они платы разводить не умеют. Но ведь и на выводах самого контроллера примерно такое же месиво. Ну может чуть лучше. Я думаю, что это одна из причин, почему вообще возник Куб.

Kogrom
()
Ответ на: комментарий от COKPOWEHEU

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

anonymous
()
Ответ на: комментарий от AUX

Я SPL не использовал, не знаю. В сети говорят, что не похоронили.

HAL мне не очень нравится, но в нём хоть есть какая-то логика, так что жить можно, если к быстродействию особых требований нет. А вот сама Stm32CubeIDE мне сильно не нравится. Я её только из-за отладчика использую, который тоже работает как-то странно - часто пролетает мимо брейкпоинта. С другой стороны, пошаговая отладка становится бесполезной, когда в программе много прерываний от различных источников. Так что может быть со временем я переползу на более вменяемую среду разработки.

Kogrom
()
Ответ на: комментарий от Kogrom

К слову, неплохой вариант с удобным отладчиком - PlatformIO (на базе VS Code). Хорошая IDE, с удобным управлением проектом, библиотеками, система сборки.

Нюанс - раньше отладчик был платным после 30-дневного триала, с помесячной оплатой. Сейчас вроде все бесплатно.

James_Holden ★★★
()
Ответ на: комментарий от Kogrom

У тебя версия 1.5? Просто я поставил 1.5, там такого не наблюдал, а в 1.2.были проблемы.

AUX ★★★
() автор топика
Ответ на: комментарий от anonymous

Значение в порт кладется не для того чтобы положить значение (это не встроенная периферия и не память), а чтобы управлять внешней периферией. Причем даже там стараются использовать внутреннюю периферию.

Так что повторяю вопрос: часто ли нужно управлять группами портов одновременно?

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

COKPOWEHEU
()
Ответ на: комментарий от AUX

У меня версия 1.4. Завтра попробую обновиться до 1.5. Надеюсь поможет.

Kogrom
()
Ответ на: комментарий от ukr_unix_user

Если взять CN11, CN12, то там порты перемешаны ещё сильнее. Возможно, это действительно неудачная плата. Посмотрел STM32F4DISCOVERY. Там немного лучше, но всё равно мешанина портов.

Kogrom
()
Ответ на: комментарий от anonymous

Примерно так:

 8003f94:	b5f8      	push	{r3, r4, r5, r6, r7, lr}
	IO_GPIO_SET_OUT(CENSORED_KEY, LL_GPIO_OUTPUT_PUSHPULL, LL_GPIO_SPEED_FREQ_HIGH);
 8003f96:	4c27      	ldr	r4, [pc, #156]	; (8004034 <_some_pins_open+0xa0>)
 8003f98:	2201      	movs	r2, #1
 8003f9a:	4620      	mov	r0, r4
 8003f9c:	f44f 5180 	mov.w	r1, #4096	; 0x1000
 8003fa0:	f7ff ff92 	bl	8003ec8 <LL_GPIO_SetPinMode>
  MODIFY_REG(GPIOx->OTYPER, PinMask, (PinMask * OutputType));
 8003fa4:	f4236863 	vld2.16	{d6-d7}, [r3 :128], r3
 8003fa8:	5380      	strh	r0, [r0, r6]
 8003faa:	68a06063 	stmiavs	r0!, {r0, r1, r5, r6, sp, lr}
 8003fae:	f44f 5380 	mov.w	r3, #4096	; 0x1000
 8003fb2:	f1a3fa93 			; <UNDEFINED> instruction: 0xf1a3fa93
  MODIFY_REG(GPIOx->OSPEEDR, (GPIO_OSPEEDR_OSPEED0 << (POSITION_VAL(Pin) * 2U)),
 8003fb6:	fab1 f181 	clz	r1, r1
 8003fba:	f2a3fa93 			; <UNDEFINED> instruction: 0xf2a3fa93
 8003fbe:	2503      	movs	r5, #3
 8003fc0:	f282fab2 			; <UNDEFINED> instruction: 0xf282fab2
 8003fc4:	0049      	lsls	r1, r1, #1
 8003fc6:	f101fa05 			; <UNDEFINED> instruction: 0xf101fa05
 8003fca:	2602      	movs	r6, #2
 8003fcc:	ea200052 	b	880411c ;<CENSORED>
 8003fd0:	0101      	lsls	r1, r0, #4
 8003fd2:	f202fa06 	vpmax.s8	d15, d2, d6
 8003fd6:	430a      	orrs	r2, r1
 8003fd8:	211060a2 	tstcs	r0, r2, lsr #1
  WRITE_REG(GPIOx->BRR, PinMask);
 8003fdc:	62a3      	str	r3, [r4, #40]	; 0x28
	IO_OUT_CLR(CENSORED_KEY); /*Initiate with zeros*/

Правда не всё заинлайнилось… Хотя LL_GPIO_SetPinMode выглядит просто:

__STATIC_INLINE void LL_GPIO_SetPinMode(GPIO_TypeDef *GPIOx, uint32_t Pin, uint32_t Mode)
{
  MODIFY_REG(GPIOx->MODER, (GPIO_MODER_MODE0 << (POSITION_VAL(Pin) * 2U)), (Mode << (POSITION_VAL(Pin) * 2U)));
}

Почему его не заинлайнило - не понятно.

Компилировал с -Os

shkolnick-kun ★★★★★
()
Последнее исправление: shkolnick-kun (всего исправлений: 4)
Ответ на: комментарий от Kogrom

у меня сложилось впечатление, что криворукие создавали и сам контроллер (использую stm32f446ze).

Вот кусок кода для stm32l4xx для полноты картины:

/*STM32L4 errata par. 2.2.10*/
#define RET_IRQ_MSP 0xFFFFFFF9

extern void Reset_Handler(void);
extern uint32_t _sflash;
extern uint32_t _estack;
static uint32_t * const new_sp = &_estack - 9; /*Need at least 8 words*/
/*---------------------------------------------------------------------------*/
static inline void _setup_new_stack(void)
{
    new_sp[5] = RET_IRQ_MSP;             /*LR  (will use msp, LOL)*/
    new_sp[6] = (uint32_t)Reset_Handler; /*PC  (will return to reset)*/
    new_sp[7] = 0x01000000;              /*PSR (reset value)*/
}
/*---------------------------------------------------------------------------*/
void HardFault_Handler(void)
{
    if ((_sflash != (uint32_t)&_estack) || *(&_sflash + 1) != (uint32_t)Reset_Handler)
    {
        /*Setup new stack and return to Reset_Handler with MSP used!!!*/

        __set_MSP((uint32_t)new_sp);
        __asm__ __volatile__ (
                "isb        \n\t"
                "dsb        \n\t"
                "ldr sp, =%0\n\t"
                "isb        \n\t"
                "dsb        \n\t"
                "ldr lr, =%1\n\t"
                "isb        \n\t"
                "dsb        \n\t"
                ::"i"(new_sp), "i"(RET_IRQ_MSP):);

        _setup_new_stack();

        __asm__ __volatile__(
                "isb       \n\t"
                "dsb       \n\t"
                "bx lr     \n\t"
                :::);
    }

    NVIC_SystemReset();
}

Источник тактовой частоты идёт на два делителя, а от них на разную периферию расходится. По умолчанию делители настроены каждый по своему. Из-за этого приходится гадать, почему одинаково настроенный ШИМ в двух таймерах работает по разному. Зачем эти делители вообще нужны? Почему нельзя было использовать напрямую тактовую частоту в таймере? Или уж один делитель на все таймеры.

Всегда сам пишу инициализацию системы тактирования так, как мне надо, плюс использую clock security system, в SystemInit от ST этого нет.

shkolnick-kun ★★★★★
()
Последнее исправление: shkolnick-kun (всего исправлений: 1)
Ответ на: комментарий от shkolnick-kun

ну, вроде, норм. из-за оптимизации, правда, не всё до конца понятно, перемешано ещё с каким-то другим кодом, явно. а ты когда выводил асм правильную архитектуру выбрал? а то вот эти неоновские vld2.16 тут как-то вообще не смотрятся и <UNDEFINED> instruction промеж нормального тоже ни к селу ни к городу.

не всё заинлайнилось … Компилировал с -Os

скорее всего функция, которая не заинлайнилась, используется в нескольких местах, и в целях сокращения размера бинаря как раз целесообразно будет её не инлайнить.

anonymous
()
Ответ на: комментарий от AUX

Я не про это, а про постоянное передергивания режима с входа на выход.

Не понимаю. i2c ведь работает в режиме open-drain, зачем его переключать на вход или на выход? И какое преимущество здесь даст управление группами выводов?

COKPOWEHEU
()
Ответ на: комментарий от shkolnick-kun

Примерно так:

IO_GPIO_SET_OUT

MODIFY_REG

У меня покороче выглидит:

  GPIO_config(RLED);
 8000208:	4b0b      	ldr	r3, [pc, #44]	; (8000238 <main+0x44>)
 800020a:	681a      	ldr	r2, [r3, #0]
 800020c:	f422 3240 	bic.w	r2, r2, #196608	; 0x30000
 8000210:	f442 3280 	orr.w	r2, r2, #65536	; 0x10000
 8000214:	601a      	str	r2, [r3, #0]
 8000216:	689a      	ldr	r2, [r3, #8]
 8000218:	f442 3240 	orr.w	r2, r2, #196608	; 0x30000
 800021c:	609a      	str	r2, [r3, #8]

И не заинлайниться просто не имеет права, поскольку макросы.

COKPOWEHEU
()
Ответ на: комментарий от COKPOWEHEU

это не встроенная периферия и не память

так я-то как раз про встроенную периферию и память — про регистры и говорю.

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

HAL

при чём здесь вообще кал?

anonymous
()
Ответ на: комментарий от anonymous

vld2.16

Так это дисасм фигню вывел, скорее всего. Архитектура Cortex-M4F, но плавающую точку я там не использую.

shkolnick-kun ★★★★★
()
Последнее исправление: shkolnick-kun (всего исправлений: 1)
Ответ на: комментарий от anonymous

так я-то как раз про встроенную периферию и память — про регистры и говорю.

Для регистров периферии я этот макрос и не предлагаю использовать, там проще напрямую. Ну либо писать специфичные. Скажем, для АЦП логично объединить все ADCSQR в один макрос или биты для USB_EPnR

при чём здесь вообще кал?

Ну мы ведь обсуждаем сравнение работы с портами через заполнение структуры с макросами

COKPOWEHEU
()
Ответ на: комментарий от shkolnick-kun

GPIO_BOP

А определено это gd32vf103.h?

Тот вариант для stm32l151, но аналогичные писал и под f103 и под gd32vf103 (кстати, последний же risc-v а не arm, к чему он тут?)

COKPOWEHEU
()
Ответ на: комментарий от ox55ff

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

anonymous
()
Ответ на: комментарий от COKPOWEHEU

А как ты GD32 прошивал? Я как-то получил две липовых «синих таблетки» с али: на одной была маркировка STM32, но чип явно какой-то левый, его st-flash и stm32flash не определили вообще. На другой явно был указан GD32F103 (но получить деньги от продавца не вышло: этот говнюк мелким шрифтом в самом конце написал, что распаян не STM32, а GD32), но тоже ни через программатор, ни через бутлоадер камень никак не определился…

Вантузоиды пишут, что у них программатор нормально работает и с CS32, и с GD32. Но вантуз использовать для работы — это же вообще треш…

anonymous
()
Ответ на: комментарий от anonymous

Есть gd32F103, это клон stm32, на ядре ARM, с ними я не работал

А есть gd32VF103, на ядре RISCV, вот про них могу сказать. Не знаю что там с браком или подделками, но у меня успешно прошивалось и через stm32flash и через dfu-util. Только через openocd/JTAG не захотело. Говорят, надо патчить openocd, но мне лень.

COKPOWEHEU
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.