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	: avr@atmel.com
;*
;* 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

Jednak się myliłem, da się odwoływać do funkcji zewnętrznych pomiędzy ASM i C, prawdopodobnie innymi językami również. Nie wiem jak to mogłem przeoczyć szukając, ale jest nawet Atmel appnote na ten temat:

http://www.atmel.com/dyn/resources/prod_documents/doc1234.pdf

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

Dołącz do dyskusji, napisz odpowiedź!

Jeśli masz już konto to zaloguj się teraz, aby opublikować wiadomość jako Ty. Możesz też napisać teraz i zarejestrować się później.
Uwaga: wgrywanie zdjęć i załączników dostępne jest po zalogowaniu!

Anonim
Dołącz do dyskusji! Kliknij i zacznij pisać...

×   Wklejony jako tekst z formatowaniem.   Przywróć formatowanie

  Dozwolonych jest tylko 75 emoji.

×   Twój link będzie automatycznie osadzony.   Wyświetlać jako link

×   Twoja poprzednia zawartość została przywrócona.   Wyczyść edytor

×   Nie możesz wkleić zdjęć bezpośrednio. Prześlij lub wstaw obrazy z adresu URL.

×
×
  • 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.