Как скомпилить асм для stm32 в keil.

Берём начало у маньяка.
Создаём прокет keil, на предложения добавить startup соглашаемся.
Создаём main.s, вставляем туда вот этот код. Табуляция имеет значения.

                 AREA |header code|,CODE,READONLY
                ENTRY
                EXPORT __main
__main
                nop
                nop
                nop

                END

Нажимаем F7 и получаем вот такую хрень.
2.axf: Error: L6218E: Undefined symbol SystemInit (referred from startup_stm32f10x_md_vl.o)
Идём СЮДА и узнаём что надо скопировать system_stm32f10x.c из каталога .\Keil\ARM\Startup\ST\STM32F10x в каталог с проектом.
Снова нажимаем F7 и ура, всё скомпилилось.
Да, забыл сказать.
Надо будет выбрать тип М.К. на ругательства вида.
«Please select first the target STM32F10x device used in your application (in stm32f10x.h file)»

Да… HEX на 2,2 килобайта. Неужели стартап столько жрёт?
выставил оптимизацию в с/с++, уже 1,93 кило

Тут асм для ARM. (ссылка на wasm.ru)
stm32asm.ru
Cortex-M3 programming manual PM0056
Справочное руководство по процессору ARM7TDMI
Некоторые вещи можно узнать по описанию других м.к.
Ознакомительное руководство по ARM-микроконтроллерам Cortex-M3
ARM аccемблер
ARM: как быстро начать писать на ассемблере
Описание ARM
ARM Cortex M3 Assembly Language Example
Даташит на отечественный cortex-m3
Дальше свой топик буду пополнять заметками для себя, но возможно они понадобятся ещё кому нибудь.

Замигал на асме называется, пока без задержек и мало понимаю как это работает. Кроме тех стандарный mov, ldr понятно. Не понятно с макросами.

				GET	 stm32f10x.asm
				GET macro.asm
				AREA |header code|,CODE,READONLY
                ENTRY
                EXPORT __main
__main
                nop
                nop
                nop
				
		            ;; Enable the Port C peripheral clock by setting bit 4
			    ldr r6, = RCC_APB2ENR ;Заносим  число в рег. r6
			    mov r0, #RCC_APB2ENR_IOPCEN; Заносим номер порта в r0
			    str r0, [r6];А тут как-то хитро это всё соеденяется и RCC_APB2ENR получает свой RCC_APB2ENR_IOPCEN.
				; Далее по аналогии подставляем в регистры андреса нужный регистров и нужный значений эти регистров а потом всё в str загоняется и вроде как работет.
				ldr r6, = GPIOC_CRH
				ldr r0, = GPIO_CRH_MODE8
				str r0, [r6]
				;
				
metka1          
				ldr r6, = GPIOC_ODR
				ldr r0, =GPIO_ODR_ODR8
				str r0,[r6]
				
				ldr r6, = GPIOC_ODR
				ldr r0, = 0
				str r0,[r6]
				b metka1        ;зацикливаем
                END
  • 0
  • 07 сентября 2012, 00:38
  • sasha85ru
  • 1
Файлы в топике: stm32f10x.zip

Комментарии (12)

RSS свернуть / развернуть
сдвинулся с мёртвой точки :-)
0
А чем вызван интерес к арм-асму?
0
  • avatar
  • psv
  • 08 сентября 2012, 00:36
интересно.
Вот смотрите.

	GET      stm32f10x.asm
	GET      macro.asm
	AREA |header code|,CODE,READONLY
	ENTRY
	EXPORT __main
__main

	reg_bit RCC_APB2ENR,RCC_APB2ENR_IOPCEN
        reg_bit GPIOC_CRH,GPIO_CRH_MODE8
  
                            
while         
	reg_bit GPIOC_ODR,GPIO_ODR_ODR8
	reg_bit GPIOC_ODR, 0
	b while        ;зацикливаем
	END 


всего ни чего надо чтобы помигать…
0

	MACRO
;
	reg_bit $reg,$bit
	ldr r6, = $reg
	ldr r0, = $bit
	str r0,[r6]
	
	MEND
0
Угу. На весь листинг — одна настоящая команда асма. Остальное — макросы. Не говоря уже о подтягиваемых зависимостях.
0
  • avatar
  • Vga
  • 08 сентября 2012, 01:17
А без макросов в арм-асме можно свихнуться.
Мои проги под арм мало напоминают асм. Например:
;main

		clock_porta	enable
		clock_portb	enable
		clock_afio	enable
		clock_spi1	enable
		clock_usart1	enable
		clock_adc1	enable
		clock_timer2	enable
		clock_timer3	enable
		clock_power	enable
		clock_backup	enable
		clock_usart3	enable
