embeded/AVR (ATmega,ATtiny)2009. 10. 9. 10:59
outp() inp()는 매크로이다.
정확한 시기는 모르겠지만, winAVR-20050414 버전 이후 제외된 것으로 보인다.
물론 <compat/deprecated.h> 를 사용하면 호환되도록 작동은 가능할 것으로 보이지만,

문법적으로 깔끔하지 않고, 표준 C를 따르지 않는(이 부분은 좀 이해가 안됨) 이유로 인해서
불편함을 감수하고 위의 매크로가 제외되었다고 한다.

There was a discussion a while back on the avr-gcc mailing list.  Some
"old stuff" has been purged.  Some people are not happy about it.  But
the purged macros were non-standard, had confusing syntax and unclear
semantics, and had been deprecated for over two years, so (IMHO) the
maintainers were justified in purging them.

The quick fix for legacy code is to create a new header (e.g.
"legacy.h") that defines the purged macros for you.  E.g.,

   #define sbi(p,b) (p) |= (1<<(b))
   #define cbi(p,b) (p) &= ~(1<<(b))

etc.  Then #include "legacy.h" in legacy code as a stopgap measure to
get that code to compile with the new compiler.

And be sure to _NOT_ #include "legacy.h" in new code.

Regards,

                               -=Dave

