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

Кто любит RISC в жизни, заходим, не стесняемся.
Ответить
Мучитель микросхем
Сообщения: 446
Зарегистрирован: Вс ноя 01, 2015 09:15:16
Откуда: 69.Ржев

Сообщение a797945 »

есть такой вопросик. можно ли уговорить компилятор более активно использовать адресацию со смещением? (F103, Keil.v5, C (не плюсы), оптимизация -время) Конкретизирую:
в обработчике исп. 9 адресов (2 переменные, 3 рег. SPI, 4 рег. TIM1) компиль только для трех из них исп. обращение по смещению.
или альтернатива только вставка asm?
сейчас мне пока не критично, но на будущее заинтересовал этот вопрос.
(в рабочее время выхода в тырнет не имею, если что отвечу только вечером)
Спойлер

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

void SPI2_IRQHandler(void){
	uint16_t h;
	uint32_t w;
		h = SPI2->DR;	
	if(wi) {
		wi = wi|h;
			TIM1->CR1 = 0;		TIM1->SR = 0;		TIM1->DIER = 0;
			SPI2->CR1 |= SPI_CR1_SSI; SPI2->CR2 = 0;		
//		uint32_t z,s;
//		z=w; s=0;
//		while (z){if (z&1) {s++;}  z>>=1;}		
//		if (s&1) break;
//		wi=0;	
		status |= 1;		
	}else{		
		if (adri==(h>>8)) wi =(h<<16);	
		else {			// stop restart 
			TIM1->CR1 = 0;		TIM1->SR = 0;
			SPI2->CR1 |= SPI_CR1_SSI; SPI2->CR2 = 0;		
			TIM1->EGR = TIM_EGR_UG;
			TIM1->DIER = TIM_DIER_CC3IE;
			TIM1->CR1 |= TIM_CR1_CEN;
		}
	}
}
листинг начало:
0x08001D86 B4F0      PUSH     {r4-r7}
0x08001D88 4810      LDR      r0,[pc,#64]  ; @0x08001DCC
0x08001D8A F8B0C000  LDRH     r12,[r0,#0x00]
0x08001D8E 481B      LDR      r0,[pc,#108]  ; @0x08001DFC
0x08001D90 6887      LDR      r7,[r0,#0x08]
0x08001D92 4E1E      LDR      r6,[pc,#120]  ; @0x08001E0C
0x08001D94 4A0E      LDR      r2,[pc,#56]  ; @0x08001DD0
0x08001D96 2100      MOVS     r1,#0x00
0x08001D98 4B0A      LDR      r3,[pc,#40]  ; @0x08001DC4
0x08001D9A 1F35      SUBS     r5,r6,#4
0x08001D9C 1D14      ADDS     r4,r2,#4
0x08001D9E B3CF      CBZ      r7,0x08001E14
0x08001DA0 6887      LDR      r7,[r0,#0x08]
0x08001DA2 EA470C0C  ORR      r12,r7,r12
0x08001DA6 F8C0C008  STR      r12,[r0,#0x08]
0x08001DAA 8019      STRH     r1,[r3,#0x00]
0x08001DAC 8031      STRH     r1,[r6,#0x00]
0x08001DAE 8029      STRH     r1,[r5,#0x00]
0x08001DB0 8813      LDRH     r3,[r2,#0x00]
Реклама
Собутыльник Кота
Аватара пользователя
Сообщения: 2567
Зарегистрирован: Вт май 01, 2018 19:44:47

Сообщение VladislavS »

a797945, переходите на 6-й компилятор. Оптимизация -O3.
Спойлер

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

     7: extern "C" void SPI2_IRQHandler(){ 
     8:    uint16_t h; 
     9:    uint32_t w; 
    10:    h = SPI2->DR;    
0x080005E0 F6430000  MOVW     r0,#0x3800
    11:    if(wi) { 
0x080005E4 F6400190  MOVW     r1,#0x890
0x080005E8 F2C40000  MOVT     r0,#0x4000
0x080005EC F2C20100  MOVT     r1,#0x2000
    10:    h = SPI2->DR;    
    11:    if(wi) { 
0x080005F0 68C2      LDR      r2,[r0,#0x0C]
0x080005F2 880B      LDRH     r3,[r1,#0x00]
0x080005F4 B1C3      CBZ      r3,0x08000628
    12:       wi = wi|h; 
0x080005F6 880B      LDRH     r3,[r1,#0x00]
0x080005F8 431A      ORRS     r2,r2,r3
0x080005FA 800A      STRH     r2,[r1,#0x00]
0x080005FC F6424100  MOVW     r1,#0x2C00
0x08000600 F2C40101  MOVT     r1,#0x4001
0x08000604 2200      MOVS     r2,#0x00
    13:       TIM1->CR1 = 0;       
0x08000606 600A      STR      r2,[r1,#0x00]
    14:           TIM1->SR = 0;       
0x08000608 610A      STR      r2,[r1,#0x10]
    15:           TIM1->DIER = 0; 
0x0800060A 60CA      STR      r2,[r1,#0x0C]
    16:       SPI2->CR1 |= SPI_CR1_SSI; SPI2->CR2 = 0;         
0x0800060C 6801      LDR      r1,[r0,#0x00]
0x0800060E F4417180  ORR      r1,r1,#0x100
0x08000612 6001      STR      r1,[r0,#0x00]
0x08000614 6042      STR      r2,[r0,#0x04]
    17:       status |= 1;       
    18:    }else{       
    19:       if (adri==(h>>8)) wi =(h<<16);    
    20:       else {         // stop restart 
    21:          TIM1->CR1 = 0;      TIM1->SR = 0; 
    22:          SPI2->CR1 |= SPI_CR1_SSI; SPI2->CR2 = 0;       
    23:          TIM1->EGR = TIM_EGR_UG; 
    24:          TIM1->DIER = TIM_DIER_CC3IE; 
    25:          TIM1->CR1 |= TIM_CR1_CEN; 
    26:       } 
    27:    } 
0x08000616 F6400094  MOVW     r0,#0x894
0x0800061A F2C20000  MOVT     r0,#0x2000
0x0800061E 6801      LDR      r1,[r0,#0x00]
0x08000620 F0410101  ORR      r1,r1,#0x01
0x08000624 6001      STR      r1,[r0,#0x00]
    28: }
0x08000626 4770      BX       lr
    19:       if (adri==(h>>8)) wi =(h<<16);    
    20:       else {         // stop restart 
0x08000628 F6400398  MOVW     r3,#0x898
0x0800062C F2C20300  MOVT     r3,#0x2000
0x08000630 881B      LDRH     r3,[r3,#0x00]
0x08000632 F3C22207  UBFX     r2,r2,#8,#8
0x08000636 429A      CMP      r2,r3
0x08000638 BF02      ITTT     EQ
0x0800063A 2000      MOVEQ    r0,#0x00
0x0800063C 8008      STRHEQ   r0,[r1,#0x00]
0x0800063E 4770      BXEQ     lr
0x08000640 F6424100  MOVW     r1,#0x2C00
0x08000644 F2C40101  MOVT     r1,#0x4001
0x08000648 2200      MOVS     r2,#0x00
    21:          TIM1->CR1 = 0;      TIM1->SR = 0; 
0x0800064A 600A      STR      r2,[r1,#0x00]
0x0800064C 610A      STR      r2,[r1,#0x10]
    22:          SPI2->CR1 |= SPI_CR1_SSI; SPI2->CR2 = 0;       
0x0800064E 6803      LDR      r3,[r0,#0x00]
0x08000650 F4437380  ORR      r3,r3,#0x100
0x08000654 6003      STR      r3,[r0,#0x00]
0x08000656 6042      STR      r2,[r0,#0x04]
0x08000658 2001      MOVS     r0,#0x01
    23:          TIM1->EGR = TIM_EGR_UG; 
0x0800065A 6148      STR      r0,[r1,#0x14]
0x0800065C 2008      MOVS     r0,#0x08
    24:          TIM1->DIER = TIM_DIER_CC3IE; 
0x0800065E 60C8      STR      r0,[r1,#0x0C]
    25:          TIM1->CR1 |= TIM_CR1_CEN; 
    26:       } 
    27:    } 
0x08000660 6808      LDR      r0,[r1,#0x00]
0x08000662 F0400001  ORR      r0,r0,#0x01
0x08000666 6008      STR      r0,[r1,#0x00]
    28: }
0x08000668 4770      BX       lr
0x0800066A 0000      MOVS     r0,r0
Реклама
Мучитель микросхем
Сообщения: 446
Зарегистрирован: Вс ноя 01, 2015 09:15:16
Откуда: 69.Ржев

Сообщение a797945 »

понял. наглядно.
Спасибо
Потрогал лапой паяльник
Аватара пользователя
Сообщения: 373
Зарегистрирован: Ср мар 09, 2016 08:07:41

Сообщение JackSmith »

ковыряю один из клонов stm32 на m4f.
обработчик прерывания таймера завершается кодом:

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

TIM4->SR &= ~(0x01);
проблема в том, что флаг прерывания не снимается с первого раза. прерывание отрабатывает по два раза. поставил барьерную инструкцию DSB после упомянутого кода, заработало как надо.
это нормальное поведение для STM32? кто-нибудь сталкивался?
Реклама
Эиком - электронные компоненты и радиодетали
Собутыльник Кота
Аватара пользователя
Сообщения: 2567
Зарегистрирован: Вт май 01, 2018 19:44:47

Сообщение VladislavS »

Нормально. Барьер не нужен, нужна задержка. Просто переместите команду очистки флага ближе к началу обработчика прерывания. А саму команду я бы упростил до записи нуля.
Реклама
Потрогал лапой паяльник
Аватара пользователя
Сообщения: 373
Зарегистрирован: Ср мар 09, 2016 08:07:41

Сообщение JackSmith »

[uquote="VladislavS",url="/forum/viewtopic.php?p=4295410#p4295410"]Нормально. Барьер не нужен, нужна задержка. Просто переместите команду очистки флага ближе к началу обработчика прерывания. А саму команду я бы упростил до записи нуля.[/uquote]
угу. проверил на F103. та же самая фигня.
Реклама
Мудрый кот
Сообщения: 1849
Зарегистрирован: Вс дек 25, 2016 08:34:54

Сообщение Dimon456 »

Чип F030, функция
Спойлер

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

uint16_t rnd(uint16_t limit){

	uint32_t result = rand();

	return (uint16_t)(((uint64_t)(result) * limit) / (RAND_MAX));	// где RAND_MAX = 0x7fffffff 
}
Вопрос, как эффективнее выполнить 64-битные вычисления?, не устраивает 2кило лишнего кода.
Собутыльник Кота
Аватара пользователя
Сообщения: 2516
Зарегистрирован: Пт июл 12, 2019 22:52:01

Сообщение Eddy_Em »

Dimon456, rand() - твой? Тогда почему бы сразу его не сделать uint16_t и по модулю брать остаток?
Linux rules! Windows must die. Здравомыслящий человек добровольно будет пользоваться мастдаем лишь в двух случаях: под дулом автомата или под влиянием анального зонда.
Я на гитхабе, в ЖЖ
Контактная информация:
Мудрый кот
Сообщения: 1849
Зарегистрирован: Вс дек 25, 2016 08:34:54

Сообщение Dimon456 »

Eddy_Em писал(а):rand() - твой?
Нет, это библиотечная функция stdlib.h
В arm-gcc используется 32-битный rand(), а в avr-gcc 16-битный.

При включении чипа, я сканирую содержимое оперативной памяти с просчетом CRC, где-то так
Спойлер

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

 	char *ptr = (void*)RAMSTART;
 	uint32_t seed=0;
 	
	for(uint16_t i=0; i < (RAMEND-RAMSTART-1); i++){
		seed += CRC_32BitsCompute(ptr++);
	}
	srand(seed);
Последний раз редактировалось Dimon456 Пн ноя 14, 2022 22:25:13, всего редактировалось 1 раз.
Опытный кот
Аватара пользователя
Сообщения: 848
Зарегистрирован: Ср авг 03, 2022 05:22:56

Сообщение MLX90640 »

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

Сообщение Dimon456 »

MLX90640, если взять uint64_t и заменить на uint32_t то получается размер 5157 байт (здесь еще вывод на индикатор LCD и прочие), а при uint64_t - 7265 байт. В чем может быть проблема?
Собутыльник Кота
Аватара пользователя
Сообщения: 2567
Зарегистрирован: Вт май 01, 2018 19:44:47

Сообщение VladislavS »

Компилятор? Формула не должна столько брать.

PS: На IAR разница между 32 и 64 всего 180 байт.
PPS: На GCC 572
Мучитель микросхем
Сообщения: 446
Зарегистрирован: Вс ноя 01, 2015 09:15:16
Откуда: 69.Ржев

Сообщение a797945 »

Dimon456, какая задача у функции rnd(limit)?
я разглядел только прорежевание результатов генератора (обнуление), а для этого может достаточно делить на 80000000h ? чего я не догоняю?
Мудрый кот
Сообщения: 1849
Зарегистрирован: Вс дек 25, 2016 08:34:54

Сообщение Dimon456 »

Задача у функции rnd(limit) в пределах какого диапазона считать случайное число.
К примеру
x = rnd(255); и
y = rnd(10);
В основной программе используется и то и другое.
a797945 писал(а):а для этого может достаточно делить на 80000000h
Было бы хорошо, но "бы" мешает.
RAND_MAX = 0x7fffffff задано жестко в библиотеке stdlib.h и видимо связано как-то с самой функцией rand().
Я пробовал так делать
Спойлер

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

return (uint16_t)((uint32_t)((uint32_t)(result>>16) * limit) / (RAND_MAX>>16));
x = rnd(255); но иногда результат выходит за диапазон 0---255.
Собутыльник Кота
Аватара пользователя
Сообщения: 2567
Зарегистрирован: Вт май 01, 2018 19:44:47

Сообщение VladislavS »

[uquote="Dimon456",url="/forum/viewtopic.php?p=4320576#p4320576"]Задача у функции rnd(limit) в пределах какого диапазона считать случайное число.[/uquote] :facepalm: Тык! И еще тык!
Собутыльник Кота
Аватара пользователя
Сообщения: 2516
Зарегистрирован: Пт июл 12, 2019 22:52:01

Сообщение Eddy_Em »

Dimon456, вот тебе рандом:

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

uint32_t getRand(){
    uint32_t r = 0;
    for(int i = 0; i < 16; ++i){
        r <<= 1;
        r |= (getADCval(0) & 1);
        r <<= 1;
        r |= (getADCval(1) & 1);
    }
    r ^= r << 13;
    r ^= r >> 17;
    r ^= r << 5;
    return r;
}
(каналы - внутренний термометр и напруга). Нормальный псевдорандом получается. Всяко лучше "фирменного". Если требуется задать границы, просто берешь остаток от деления на нужное число (жаль, что в STM32F0 деление софтовое).
Вот, например, здесь я вычисляю случайную начальную скорость мячика:

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

    xspeed[Nballs] = ((int)getRand()) % SPEEDMAX;
    yspeed[Nballs] = ((int)getRand()) % SPEEDMAX;
Linux rules! Windows must die. Здравомыслящий человек добровольно будет пользоваться мастдаем лишь в двух случаях: под дулом автомата или под влиянием анального зонда.
Я на гитхабе, в ЖЖ
Контактная информация:
Мудрый кот
Сообщения: 1849
Зарегистрирован: Вс дек 25, 2016 08:34:54

Сообщение Dimon456 »

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

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

  .section .text.Reset_Handler
  .weak Reset_Handler
  .type Reset_Handler, %function
Reset_Handler:
  ldr   r0, =_eram
  mov   sp, r0          /* set stack pointer */

/* Copy the data segment initializers from flash to SRAM */
  movs r1, #0
  b LoopCopyDataInit

CopyDataInit:
  ldr r3, =_sidata
  ldr r3, [r3, r1]
  str r3, [r0, r1]
  adds r1, r1, #4

LoopCopyDataInit:
  ldr r0, =_sdata
  ldr r3, =_edata
  adds r2, r0, r1
  cmp r2, r3
  bcc CopyDataInit
  ldr r2, =_sbss
  b LoopFillZerobss
/* Zero fill the bss segment. */
FillZerobss:
  movs r3, #0
  str  r3, [r2]
  adds r2, r2, #4


LoopFillZerobss:
  ldr r3, = _ebss
  cmp r2, r3
  bcc FillZerobss

/* Call the clock system intitialization function.*/
    bl  SystemInit
    
/* Call the application's entry point.*/
  bl main
Нужно и CRC сконфигурировать, и до момента пока он ее (память) не обнулил.
Eddy_Em, getADCval, это уж когда совсем делать не чего будет.
Опытный кот
Аватара пользователя
Сообщения: 848
Зарегистрирован: Ср авг 03, 2022 05:22:56

Сообщение MLX90640 »

Сканировать SRAM? А что там предполагаете увидеть?
Тот участок асма это не сканирование, а копирование из флеша константных значений и обнуление неинициализованных глобальных и статич переменных.

Если хотите проверить целостность ячеек ОЗУ, то записывайте один из шаблонов и считывайте его. Однако, при запуске на дефолтной частоте это будет небыстро
Мудрый кот
Сообщения: 1849
Зарегистрирован: Вс дек 25, 2016 08:34:54

Сообщение Dimon456 »

MLX90640 писал(а):Сканировать SRAM? А что там предполагаете увидеть?
А вы, что, не поняли что я пытаюсь сделать?

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

srand(seed);
MLX90640 писал(а):Тот участок асма это не сканирование, а копирование из флеша константных значений и обнуление неинициализованных глобальных и статич переменных.
Вот именно, пока не произошло копирование из флеша .... эти ячейки имеют рандомное значение и оно всегда разное. Можете сами убедиться.
Другой вопрос, где srand() хранит свое значение и в какой момент нужно произвести это сканирование и запись в srand() нового значения что бы дальнейшая инициализация глобальных и статич переменных не повлияла на новую запись в srand()?
Собутыльник Кота
Аватара пользователя
Сообщения: 2516
Зарегистрирован: Пт июл 12, 2019 22:52:01

Сообщение Eddy_Em »

Dimon456, единственный надежный способ получить более-менее похожие на правду псевдослучайные числа, если нет аппаратного блока, - это использовать АЦП. А дурной библиотечный rand даст всегда абсолютно одну и ту же последовательность. Советую проверить.
И да, инициализировать его условной CRC оперативки смысла особого нет, т.к. всегда есть шанс, что два и более включения дадут полностью одинаковое содержимое оной! Вот после софт-резета вполне возможно, что там какие-нибудь хвосты стека останутся. Но и смысл тогда всю оперативку проверять - проверяй только стек.
Linux rules! Windows must die. Здравомыслящий человек добровольно будет пользоваться мастдаем лишь в двух случаях: под дулом автомата или под влиянием анального зонда.
Я на гитхабе, в ЖЖ
Контактная информация:
Ответить

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