;gpio config-----------------------------------------------
		startportconfig portA,0
		pinconfig 0,out50push_pull		;PA0 - push_pull 50MHz	cs
		pinconfig 1,out50push_pull		;PA1 - push_pull 50MHz	rs
		pinconfig 4,out50push_pull		;PA2 - push_pull 50MHz	reset

		pinconfig 5,out10push_pull_alt	;PA5 - push_pull  10MHz	 alt spi1_sck
		pinconfig 6,infloat				;PA6 - input				psi1_miso; вход тахометра
		pinconfig 7,out10push_pull_alt	;PA7 - push_pull  10MHz	 alt spi1_mosi
		endportconfig portA,0

		startportconfig portA,1
		pinconfig 10,infloat			;PA10 - infloat	 (rx usart1)
		pinconfig 12,out10push_pull		;PA12 - push_pull  10MHz (servo signal)
		endportconfig portA,1

		startportconfig portB,0
		pinconfig 0,inanm				;PB0 - ANALOG input	(IN8)
		pinconfig 1,infloat				;PB1 - infloat (tim3_ch4 вход тахометра)
		endportconfig portB,0

		startportconfig portB,1
		pinconfig 10,out10push_pull		;PB10 - push_pull  10MHz	test0 pin
		pinconfig 11,infloat			;PB11 - infloat	 (rx usart3)
;		pinconfig 11,out10push_pull		;PB11 - push_pull  10MHz	test1 pin
		endportconfig portB,1
;end gpio config-------------------------------------------
;SPI config------------------------------------------------
		setbits spi1, spi_cr1, spi_cr1_br_lbs, spi_cr1_br_width, spi_cr1_br_2 ;baud rate control (Fpclk/2)
		resbit spi1, spi_cr1, spi_cr1_cpol_bit
		resbit spi1, spi_cr1, spi_cr1_cpha_bit		;cpha=0,cpol=0 _/ 
		resbit spi1, spi_cr1, spi_cr1_dff_bit		;8-bit data frame format
		resbit spi1, spi_cr1, spi_cr1_lsbfirst		;msb transmitted first
		setbit spi1, spi_cr1, spi_cr1_mstr_bit		;master configuration
		setbit spi1, spi_cr1, spi_cr1_ssm			;
		setbit spi1, spi_cr1, spi_cr1_ssi			;NSS internal = 1
		setbit spi1, spi_cr1, spi_cr1_spe_bit		;peripheral enabled						
;end SPI config--------------------------------------------
;usart1 config---------------------------------------------
;получаем информацию по датчикам от сопроцессора
;9600 baud, 1 Start Bit, 8 Data Bits, 1.0 Stop Bits, No Parity
;--------------------------------------
		setbit usart1, usart_cr1, usart_cr1_re			;receiver enable
;div=fck/(baud*16)=24M/(9600*16)=156,25 (div_mantissa=156, div_fraction=16*0,25=4)
;usart_gtpr <- (156<<4) + 4 = 2500
		mov32 r0,#usart1
		savecw 2500, usart_brr
		setbit usart1,usart_cr1,usart_cr1_rxneie		;RXNE interrupt enable
		setbit usart1, usart_cr1, usart_cr1_ue			;usart enable
;end usart1 config-----------------------------------------

;usart3 config---------------------------------------------
;получаем код кнопки ir-пульта с сопроцессора
;9600 baud, 1 Start Bit, 8 Data Bits, 1.0 Stop Bits, No Parity
;--------------------------------------
		setbit usart3, usart_cr1, usart_cr1_re			;receiver enable
;div=fck/(baud*16)=24M/(9600*16)=156,25 (div_mantissa=156, div_fraction=16*0,25=4)
;usart_gtpr <- (156<<4) + 4 = 2500
		mov32 r0,#usart3
		savecw 2500, usart_brr
		setbit usart3,usart_cr1,usart_cr1_rxneie		;RXNE interrupt enable
		setbit usart3, usart_cr1, usart_cr1_ue			;usart enable
;end usart3 config-----------------------------------------

;adc1 config-------------------------------------------------------------------
;меряем напряжение батареи через делитель на 11 (10k/1k;20k/2k;...)
		setbits adc1, adc_sqr1, adc_sqr1_l_lbs, adc_sqr1_l_width, adc_sqr_l1			;1 conversion
		setbits adc1, adc_sqr3, adc_sqr3_sq1_lbs, adc_sqr3_sq_width, adc_cr1_awdch_8	;select the ADCx_IN8 input channel
		setbits adc1, adc_smpr2, adc_smpr2_smp0_lbs, adc_smpr1_smp_width, adc_smp_55_5	;sample time selection
		resbit adc1, adc_cr2, adc_cr2_align			;right alignment
		resbit adc1, adc_cr2, adc_cr2_cont			;single conversion mode
		setbit adc1, adc_cr2, adc_cr2_exttrig		;conversion on external event enabled
		setbits adc1, adc_cr2, adc_cr2_extsel_lbs, adc_cr2_extsel_width, adc_cr2_extsel_swstart	;swstart
