opa! mas *nenhuma* cpu consegue fazer uma instrucao por clock se a instrucao nao for puramente de registro para registro! o barramento eh um gargalo e qualquer operacao em memoria (ou io) tera uma penalidade.
alem disso, o seu codigo nao esta bom! nos comentarios abaixo, eu chuto quanto cada instrucao consome:
- Código: Selecionar todos
0x000008a8 <main+16>: moveq #0,d0 // 1 clock
0x000008aa <main+18>: move.b -4(a6),d0 // 2 clocks
0x000008ae <main+22>: addq.l #1,d0 // 1 clock
0x000008b0 <main+24>: move.b d0,-4(a6) // 2
//PORTUA = 0x02;
PORTAN = counter;
0x000008b4 <main+28>: move.b -4(a6),d0 // 2 clocks
0x000008b8 <main+32>: move.b d0,0x4010000A (0x4010000a) // 1
0x000008be <main+38>: bra.s main+0x10 (0x8a8) ; 0x000008a8 // 1
o codigo inteiro consome entao, uns 10 clocks. para um ciclo completo de GPIO, seriam 20 clocks. rodando com 80MHz, vc vai ter exatamente 4MHz!

agora, no codigo mais otimizado que eu mostrei, temos:
- Código: Selecionar todos
.L2:
move.b %d1,(%a0) // 2 clocks
move.b %d0,(%a0) // 2 clocks
move.b %d1,(%a0) // 2 clocks
move.b %d0,(%a0) // 2 clocks
move.b %d1,(%a0) // 2 clocks
move.b %d0,(%a0) // 2 clocks
move.b %d1,(%a0) // 2 clocks
move.b %d0,(%a0) // 2 clocks
jbra .L2 // 1 clock
assim, temos 17 clocks no total. rodando com 80MHz, vamos ter 4.7 milhoes de loops. mas lembrando que em cada loop temos 4 ciclos completos, o que vc efetivamente vai medir no pino de GPIO eh 18.8MHz, ou seja, o codigo pode ficar pelo menos 4 vezes melhor.
e definitivamente isso nao pode ser considerado um bom benchmark! suponha que vc fosse usar essa cpu para graficos. uma das operacoes que mais consomem recursos de software eh justamente o preenchimento de areas e existem truques para otimizar isso. por exemplo, para um display 640x480 podemos pensar em algo para otimizar o preenchimento de retangulos:
- Código: Selecionar todos
for(y=y0;y!=y1;y++)
{
*vram = lines[y];
switch(x1-x0)
{
case 640: *vram++ = pixel;
case 639: *vram++ = pixel;
case 638: *vram++ = pixel;
case 637: *vram++ = pixel;
...
case 2: *vram++ = pixel;
case 1: *vram = pixel;
}
}
efetivamente, o que o codigo faz eh procurar em cada linha quantas atribuicoes faltam para completar a largura do retangulo (eh facil adaptar isso tb para triangulos, o que permite extender para qq poligono!). vamos supor que cada pixel eh um byte, entao, na pratica, o codigo em asm disso vai virar uma sequencia do tipo:
- Código: Selecionar todos
case_640: move.b %d0,(%a0)+
case_639: move.b %d0,(%a0)+
case_638: move.b %d0,(%a0)+
case_637: move.b %d0,(%a0)+
...
case_2: move.b %d0,(%a0)+
case_1: move.b %d0,(%a0)
o que significa que o codigo que faz o for das linhas, calcula o endereco base da vram e controla o switch impacta muito pouco. se cada linha destas consome 2 clocks, temos entao ateh 1280 clocks para transferir 640 bytes. desta forma, o codigo que controla o loop poderia ter ateh 128 clocks e estaria impactando em menos de 10% na performance total.
em outras palavras, a 80MHz, vc estaria conseguindo trabalhar com uma performance de 40 Mpixel/s se fosse utilizada uma memoria capaz de operar com 2 clocks. na pratica, tem o impacto do loop de controle, que deve reduzir esse total em uns 10%. mas por outro lado, nao usamos a largura total do barramento. se a memoria de video for de 32 bits, podemos refazer o loop para otimizar transferencias de 4 em 4 bytes.
isso requer um tratamento das bordas de inicio e fim, transferindo bytes e words para alinhar e entao fazendo o grosso da transferencia com longs. por exemplo, um poligono nas coordenadas 3,3 e 129,129 requer um byte no inicio para alinhar com multiplo de 4. daih ele consegue preencher otimizado ateh o pixel 128 e entao temos mais um byte para fechar o valor 129. neste caso, a transferencia otimizada seria 4x mais veloz, chegando entao a 160Mpixel/s.
mas otimizar o codigo nem sempre eh facil!
eu acho mais facil acreditar que o software sempre eh uma penalidade. se vc precisa de performance, vc precisa de hardware, motivo pelo qual DMA eh sempre essencial.
mastk escreveu:Entendi Sam, mas nao deixei de ficar descepcionado.
Veja, estou com uma M52259EVB e apesar do kit ser bom, o FlexBus não esta externado em nenhum conector.
As unicas opções que me restaram foram, QSPI, que é lenta 20Mhz, se nao me falha a memoria ou GPIO. As GPIOs são rapidas, mas a CPU não faz uma instrução por clock.