[링크 : http://www.embeddedrelated.com/usenet/embedded/show/25084-1.php]


[링크 : http://winavr.sourceforge.net/]



20091022 추가>
outp(value, PORTn); 은
PORTn = valuel 로 사용하면 된다.

예를들어,
outp(0xff, PORTA); 는
PORTA = 0xff; 로 사용한다.
Posted by 구차니
embeded/AVR (ATmega,ATtiny)2009. 10. 8. 23:13
에코 서버라고 하니 먼가 거창한데,
간단하게 입력하면 그걸 그대로 돌려줘서 화면에 나타나게 하는 프로그램이다.
시리얼로 전송하면, 받는쪽에서 그 값을 돌려주지 않으면 터미널에서 그 값이 출력되지 않는다.
가장 간단하고, 확실한 테스트 방법이라서 일단 echo 하도록 하는데 먼가 험난했다 ㄱ-

아무튼 개인적으로 선호하는 115200bps - N - 8 - 1 로 설정하고, UART0를 통해 UART echo server를 만들어보자





오늘 필요한 녀석은
#include <avr/interrupt.h>

ISR(USART0_RX_vect)
{
    UDR0 = UDR0;
}
요렇게 두 부분이다.

위의 헤더는 ISR() 이라는 매크로를 사용하게 하는 것이고,
ISR은 Interrupt Serive Routine의 약자이다.

예전에는 SIGNAL(SIG_UART0_RECV) 로 사용했을 것이지만,
winAVR 버전이 올라가면서 ISR()로 바뀐 것으로 알고 있다. (물론 사용중인 버전이 20080610 버전으로 좀 오래됐다 ㅠ.ㅠ)

아무튼 USART0_RX_vect 라는 것은 iom128.h의 432 라인에 기술되어있다.
(iom128.h는 <avr/io.h>와 makefile의 cpu 선언에 의해서 자동으로 불려지는 파일이다)
/* USART0, Rx Complete */
#define USART0_RX_vect            _VECTOR(18)
#define SIG_USART0_RECV            _VECTOR(18)
#define SIG_UART0_RECV            _VECTOR(18)

시리얼포트 초기화시에는 당연히 UART RX 인터럽트를 사용하도록 설정을 해야하고,
전역 인터럽트를 사용하도록 해주어야 한다.

UART 인터럽트는 UCSR0A/B/C 레지스터로 조작을 해준다.
    /* for UART */
    /* "BaudRate" related setting */
    UBRR0H = 0;
    UBRR0L = 8; // 115k with U2X = 0
    UCSR0A = 0x00; // U2X = 0;

   /* "Interrupt" related setting */
    UCSR0B = 0x98;

   /* "Sync or Async mode - Parity - stop bits - data bits" related setting*/
    UCSR0C = 0x06; //Asyncronous - no parity - 1bits(stop) - 8bits(data)

UCSR0A  레지스터는 U2X0 를 제외하면 전부 Status Flag 이므로 U2X0를 사용하지 않는다면 0x00으로 설정한다.
UBBR0H 와 UBBR0L 은 BaudRate와 관련된 것으로, 클럭과 원하는 BaudRate에 따라 변하지만,
귀찮으면, 데이터 시트에 나와있는 값으로 입력을 하면된다. (위의 값은 계산하지 않고 그냥 데이터시트 값을 사용한 것이다)

그리고 U2X는 UCSR0A의 비트로, 에러율을 낮추기 위해 2배 속도로 샘플링하는 것이다.
(디바이더(Divider)의 값을 반으로 줄여, 샘플링을 자주해서 값을 놓치지 않도록 한다)

• Bit 1 – U2Xn: Double the USART Transmission Speed
This bit only has effect for the asynchronous operation. Write this bit to zero when using synchronous operation.
Writing this bit to one will reduce the divisor of the baud rate divider from 16 to 8 effectively doubling the transfer rate for asynchronous communication.

UCSR0B  레지스터의 98 값은 인터럽트 관련 설정값이다.
일단 Bit 5를 set 하게 되면, 원하는대로 echo 되지 않으니
    UCSR0B = 0xD8 이나
    UCSR0B = 0x98 로 설정해주면 된다.
(Bit 7 에서 Bit 4까지 1001(2) 이므로 0x90 이고 (RX enable / Receiver Enable)
 Bit 3 으로 인해 0x08, 합쳐서 0x98이 된다.)


UCSR0C  레지스터는 Asynchronous / Synchronous mode 를 고르고,
                어떤 종류의 패리티를 쓸지, 스탑 비트는 몇 비트를 할지, 데이터는 몇 비트로 사용할지 결정한다.
                친숙하게 보는 115200-N-8-1 이러한 설정값에 대한것 중 BaudRate를 제외한 거의 모든것을 결정한다.

그리고 sei() 라는 매크로를 통해, 전역 인터럽트를 사용가능하도록 설정해주어야 한다.
#define sei ()      
#include <avr/interrupt.h>

Enables interrupts by setting the global interrupt mask.
This function actually compiles into a single line of assembly, so there is no function call overhead.

[링크: http://www.nongnu.org/avr-libc/user-manual/group__avr__interrupts.html]

머.. sei() 친구로 cli()도 있지만, 어셈블리 명령어인데 명확한 약자로 보기에는 조금 애매함이 있다.
SEtting global Interrupt
CLearing global Interrupt
more <avr/interrupt.h>

#if defined(__DOXYGEN__)
/** \def sei()
    \ingroup avr_interrupts

    \code #include <avr/interrupt.h> \endcode

    Enables interrupts by setting the global interrupt mask. This function
    actually compiles into a single line of assembly, so there is no function
    call overhead. */
#define sei()
#else  /* !DOXYGEN */
# define sei()  __asm__ __volatile__ ("sei" ::)
#endif /* !DOXYGEN */

#if defined(__DOXYGEN__)
/** \def cli()
    \ingroup avr_interrupts

    \code #include <avr/interrupt.h> \endcode

    Disables all interrupts by clearing the global interrupt mask. This function
    actually compiles into a single line of assembly, so there is no function
    call overhead. */
#define cli()
#else  /* !DOXYGEN */
# define cli()  __asm__ __volatile__ ("cli" ::)
#endif /* !DOXYGEN */



[링크: http://blog.yurihan.net/]

Posted by 구차니
embeded/AVR (ATmega,ATtiny)2009. 10. 7. 23:13
us-tech 사의 제품을 사용해서, 아래 링크의 예제를 사용하려고 했더니.
outp 매크로를 이용하는 구버전이라서 조금 고민하다가 데이터시트를 읽고 시도했다.

    /* for USART */
    UBRR0H = 0;
    UBRR0L = 8; // 115200bps with U2X = 0
    UCSR0A = 0x00; // U2X = 0;
    UCSR0B = 0xF8;
    UCSR0C = 0x06; // Asyncronous - no parity - 1bits(stop) - 8bits(data)


USART Baud Rate Register (UBRR) 은 일종의 divider의 설정값으로, 클럭을 분기하는데 사용하는 값이라고 생각이 된다.
아무튼 16.0MHz 같은녀석은, Error 율이 0% 인녀석이 일반적으로 사용하는 115k 이하에는 없으므로 그리 좋지 않다.

그리고 U2X는
Bit 1 – U2Xn: Double the USART Transmission Speed
This bit only has effect for the asynchronous operation. Write this bit to zero when using synchronous operation.
Writing this bit to one will reduce the divisor of the baud rate divider from 16 to 8 effectively doubling the transfer rate for asynchronous communication
라고 나와있 듯, asynchronous 모드에서만 작동이 되며, 클럭을 두배로 증가시켜 에러율을 줄이는 효과를 보인다.

아무튼, USART / UART를 설정하는데 사용되는 레지스터는
UCSR0A, UCSR0B, UCSR0C 세가지가 있으며

UCSR0A에는 U2X를 제외하면 실질적으로 전부 Status 레지스터이다.
• Bit 7 – RXCn: USART Receive Complete
• Bit 6 – TXCn: USART Transmit Complete
• Bit 5 – UDREn: USART Data Register Empty
• Bit 4 – FEn: Frame Error
• Bit 3 – DORn: Data OverRun
• Bit 2 – UPEn: Parity Error
• Bit 1 – U2Xn: Double the USART Transmission Speed
• Bit 0 – MPCMn: Multi-Processor Communication Mode

UCSR0B에는 인터럽트와 , TX / RX enable 를 설정하며
• Bit 7 – RXCIEn: RX Complete Interrupt Enable
• Bit 6 – TXCIE: TX Complete Interrupt Enable
• Bit 5 – UDRIEn: USART Data Register Empty Interrupt Enable
• Bit 4 – RXENn: Receiver Enable
• Bit 3 – TXENn: Transmitter Enable
• Bit 2 – UCSZn2: Character Size
• Bit 1 – RXB8n: Receive Data Bit 8
• Bit 0 – TXB8n: Transmit Data Bit 8

UCSR0C에는 눈에 익숙한 N-8-1 (No Parity - 8bit data - 1bit stop) 이러한 설정값을 조절한다.
• Bit 7 – Reserved Bit
• Bit 6 – UMSELn: USART Mode Select
• Bit 5:4 – UPMn1:0: Parity Mode
• Bit 3 – USBSn: Stop Bit Select
• Bit 2:1 – UCSZn1:0: Character Size
• Bit 0 – UCPOLn: Clock Polarity


데이터를 TX로 출력하려면 UDR0 = data; 를 하면된다.




[링크 : http://www.us-technology.co.kr/lecture/lecture_main.asp?mode=1&smode=6]
Posted by 구차니

AVR Studio에서 읽은 us-technology.co.kr에서 판매하는 보드의 기본 퓨즈 비트 설정값이다.
CKOPT가 원래 체크 되어 있어야 했던거 같은데 흐음..
Posted by 구차니
embeded/AVR (ATmega,ATtiny)2009. 5. 27. 22:41
ubuntu에는
/dev/paraport0 가 아닌
/dev/parport0 로 장치명이 되어 있었다.



그리고 그냥 패널에서 실행할경우 일반 사용자 모드로 구동이 되므로
아래와 같이 device를 열 수 없다는 에러가 발생한다.

패널에서 실행방법을 변경하거나
아니면 콘솔에서
$ sudo gnome-avrdude &
로 실행을 하면 해결이 된다.



패러럴로 사용시 stk200으로 프로그래머를 설정해주면
ATMega128을 패러럴로 읽을 수 있다.
Posted by 구차니
embeded/80512009. 4. 21. 17:51
신기한 현상을 발견했다.
코드의 위치에 따라 용량이 상당히 많이 변한다는 사실!

for(idx = 0; idx < len; idx++)
{
	tempUnicode = input[idx];
	if(0x0020 <= tempUnicode && tempUnicode < 0x0080)	res = (char)(tempUnicode & 0x00FF);
	else if(tempUnicode == 0x00E1)						res = 0x80;
	else if(tempUnicode == 0x00E0)						res = 0x81;
	...
	else if(0x0400 < tempUnicode && tempUnicode <= 0x045F)
	{
		switch(tempUnicode)
		{
			case 0x0401:	res = 192 +	0;	break;
			case 0x0402:	res = 192 +	1;	break;
			...
		}
	}
	else												res = ' ';
}

Program Size: data=187.7 xdata=0 code=9505

for(idx = 0; idx < len; idx++)
{
	tempUnicode = input[idx];
	if(0x0020 <= tempUnicode && tempUnicode < 0x0080)	res = (char)(tempUnicode & 0x00FF);
	else if(0x0400 < tempUnicode && tempUnicode <= 0x045F)
	{
		switch(tempUnicode)
		{
			case 0x0401:	res = 192 +	0;	break;
			case 0x0402:	res = 192 +	1;	break;
			...
		}
	}
	else if(tempUnicode == 0x00E1)						res = 0x80;
	else if(tempUnicode == 0x00E0)						res = 0x81;
	...
	else												res = ' ';
}

Program Size: data=189.7 xdata=0 code=9698

바뀐건, else if() 내부에 switch()가 있는 경우의 위치가 바뀐 경우이다.
속도 최적화를 위해 빨리빠져 나갈수 있도록 위로 옮겨 주었떠니 용량이 무려!!!
193 바이트나 늘어났다.. OTL

아마도..
코드사이즈가 커지면서 MOV대신 MOVX 라던가..
이런식으로 명령어에 넣어야 하는 주소의 크기가 달라지면서 발생하는 문제가 아닐까 생각이 된다.
Posted by 구차니
embeded/80512009. 4. 21. 17:36
if(tempUnicode == 0x00E0)        output[out_idx] = 0x80;
else if(tempUnicode == 0x00E0) output[out_idx] = 0x80;
else if(tempUnicode == 0x00E0) output[out_idx] = 0x80;
...
else if(tempUnicode == 0x00E0) output[out_idx] = 0x80;
// 대략 128개

이녀석을 컴파일 하면
Program Size: data=189.7 xdata=0 code=10418

if(tempUnicode == 0x00E0)        res = 0x80;
else if(tempUnicode == 0x00E0) res = 0x80;
else if(tempUnicode == 0x00E0) res = 0x80;
...
else if(tempUnicode == 0x00E0) res = 0x80;
// 대략 128개

이녀석을 컴파일 하면
Program Size: data=187.7 xdata=0 code=9518


별거 아닌 코드이지만, 900byte 차이가 난다.
결론. 8051에서는 배열사용을 자제하자(switch / if-else 문처럼 한번의 액션에 분기되는 거라면)
Posted by 구차니
embeded/AVR (ATmega,ATtiny)2009. 4. 20. 00:37
패러럴이면 STK-200 호환
USB면 STK-500 호환이라고 한다.


Valid programmers are:
  c2n232i  = serial port banging, reset=dtr sck=!rts mosi=!txd miso=!cts [/usr/local/etc/avrdude.conf:834]
  dasa3    = serial port banging, reset=!dtr sck=rts mosi=txd miso=cts [/usr/local/etc/avrdude.conf:821]
  dasa     = serial port banging, reset=rts sck=dtr mosi=txd miso=cts [/usr/local/etc/avrdude.conf:808]
  siprog   = Lancos SI-Prog <http://www.lancos.com/siprogsch.html> [/usr/local/etc/avrdude.conf:795]
  ponyser  = design ponyprog serial, reset=!txd sck=rts mosi=dtr miso=cts [/usr/local/etc/avrdude.conf:782]
  89isp    = Atmel at89isp cable            [/usr/local/etc/avrdude.conf:749]
  frank-stk200 = Frank STK200                   [/usr/local/etc/avrdude.conf:735]
  blaster  = Altera ByteBlaster             [/usr/local/etc/avrdude.conf:722]
  ere-isp-avr = ERE ISP-AVR <http://www.ere.co.th/download/sch050713.pdf> [/usr/local/etc/avrdude.conf:712]
  atisp    = AT-ISP V1.1 programming cable for AVR-SDK1 from <http://micro-research.co.th/>  [/usr/local/etc/avrdude.conf:702]
  dapa     = Direct AVR Parallel Access cable [/usr/local/etc/avrdude.conf:691]
  xil      = Xilinx JTAG cable              [/usr/local/etc/avrdude.conf:678]
  futurlec = Futurlec.com programming cable. [/usr/local/etc/avrdude.conf:661]
  abcmini  = ABCmini Board, aka Dick Smith HOTCHIP [/usr/local/etc/avrdude.conf:651]
  picoweb  = Picoweb Programming Cable, http://www.picoweb.net/ [/usr/local/etc/avrdude.conf:641]
  sp12     = Steve Bolt's Programmer        [/usr/local/etc/avrdude.conf:630]
  alf      = Nightshade ALF-PgmAVR, http://nightshade.homeip.net/ [/usr/local/etc/avrdude.conf:614]
  bascom   = Bascom SAMPLE programming cable [/usr/local/etc/avrdude.conf:604]
  dt006    = Dontronics DT006               [/usr/local/etc/avrdude.conf:594]
  pony-stk200 = Pony Prog STK200               [/usr/local/etc/avrdude.conf:582]
  stk200   = STK200                         [/usr/local/etc/avrdude.conf:566]
  bsd      = Brian Dean's Programmer, http://www.bsdhome.com/avrdude/ [/usr/local/etc/avrdude.conf:555]
  pavr     = Jason Kyle's pAVR Serial Programmer [/usr/local/etc/avrdude.conf:547]
  dragon_dw = Atmel AVR Dragon in debugWire mode [/usr/local/etc/avrdude.conf:540]
  dragon_hvsp = Atmel AVR Dragon in HVSP mode  [/usr/local/etc/avrdude.conf:532]
  dragon_pp = Atmel AVR Dragon in PP mode    [/usr/local/etc/avrdude.conf:524]
  dragon_isp = Atmel AVR Dragon in ISP mode   [/usr/local/etc/avrdude.conf:516]
  dragon_jtag = Atmel AVR Dragon in JTAG mode  [/usr/local/etc/avrdude.conf:508]
  jtag2dw  = Atmel JTAG ICE mkII in debugWire mode [/usr/local/etc/avrdude.conf:500]
  jtag2isp = Atmel JTAG ICE mkII in ISP mode [/usr/local/etc/avrdude.conf:492]
  jtag2    = Atmel JTAG ICE mkII            [/usr/local/etc/avrdude.conf:484]
  jtag2fast = Atmel JTAG ICE mkII            [/usr/local/etc/avrdude.conf:476]
  jtag2slow = Atmel JTAG ICE mkII            [/usr/local/etc/avrdude.conf:468]
  jtagmkII = Atmel JTAG ICE mkII            [/usr/local/etc/avrdude.conf:460]
  jtag1slow = Atmel JTAG ICE (mkI)           [/usr/local/etc/avrdude.conf:453]
  jtag1    = Atmel JTAG ICE (mkI)           [/usr/local/etc/avrdude.conf:445]
  jtagmkI  = Atmel JTAG ICE (mkI)           [/usr/local/etc/avrdude.conf:437]
  avr911   = Atmel AppNote AVR911 AVROSP    [/usr/local/etc/avrdude.conf:431]
  avr109   = Atmel AppNote AVR109 Boot Loader [/usr/local/etc/avrdude.conf:425]
  butterfly = Atmel Butterfly Development Board [/usr/local/etc/avrdude.conf:419]
  usbtiny  = USBtiny simple USB programmer, http://www.ladyada.net/make/usbtinyisp/ [/usr/local/etc/avrdude.conf:413]
  usbasp   = USBasp, http://www.fischl.de/usbasp/ [/usr/local/etc/avrdude.conf:407]
  avr910   = Atmel Low Cost Serial Programmer [/usr/local/etc/avrdude.conf:401]
  stk600hvsp = Atmel STK600 in high-voltage serial programming mode [/usr/local/etc/avrdude.conf:395]
  stk600pp = Atmel STK600 in parallel programming mode [/usr/local/etc/avrdude.conf:389]
  stk600   = Atmel STK600                   [/usr/local/etc/avrdude.conf:383]
  stk500hvsp = Atmel STK500 V2 in high-voltage serial programming mode [/usr/local/etc/avrdude.conf:377]
  stk500pp = Atmel STK500 V2 in parallel programming mode [/usr/local/etc/avrdude.conf:371]
  stk500v2 = Atmel STK500 Version 2.x firmware [/usr/local/etc/avrdude.conf:365]
  mib510   = Crossbow MIB510 programming board [/usr/local/etc/avrdude.conf:359]
  stk500v1 = Atmel STK500 Version 1.x firmware [/usr/local/etc/avrdude.conf:353]
  stk500   = Atmel STK500                   [/usr/local/etc/avrdude.conf:347]
  avrisp2  = Atmel AVR ISP mkII             [/usr/local/etc/avrdude.conf:337]
  avrispmkII = Atmel AVR ISP mkII             [/usr/local/etc/avrdude.conf:331]
  avrispv2 = Atmel AVR ISP V2               [/usr/local/etc/avrdude.conf:325]
  avrisp   = Atmel AVR ISP                  [/usr/local/etc/avrdude.conf:319]
  arduino  = Arduino                        [/usr/local/etc/avrdude.conf:313]



Posted by 구차니
embeded/AVR (ATmega,ATtiny)2009. 4. 15. 00:17

avrdude를 막상 사용해보려니 막막해서.. 일단 이런녀석을 찾아 보게 되었다.
이거 말고도 존재하지만, 막상 실행하보니 윈도우용.. gnome용이나 Xwindow용으로 할 방법이 딱히 보이지 않아서
(게다가 g++도 설치가 되어 있지 않으니 ㄱ-) 포기를 할까 하다가 구글에서 조금 더 찾아 보니
gnome-avrdude라는 것을 발견하게 되었다.  아무튼 이녀석으로 나중에 AVR 읽어 보는 테스트를 해봐야겠다.

[발견 : korean.osstrans.net/software/gnome-avrdude.html]
[gnome-avrdude : http://sourceforge.net/projects/gnome-avrdude]

'embeded > AVR (ATmega,ATtiny)' 카테고리의 다른 글

ubuntu에서 gnome-avrdude 사용하기  (0) 2009.05.27
STK-200 / STK-500 호환 AVR ISP  (2) 2009.04.20
linux에서 AVR 컴파일하기  (0) 2009.04.07
어셈블리 언어 ORG 명령  (4) 2009.03.19
AVR Studio / AVR-GCC 뜯어 보기  (0) 2008.11.18
Posted by 구차니
embeded/80512009. 4. 14. 10:57
대용량의 데이터(예를들어 폰트데이터)를 저장하는데 있어 기본변수로 선언을 했더니 문제가 발생했다.
Memory Model은 기본 값인 Small model이었고, 이로 인해서 data형으로 선언이 된다.(위의 small model 참조)

그래서 Large model로 변경하니 xdata로 되었고, 이로 인해 64k까지 가능해져서 에러없이 돌아 갔지만,
다른 문제가 발생을 해서 오작동을 한것으로 생각이 된다.

아무튼 플래시는 넉넉하니, code라는 변수 타입을 선언하면 rom에 저장이 되고,
메모리에 저장이 되지 않으므로 별다른 문제 없이 프로그램이 실행된다.


Memory TypeDescription
code Program memory (64 KBytes); accessed by opcode MOVC @A+DPTR.
data Directly addressable internal data memory; fastest access to variables (128 bytes).
idata Indirectly addressable internal data memory; accessed across the full internal address space (256 bytes).
bdata Bit-addressable internal data memory; supports mixed bit and byte access (16 bytes).
xdata External data memory (64 KBytes); accessed by opcode MOVX @DPTR.
far Extended RAM and ROM memory spaces (up to 16MB); accessed by user defined routines or specific chip extensions (Philips 80C51MX, Dallas 390).
pdata Paged (256 bytes) external data memory; accessed by opcode MOVX @Rn.

If no memory type is specified for a variable, the compiler implicitly locates the variable in the default memory space determined by the memory model: SMALL, COMPACT, or LARGE. Function arguments and automatic variables that cannot be located in registers are also stored in the default memory area. Refer to Memory Models for more information.

[출처 : http://www.keil.com/support/man/docs/c51/c51_le_memtypes.htm]


xdata

The xdata memory type may be used to declare variables only. You may not declare xdata functions. This memory is indirectly accessed using 16-bit addresses and is the external data RAM of the 8051. The amount of xdata is limited in size (to 64K or less).

Variables declared xdata are located in the XDATA memory class.
Declare xdata variables as follows:
unsigned char xdata variable;
[출처 : http://www.keil.com/support/man/docs/c51/c51_le_xdata.htm]

code

The code memory type may be used for constants and functions. This memory is accessed using 16-bit addresses and may be on-chip or external.

    * For constants (ROM variables), code memory is limited to 64K.
      Objects are limited to 64K and may not cross a 64K boundary.
      Constant variables declared code are located in the CODE memory class.
    * For program code (functions), code memory is limited to 64K.
      Program functions are stored in the CODE memory class by default.
      The code memory type specifier is not required.

Declare code objects as follows:
unsigned char code code_constant;
unsigned int func (void)
{
    return (0);
}
[출처 : http://www.keil.com/support/man/docs/c51/c51_le_code.htm]

Small Model

In this model, all variables, by default, reside in the internal data memory of the 8051 system as if they were declared explicitly using the data memory type specifier.

In this memory model, variable access is very efficient. However, all objects (that are not explicitly located in another memory area) and the stack must fit into the internal RAM. Stack size is critical because the stack space used depends on the nesting depth of the various functions.

Typically, if the linker is configured to overlay variables in the internal data memory, the small memory model is the best model to use.

[출처 : http://www.keil.com/support/man/docs/c51/c51_le_modelsmall.htm]

Large Model

In the large model, all variables, by default, reside in external data memory (which may be up to 64K Bytes). This is the same as if they were explicitly declared using the xdata memory type specifier.

The data pointer (DPTR) is used to address external memory. It is important to note that memory access through the data pointer is inefficient and slow, especially on variables that are two or more bytes long. This type of data access mechanism generates more code than the small model or compact model.

[출처 : http://www.keil.com/support/man/docs/c51/c51_le_modellarge.htm]

Posted by 구차니