memcpy leo que es lo más rápido, pero no estoy seguro si permite copiar una matriz tridimensional completa sobre otra idéntica. Mi duda radica en que no se como está organizada internamente en memoria una matriz tridimensional, para poder usar un puntero de origen a destino con posiciones contiguas de memoria. He visto algún ejemplo en el que solo copian una de las dimensiones completas de una matriz bidimensional o tridimensional, pero no la matriz al completo, o que todos los elementos deben de estar ubicados en posiciones de memoria contiguas tanto en origen como en destino.
No deberías preocuparte por la estructura interna de los datos a copiar, podrías copiar un struct que tenga cualquier clase de campos y estaría bien. Mientras se pase puntero de origen, destino, y tamaño basta. Pero eso ya lo pusiste más abajo.
Mi problema, es que tengo una matriz que se llena a partir de datos que entran por SPI/DMA. Por eso cuando esa matriz está llena, como la tengo que enviar por UDP (previo proceso y troceado de esos datos), necesito copiarla rápido a otra matriz de trabajo, porque si trabajo sobre la matriz original, mientras la estoy leyendo, ya se está actualizando por otro lado y me altera los datos.
Mi idea es copiar la matriz original y trabajar sobre la copia, mientras el resto de proceso puede seguir actualizando la matriz original.
Mmmmm, si se quiere enviar una estructura de datos por puerto serie entonces ahí sí interesa el orden de los datos, porque hay que reconstruirlo del otro lado... pero si usas UDP supongo que no interesa perder paquetes de datos?
Eso de configurar el DMA para que de manera alternada y automática vuelque en dos buffers, no se como hacerlo. Puedo simularlo por software, usando un campo a modo de switch, para que con un IF vuelque los datos del buffer a una u otra matriz, para ir alternando la matriz de trabajo.
De todas formas el buffer del DMA no es con el que trabajo directamente, ese buffer se copia con un memcpy a la matriz multidimensional, usando tres índices, y es cuando la matriz está totalmente llena, cuando se pasa a una función para procesarla.
Y la cosa aún se complica más, porque la matriz se llena como si fuera un registro de desplazamiento, así tampoco se podrían alternar. No puedo meter 3 planos de datos a una matriz, y luego pasarme a la otra, los datos que van entrando por el DMA van empujando a los planos de la matriz, de manera que siempre estén los 3 últimos que han entrado. Si las alternara, habría un vacío de 3 planos que dejarían de desplazar los datos en cada matriz.
¿Pensaste en usar un esquema de doble buffer?
Si hay suficiente memoria RAM podrías hacer
uint8_t buffer1[TAMANO];
uint8_t buffer2[TAMANO];
uint8_t *bufferEntrada = buffer1;
uint8_t *bufferSalida = buffer2;
Entonces la principio se llena bufferEntrada = buffer1; cuando está lleno se intercambian:
swap(bufferEntrada, bufferSalida);
SPI_Recibir(bufferEntrada, TAMANO);
UDP_Enviar(bufferSalida, TAMANO);
Luego cuando se llena nuevamente el buffer de entrada se realiza la misma operación, la limitación es que la salida de datos (por UDP) tiene que ser más rápida que la entrada de datos (por SPI).
Esto tiene la ventaja de que no hay que perder tiempo copiando bloques de memoria, y la desventaja de que ocupa el doble de RAM.
Yo creo que con un memcpy se puede hacer un memcpy(&array2,&array1,sizeof(array2));, que duplique el array, creo que es algo bastante rápido.
Si los arrays estan definidos con corchetes:
uint8_t array1[indiceMax1][IndiceMax2][IndiceMax3];
Entonces no va el operador & porque ya array1 y array2 serían punteros:
memcpy(array2,array1,sizeof(array2));