Estoy usando SPI para escribir y leer los datos de la placa esclava. Tengo dos preguntas con respecto a este proceso:
Pregunta 1. ¿Por qué cuando trato de leer 1.000.000 bytes a través de SPI utilizando 1 mensaje, funciona más lento que si los divido en K mensajes?
Intenté reproducir la diferencia entre un mensaje grande por transacción y varios mensajes más pequeños (lo que en total nos brinda buffers del mismo tamaño) y observé que cuanto menor es el tamaño del mensaje, más rápida es la velocidad de transacción SPI.
Pregunta 2. ¿Hay alguna forma de aumentar la velocidad de las transacciones SPI?
Según mis pruebas, la transacción SPI pura para 1.000.000 bytes dividida en 500 paquetes está tomando 380 ms de tiempo de trabajo.
Lo que significa que tengo 8.000.000 bits por 0,38 segundos = > 20.55 Mbits / seg, que es menos de 48 Mbits / seg que se supone que debe ser.
Además, aquí hay algunas piezas de código que solía comparar y probar:
device = "/dev/spidev1.0";
mode = SPI_MODE_0;
bits = 8;
speed = 48000000;
fd = open(device, O_RDWR);
memset(read_buffer, 0, sizeof(read_buffer));
mass_xfer[0].tx_buf = (unsigned long)tx1;
mass_xfer[0].len = 2;
mass_xfer[0].speed_hz = speed;
// sz - amount of bytes within one SPI message
// n - amount of messages in one SPI transaction
unsigned long sz = 2000, i, n = (nbytes + sz - 1) / sz;
for (i = 0; i < n; i++) {
mass_xfer[i + 1].rx_buf = (unsigned long)read_buffer + i * sz;
mass_xfer[i + 1].len = min(sz, nbytes - i * sz);
mass_xfer[i + 1].speed_hz = speed;
}
timestamp_t t0 = get_timestamp();
ret = ioctl(fd, SPI_IOC_MESSAGE(n + 1), mass_xfer);
// ret = ioctl(fd, SPI_IOC_MESSAGE(1), &read_xfer); // When I tried to read using one message, time was more than 600ms
timestamp_t t1 = get_timestamp();
printf(" SPI READ: %.2f (%d) %d\n", (t1 - t0)/1000.0L, n + 1, SPI_MSGSIZE(n + 1)); // After this output, for 1.000.000 bytes I am receiving 380.xx ms
if (ret < 1)
pabort("can't send spi message");
¿Alguna idea?
ACTUALIZACIÓN 1:
SO: Linux 3.15.10-bone8 # 1 Vie 26 de septiembre 14:20:19 PDT 2014 armv7l GNU / Linux
CPU: Sitara AM3358 1GHz. Según esta CPU, la velocidad máxima del reloj SPI es de 48MHz.
El código está escrito en C ++ y usando la biblioteca spidev.h.
Básicamente, el tablero es BeagleBone Black .
ACTUALIZACIÓN 2: He hecho muchas pruebas y he descubierto qué está pasando y qué causa el problema.
La razón es las brechas entre las lecturas de bytes. Para ser más específicos, repasemos las líneas de código: read_xfer.rx_buf = read_buffer; read_xfer.len =; read_xfer.speed_hz = 48000000; ioctl (fd, SPI_IOC_MESSAGE (1), & read_xfer);
Si colocamos 100 (que se leen 100 bytes) en lugar de veremos la siguiente imagen en el osciloscopio: Como puede observar, lee 8 bits, luego se detiene, luego lee otros 8 bits. Así que el problema son esas brechas entre la lectura de los bytes. Aquí hay algunos resultados de prueba usando el osciloscopio:
- bytes_amount = gap_width
- 10 bytes = 480ns
- 50 bytes = 410ns
- 100 bytes = 200ns
- 50 000 bytes = 200ns
- 70 000 bytes = 350ns
Según los resultados, no puedo leer mensajes de más de 100 000 bytes en un paquete, ya que las brechas crearán una gran sobrecarga.
OTRA PREGUNTA ¿Qué causa esas brechas y cómo reducirlas?