eu particularmente nunca consegui tempo livre para aprender como o codewarrior funciona... acho infinitamente mais pratico digitar make no prompt e ver o codigo compilar. mas um amigo meu passou uma dica muito boa: ele usa o processor expert para gerar codigo para determinados perifericos do coldfire e entao simplesmente compila estes codigos com o gcc.
a primeira coisa eh arrumar um gcc...
a maioria das plataformas possui packages pre-montados com gcc para m68k, por exemplo, no meu mac eh simplesmente digitar:
sudo port install m68k-elf-gcc
e o compilador esta lah... infelizmente eh um gcc 3.4.6 para 68k e cfv2 apenas. mas como eu ainda nao uso nada diferente disso, ateh o momento nao precisei correr atras de nada mais atualizado.
para ter uma versao mais atualizada, eu precisaria baixar o fonte do gcc lah do site oficial e mandar bala em uma versao cross. nao eh dificil e jah fiz isso varias vezes no passado. mas compilar aqui numa maquina unix eh uma coisa, compilar no windows eh outra... jah comeca que o windows nem compilador tem! hehehe :)
no fundo tem que instalar uma porrada de tools de unix para compilar o gcc e daih massacra demais quem usa windows. nesse caso o negocio eh apelar para a boa vontade alheia:
http://www.codesourcery.com/sgpp/lite/c ... elease1049
versao bem recente, inclusive com suporte a coldfire v1 e toda a documentacao disponivel.
sobre a forma de usar, nao tem muito segredo compilar no gcc e vc pode comecar praticando na sua maquina x86 mesmo (arrumar um unix qq para praticar eh uma boa ideia!).
basicamente, vc vai compilar os codigos gerando um arquivo objeto:
gcc -Wall -c codigo_1.c
gcc -Wall -c codigo_2.c
...
e depois linkar tudo com o ld:
ld -o codigo *.o /usr/lib/crt1.o -lc
de onde crt1.o eh um codigo que faz o startup do ambiente e chama main(), que esta em algum dos arquivos .c que vc compilou, e -lc eh para linkar com a libc, que normalmente inclui uma parafernalha de opcoes como memcpy, bzero, printf, etc. isso ae para x86...e a localizacao de crt1.o infelizmente pode variar de sistema para sistema... se nao for no mesmo lugar, tem q procurar com locate... se nao tiver locate, tem q procurar com find! :)
assumindo que tudo correu bem, o mesmo codigo no caso do 68k:
m68k-elf-gcc -Wall -c codigo_1.c
m68k-elf-gcc -Wall -c codigo_2.c
...
m68k-elf-ld -o codigo *.o /opt/local/m68k-elf/lib/libc.a
diferentemente do x86, nao tem um crt1.o (a menos que vc escreva um!) e entao ele assume um default qq:
m68k-elf-ld: warning: cannot find entry symbol _start; defaulting to 80000074
olhando com um 'm68k-elf-objdump -d codigo' temos:
- Código: Selecionar todos
codigo: file format elf32-m68k
Disassembly of section .text:
80000074 <f>:
80000074: 4e56 0000 linkw %fp,#0
80000078: 202e 0008 movel %fp@(8),%d0
8000007c: d080 addl %d0,%d0
8000007e: 4e5e unlk %fp
80000080: 4e75 rts
80000082: 4e75 rts
80000084 <main>:
80000084: 4e56 0000 linkw %fp,#0
80000088: 2f2e 0008 movel %fp@(8),%sp@-
8000008c: 61ff ffff ffe6 bsrl 80000074 <f>
80000092: 588f addql #4,%sp
80000094: 4e5e unlk %fp
80000096: 4e75 rts
parece bacana, mas provavelmente meu 'int main(int argc, char **p)' vai falhar porcamente, pq nao tem um pre-startup antes de main nesse caso (no x86 tem um sistema operacional e tal, aqui nao).
uma jogada boa eh posicionar uma stack e uma tabela de vetores:
- Código: Selecionar todos
unsigned stack[256];
void main(void);
const unsigned vtable[256]={
(unsigned)&stack[255],
(unsigned)main
};
compilo isso ae e tenho um vtable.o para usar... entao eh possivel posicionar as coisas usando um link.ld:
- Código: Selecionar todos
SECTIONS
{
. = 0x00000000;
. = ALIGN(4);
.text :
{
vtable.o(.rodata)
*(.text)
}
.rodata :
{
*(.rodata)
}
. = 0x80000000;
. = ALIGN(4);
.data :
{
*(.data)
}
.bss :
{
*(.bss)
}
}
chutando ae 0x80000000 para sram e 0x00000000 para flash.
linkando tudo com:
m68k-elf-ld -o codigo *.o /opt/local/m68k-elf/lib/libc.a -Tlink.ld
e rodando novamente o objdump, parece mais legal:
- Código: Selecionar todos
codigo: file format elf32-m68k
Disassembly of section .text:
00000000 <vtable>:
0: 80 00 03 fc 00 00 04 10 00 00 00 00 00 00 00 00 ................
...
00000400 <f>:
400: 4e56 0000 linkw %fp,#0
404: 202e 0008 movel %fp@(8),%d0
408: d080 addl %d0,%d0
40a: 4e5e unlk %fp
40c: 4e75 rts
...
00000410 <main>:
410: 4e56 0000 linkw %fp,#0
414: 4878 0002 pea 2 <vtable+0x2>
418: 61ff ffff ffe6 bsrl 400 <f>
41e: 588f addql #4,%sp
420: 4e5e unlk %fp
422: 4e75 rts
tem uma tabela de vetores lah no endereco onde deveria estar, contendo o endereco da stack em 0x80003fc e o endereco de main em 0x00000410. o codigo eh basicao, roda ateh o fim e dah crash! :)
como eh um elf, eh possivel carregar ele em simuladores de 68k/cf como o da lauterbach, conseguindo debugar passo a passo com codigo de maquina e C lado a lado. para gerar o binario ou S19, soh ajustar a saida o ld:
m68k-elf-ld -o codigo *.o /opt/local/m68k-elf/lib/libc.a -Tlink.ld --oformat binary
ou:
m68k-elf-ld -o codigo *.o /opt/local/m68k-elf/lib/libc.a -Tlink.ld --oformat srec
sobre set de instrucoes, como nao tenho a versao que gera para coldfire v1 nao consigo verificar nenhuma situacao particular. mas basicamente, isso se define durante a compilacao com o gcc (nos exemplos compilei com o default, q deve ser para 68020).
tambem eh uma boa ideia fazer um Makefile:
- Código: Selecionar todos
CC = m68k-elf-gcc
LD = m68k-elf-ld
CFLAGS = -Wall -m5200
LDFLAGS = -Tlink.ld
SRCS = vtable.c a.c b.c
OBJS = $(SRCS:.c=.o)
%.o: %.c
$(CC) $(CFLAGS) -c $<
codigo: $(OBJS) $(SRCS)
$(LD) $(LDFLAGS) -o $@ $(OBJS) $(LDFLAGS)
all: codigo $(SRCS)
clean:
rm -f $(OBJS) codigo
daih quando vc edita qq arquivo .c eh soh rodar make, ele recompila o que precisa e relinka certinho. quer limpar tudo, basta um make clean.
os arquivos que usei no exemplo sao o a.c e b.c:
- Código: Selecionar todos
int f(int a)
{
return 2*a;
}
- Código: Selecionar todos
extern int f(int);
int main(void)
{
return f(2);
}
e como eu nem uso a libc, acabei optando por tirar ela da compilacao. e obvio, a falta do crt1.o tem uma consequencia extra: o segmento data nao eh inicializado... dae o pulo do gato eh criar um codigo de pre-startup q faz um memcpy da area correta da flash para a sram... mas fica para a proxima licao hehehe
KrafT escreveu:Um dos maiores empecilhos para os meros mortais, é a limitação de código do Code Warrior. Pagar por ele está fora da realidade de muita gente.
Ajudaria muito se a Freescale fisesse como a NXP e a ST: Montar um pacote com o GCC já configurado para um mcu qualquer. Assim os mortais aprenderiam e poderiam continuar no GCC.
Gravar via USB ajuda na produção e atualização de firmware com certeza, mas um debug como o dos Zilog Z8 seria bem legal.