La función de espera de espera ocupada tiene una sincronización incorrecta en la CPU NIOS

4

Tengo un sistema Qsys que incluye una CPU NIOS II / e (que es el único maestro en el bus) y una porción de 36kB de RAM interna de 32 bits. La RAM está configurada para tener la latencia de lectura mínima (que es de 1 ciclo). Todo el sistema está cronometrado por un solo reloj de 50MHz.

Intento usar la función usleep para esperar 1 segundo y usar clock para medir el tiempo:

#include <sys/alt_stdio.h>
#include <unistd.h>
#include <time.h>

void main(void) {
    clock_t start, end;
    start = clock();
    usleep(1000000);
    end = clock();
    alt_printf("usleep(1s) takes 0x%xms\n", (end - start) * 1000 / CLOCKS_PER_SEC);
}

Sorprendentemente, obtengo un valor 0x592 (1426 DEC), que ni siquiera está cerca de 1 segundo. Al alternar un pin antes y después de usleep y medir el tiempo, se confirma externamente que la demora es cercana a los 1.4s.

Entiendo que la espera ocupada se ve afectada por la latencia de RAM y el arbitraje de bus, que traté de excluir cuidadosamente. ¿Cuál es la configuración del sistema esperada en la que usleep funciona correctamente? ¿Existe una función de retardo alternativa con resolución μs que funcione en la configuración que tengo?

Para responder a la solicitud de aclaración, todas las duraciones son incorrectas en aproximadamente el mismo factor (1.4), que supongo que depende de la configuración del hardware. Simplemente multiplicar por el factor correctivo no es una solución para mí, ya que es para un proyecto que debería permitir a los usuarios ejecutar el código Arduino en cualquier FPGA capaz de implementar NIOS.

La implementación usleep que estoy usando proviene de Altera "Small C library", AFAIK es un clon de newlib. Las opciones del compilador del proyecto de muestra "Hello World Small" reproducen el problema. Probé varias combinaciones de opciones, y ninguna de ellas solucionó el problema. Nuevamente, dado que esto es para una biblioteca, me gustaría encontrar una solución que funcione con diferentes opciones de compilación (razonables).

    
pregunta Dmitry Grigoryev

2 respuestas

1

Si este es el código completo y no un pseudo código recortado para esta publicación, está claro que tiene un problema con la implementación de newlib.

La solución rápida es hacer su propia macro usando clock ()

end = clock() + delay;
while((end - clock()) > 0);
    
respondido por el pacman
2

Tuve el mismo problema y obtuve el mismo resultado. Durante 1 segundo tuve una pausa real de 2 s. La razón es que se realiza por ciclo de software, supongo. Al menos, aquí está el comentario de Intel FPGA (anterior. Altera) enlace

Puedes resolver tu necesidad de un buen conteo de tiempo usando tics que cuenten algo así:

#include <sys/alt_alarm.h>
...
//somewhere in your program
void function_t(){
int prev= 0;
int now;
now = (int) (alt_nticks() * alt_ticks_per_second() / 1000);
if ((now - prev) < period)
return;
last = now;
//my action
}

así que usé esa función en mi código de round-robin para hacer algo con el uso del temporizador. Pero si realmente desea usar el temporizador de manera precisa, debe usar interrupciones.

    
respondido por el Daniil Smirnov

Lea otras preguntas en las etiquetas