;	setbit adc1, adc_cr2, adc_cr2_cont
		setbit adc1, adc_cr1, adc_cr1_eocie			;interrupt enable for end of conversion
		setbit adc1, adc_cr2, adc_cr2_adon			;enable ADC and to start conversion
;end adc1 config---------------------------------------------------------------
;tim2 config-------------------------------------------------------------------
;формирует servo сигнал
		mov32 r0,#tim2
		savecw 48, gpt_psc						;set prescaler
		savecw 9500, gpt_arr					;set reload
		savecw 9500-(450+450/2), gpt_ccr4		;set capture/compare register 4
		resbit tim2, gpt_cr1, gpt_cr1_dir		;upcounter
		setbit tim2, gpt_dier,gpt_dier_uie		;Update interrupt enable

		setbit tim2, gpt_ccer, gpt_ccer_cc4e	;Capture/Compare 4 output enable
		setbit tim2, gpt_dier, gpt_dier_cc4ie	;Capture/Compare 4 interrupt enable
		 
		setbit tim2, gpt_cr1, gpt_cr1_cen		;counter enabled
;end tim2 config---------------------------------------------------------------
;tim3 config-------------------------------------------------------------------
;захватывает фронт импульса обмотки мотора (для определения скорости)
		mov32 r0,#tim3
		savecw 240, gpt_psc						;set prescaler
		savecw 65535, gpt_arr					;set reload

		resbit tim3, gpt_cr1, gpt_cr1_dir		;upcounter
		setbits tim3, gpt_ccmr2, gpt_ccmr2_cc4s_lbs, gpt_ccmr2_cc4s_width, gpt_ccmr2_cc4s_ti4
		;CC4 channel is configured as input, IC4 is mapped on TI4
		resbit tim3, gpt_ccer, gpt_ccer_cc4p	;capture is done on a rising edge of IC4
		setbit tim3, gpt_dier, gpt_dier_cc4ie	;CC4 interrupt enable
		setbit tim3, gpt_ccer, gpt_ccer_cc4e	;capture enable
		 
		setbit tim3, gpt_cr1, gpt_cr1_cen		;counter enabled
;end tim3 config---------------------------------------------------------------

Такой код легче поддерживать и от асма весьма недалеко.
0
  • avatar
  • psv
  • 08 сентября 2012, 13:44
Ага, простыня каких-то макросов и мутное использование регистров внутри них. Фтопку такой ассемблер. На ARM куда разумней писать на С/С++.
Да и ассемблер там вполне вменяемый. Просто такой объем кода, какой типичен для этих МК писать на асме не самое разумное решение.
0
  • avatar
  • Vga
  • 08 сентября 2012, 13:49
Асм там, конечно, вменяемый, но доступ к памяти и битам — 2-3 асм команды, и их глупо не упрятать в макрос. Это как знаменитая outi для avr от DI. А C я не умею и не хочу — у каждого свои недостатки :)
0
  • avatar
  • psv
  • 08 сентября 2012, 14:03
Асм там, конечно, вменяемый, но доступ к памяти и битам — 2-3 асм команды, и их глупо не упрятать в макрос.
… не стоит забывать, что излишнее использование макросов раздувает объем кода, так что везде хороша «золотая середина» :)
0
Речь не о макросах — заменителях подпрограмм, а о макросах, где мы заменяем одной строкой 2-3 НЕОБХОДИМЫЕ асм команды. Где раздувание кода?
Например:
Загрузка байтовой переменной в r1
Вместо того чтобы каждый раз писать
mov32 r0,#base
ldrb r1,[r0]
пишем макрос

macro
loadb $base
mov32 r0,#$base
ldrb r1,[r0]
mend

и в программе одна строка
loadb 0x20000000
0
  • avatar
  • psv
  • 08 сентября 2012, 17:16
макросы вещь хорошая
0
Идём СЮДА и узнаём что надо скопировать system_stm32f10x.c из каталога .\Keil\ARM\Startup\ST\STM32F10x в каталог с проектом.
Снова нажимаем F7 и ура, всё скомпилилось.
… ни какие system_stm32f10x.c для компиляции не нужны.
Неужели стартап столько жрёт?
startup отъедает ~300 байт, и не стоит забывать о таблице векторов прерываний :)
Чистый код на ассемблере «для помигать» занимает примерно 100 байт.
0
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.