Skocz do zawartości

Wstawka assemblera w c


Zolw2305

Pomocna odpowiedź

Witam. Mam ze strony Atmela kod źródłowy realizujący programowy UART, napisany w asemblerze (AVR305). Chciałbym w c wywoływać funkcje, które realizowały by podprogramy putchar, getchar (nadawanie, odbiór). Wiem że muszę dodać w makefile plik.S ale nie wiem jak zrealizować wywoływanie poszczególnych funkcji. Np aby przesłać jakieś dane, chciałbym wywołać funkcję putchar(data). Lub aby dane odebrać - data = getchar(). W jaki sposób wskazać w pliku asemblera argument data, który miałby zostać użyty do wysłania?

Kompilator - avr-gcc

Kod źródłowy z asemblera:

;* Title		: Half Duplex Interrupt Driven Software UART
;* Version		: rev. 1.2 (24-04-2002), reset vector added
;*			: rev. 1.1 (27.08.1997)
;* Last updated		: 24-04-2002
;* Target		: AT90S1200 
;*			  Can be used with all AVR Device. In devices without HW
;*			  stack the stackpointer must be set up.
;*
;* Support email	: [email protected]
;*
;* Code Size		: 32 Words
;* Low Register Usage	: 0
;* High Register Usage	: 4
;* Interrupt Usage	: None
;*
;* DESCRIPTION
;* This Application note contains a very code efficient software UART.
;* The example program receives one character and echoes it back.
;***************************************************************************

.include "m16def.inc"

;***** Pin definitions

.equ	RxD	=0					;Receive pin is PD0
.equ	TxD	=1					;Transmit pin is PD1

;***** Global register variables

.def	bitcnt	=R16			;bit counter
.def	temp	=R17			;temporary storage register

.def	Txbyte	=R18			;Data to be transmitted
.def	RXbyte	=R19			;Received data

.cseg
.org 0
	rjmp	reset
;***************************************************************************
;*
;* "putchar"
;*
;* This subroutine transmits the byte stored in the "Txbyte" register
;* The number of stop bits used is set with the sb constant
;*
;* Number of words	:14 including return
;* Number of cycles	:Depens on bit rate
;* Low registers used	:None
;* High registers used	:2 (bitcnt,Txbyte)
;* Pointers used	:None
;*
;***************************************************************************
.equ		sb	=1				;Number of stop bits (1, 2, ...)

putchar:	ldi	bitcnt,9+sb		;1+8+sb (sb is # of stop bits)
		com	Txbyte			;Inverte everything
		sec					;Start bit

putchar0:	brcc	putchar1	;If carry set
		cbi	PORTD,TxD		;    send a '0'
		rjmp	putchar2	;else	

putchar1:	sbi	PORTD,TxD		;    send a '1'
		nop

putchar2:	rcall UART_delay	;One bit delay
		rcall UART_delay

		lsr	Txbyte			;Get next bit
		dec	bitcnt			;If not all bit sent
		brne	putchar0	;   send next
							;else
		ret					;   return


;***************************************************************************
;*
;* "getchar"
;*
;* This subroutine receives one byte and returns it in the "Rxbyte" register
;*
;* Number of words	:14 including return
;* Number of cycles	:Depens on when data arrives
;* Low registers used	:None
;* High registers used	:2 (bitcnt,Rxbyte)
;* Pointers used	:None
;*
;***************************************************************************

getchar:	ldi 	bitcnt,9	;8 data bit + 1 stop bit

getchar1:	sbic 	PIND,RxD	;Wait for start bit
		rjmp 	getchar1

		rcall UART_delay	;0.5 bit delay

getchar2:	rcall UART_delay	;1 bit delay
		rcall UART_delay		

		clc					;clear carry
		sbic 	PIND,RxD	;if RX pin high
		sec					;

		dec 	bitcnt		;If bit is stop bit
		breq 	getchar3	;   return
							;else
		ror 	Rxbyte		;   shift bit into Rxbyte
		rjmp 	getchar2	;   go get next

getchar3:	ret


;***************************************************************************
;*
;* "UART_delay"
;*
;* This delay subroutine generates the required delay between the bits when
;* transmitting and receiving bytes. The total execution time is set by the
;* constant "b":
;*
;*	3ˇb + 7 cycles (including rcall and ret)
;*
;* Number of words	:4 including return
;* Low registers used	:None
;* High registers used	:1 (temp)
;* Pointers used	:None
;*
;***************************************************************************
; Some b values: 	(See also table in Appnote documentation)
;
; 1 MHz crystal:
;   9600 bps - b=14
;  19200 bps - b=5
;  28800 bps - b=2
;
; 2 MHz crystal:
;  19200 bps - b=14
;  28800 bps - b=8
;  57600 bps - b=2

; 4 MHz crystal:
;  19200 bps - b=31
;  28800 bps - b=19
;  57600 bps - b=8
; 115200 bps - b=2

.equ	b		=31	;4800 bps @ 1 MHz crystal


UART_delay:		ldi	temp,b
UART_delay1:	dec	temp
			brne	UART_delay1

			ret

;***** Program Execution Starts Here
Link do komentarza
Share on other sites

Z tego co mi wiadomo, AVR Assembler nie przewiduje takiego łączenia z modułami napisanymi w językach wyższego poziomu jak na przykład asembler na x86. Swego czasu również szukałem rozwiązania tego problemu i nic sensownego nie znalazłem. Jedyna namiastka to dyrektywa .include kopiująca na swoje miejsce całą zawartość wskazanego pliku przed asemblacją. Jeżeli masz dobrze napisaną bibliotekę w pliku .asm to możesz ją w ten sposób dołączyć do innego pliku asemblera i na tym praca na wielu plikach się kończy. Jeżeli natomiast chcesz korzystać ze wstawek asemblerowych w C, musisz użyć komendy

_asm
{
   //kod w asemblerze
}

W twoim wypadku będzie to utworzenie zwykłych funkcji w C i dodanie wstawki asemblerowej jako ciało funkcji. Natomiast żeby zapisywać/wczytywać wartości będziesz musiał dodać odpowiednie operacje na rejestrach.

Link do komentarza
Share on other sites

Witam.

Zadanie jest w sumie proste.

Plik asm należy podzielić na funkcje, nadać im nazwy i zapisać z rozszerzeniem .s

Następnie utworzyć plik nagłówkowy .h i dołączyć obydwa do projektu.

Kiedyś napisałem artykuł na forum o dodawaniu programowych opóźnień

z wykorzystaniem wstawek asemblerowych - poszukaj a przekonasz się.

Pozdrawiam

Zuk

Link do komentarza
Share on other sites

Zarejestruj się lub zaloguj, aby ukryć tę reklamę.
Zarejestruj się lub zaloguj, aby ukryć tę reklamę.

jlcpcb.jpg

jlcpcb.jpg

Produkcja i montaż PCB - wybierz sprawdzone PCBWay!
   • Darmowe płytki dla studentów i projektów non-profit
   • Tylko 5$ za 10 prototypów PCB w 24 godziny
   • Usługa projektowania PCB na zlecenie
   • Montaż PCB od 30$ + bezpłatna dostawa i szablony
   • Darmowe narzędzie do podglądu plików Gerber
Zobacz również » Film z fabryki PCBWay

Doczytałem jak to jest dokładnie. Standardowy atmelowski asembler nie daje się połączyć bezpośrednio z projektami w avr-gcc ponieważ kompilator używa innych dyrektyw. Ten appnote który wyżej podlinkowałem zawiera trochę przydatnych informacji ale również nie używa oryginalnego asemblera, tylko wersję kompatybilną z używanym tam kompilatorem. Który z resztą jest inny niż avr-gcc.

Aby w projekcie avr-gcc zintegrować pliki c i asemblera, trzeba pisać w asemblerze avr-gcc opisanym w manualu do avr-libc. Zestaw instrukcji jest w nim taki sam, ale różni się wprowadzaniem danych dla preprocesora. Include, define i komentarze używa się jak w C, nie przydziela się dokładnych adresów pamięci w których znajdą się określone funkcje i ogólnie dyrektywy się trochę różnią. Standardowe funkcje np LOW(xxx), HIGH(xxx) też wyglądają inaczej i można używać dodatkowych makr. Pewnie są jeszcze inne różnice których tutaj nie wypisałem.

Link do komentarza
Share on other sites

Bądź aktywny - zaloguj się lub utwórz konto!

Tylko zarejestrowani użytkownicy mogą komentować zawartość tej strony

Utwórz konto w ~20 sekund!

Zarejestruj nowe konto, to proste!

Zarejestruj się »

Zaloguj się

Posiadasz własne konto? Użyj go!

Zaloguj się »
×
×
  • Utwórz nowe...

Ważne informacje

Ta strona używa ciasteczek (cookies), dzięki którym może działać lepiej. Więcej na ten temat znajdziesz w Polityce Prywatności.