Autor Tema: Desreferenciando caracteres en una struct...  (Leído 6447 veces)

0 Usuarios y 3 Visitantes están viendo este tema.

Desconectado elgarbe

  • Moderador Local
  • PIC24H
  • *****
  • Mensajes: 2178
Re:Desreferenciando caracteres en una struct...
« Respuesta #15 en: 09 de Febrero de 2016, 11:24:33 »
y mi pregunta es, es necesario que sean volátiles las estructuras del RB?

Ahora yo tengo esto:

Código: C
  1. typedef struct {
  2.         void *data;
  3.         int count;
  4.         int itemSz;
  5.         uint32_t head;
  6.         uint32_t tail;
  7. } RINGBUFF_T;
  8.  
  9. /* Transmit and receive ring buffers */
  10. static RINGBUFF_T txring, rxring;
  11.  
  12. // Buffers para los datos del RB
  13. static uint8_t rxbuff[UART_RB_SIZE];
  14. // No estoy usando la transmision de datos. Configuro igual el RB de transmision.
  15. static uint8_t txbuff[UART_RB_SIZE];
  16.  
  17. int RingBuffer_Init(RINGBUFF_T *RingBuff, void *buffer, int itemSize, int count)
  18. {
  19.         RingBuff->data = buffer;
  20.         RingBuff->count = count;
  21.         RingBuff->itemSz = itemSize;
  22.         RingBuff->head = RingBuff->tail = 0;
  23.  
  24.         return 1;
  25. }
  26.  
  27.         RingBuffer_Init(&rxring, rxbuff, 1, UART_RB_SIZE);
  28.         RingBuffer_Init(&txring, txbuff, 1, UART_RB_SIZE);
  29.  
  30.  
  31. void USART1_4_IRQHandler(void)
  32. {
  33.         uint8_t key;
  34.         uint16_t lastpos;
  35.         Chip_UARTN_IRQRBHandler(LPC_USART1, &rxring, &txring);
  36.  
  37.         lastpos = ((rxring.head)-1) & (rxring.count - 1);
  38.         key = ((uint8_t *)rxring.data)[lastpos];
  39.         if(key == 27)
  40.         {
  41.                 isRBHalfFull = 2;
  42.         }else
  43.         {
  44.                 if(RingBuffer_GetCount(&rxring) == SD_WR_BUFF_SIZE){
  45.                         isRBHalfFull = 1;
  46.                 }else
  47.                 {
  48.                         isRBHalfFull = 0;
  49.                 }
  50.         }
  51. }

Puse todo el código junto para que se entienda, aunque en los sources no estan juntos.

Mi duda es que cosa puede hacer el compilador (con la optimizacion habilitada) que tenga un mal funcionamiento?
Por que estoy pasando siempre a las funciones del RB la direccion del RingBuffer, dicha direccion no cambia nunca, entonces no veo que el compilador pueda hacer macana. No sé como funciona el almacenaje de los miembros de la estructura... Quizá si el compilador almacena en un registro el miembro "count" que no es volatile y en algúna parte peligrosa del codigo yo cambiara ese miembro puede ser que haya problemas. Pero el unico miembro que cambia es "data" que al ser un puntero no volatile, no sé que pueda pasar....

Distinto es si declaro un puntero a una variable y, por ejemplo, dentro de una interrupcion hago que ese puntero apunte a otra cosa...
No tengo bien claro este tema, pero así lo entiendo yo...
-
Leonardo Garberoglio

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:Desreferenciando caracteres en una struct...
« Respuesta #16 en: 09 de Febrero de 2016, 13:34:49 »
Es simple elgarbe, activa las optimizaciones y si funciona esta todo bien :P

Citar
Mi duda es que cosa puede hacer el compilador (con la optimizacion habilitada) que tenga un mal funcionamiento?
Por que estoy pasando siempre a las funciones del RB la direccion del RingBuffer, dicha direccion no cambia nunca, entonces no veo que el compilador pueda hacer macana. No sé como funciona el almacenaje de los miembros de la estructura... Quizá si el compilador almacena en un registro el miembro "count" que no es volatile y en algúna parte peligrosa del codigo yo cambiara ese miembro puede ser que haya problemas. Pero el unico miembro que cambia es "data" que al ser un puntero no volatile, no sé que pueda pasar....

Lo que cambia es: head y tail. Nada mas,  *data se mantiene constante pero el cotenido no.
El compilador creo que debe tomar "funcion a funcion" y ver si por ejemplo no se modifica head o no se modifica tail, entonces pensara que no tiene sentido leer una y otra ves esos valores (ya que jamas son modificados). Entonces tal ves inserte codigo para calcularlo una sola ves o insertar un valor constante. Y ahi es donde entra el problema.

Supongamos una funcion en tu main preguntando por isRBHalfFull dentro de un while, y que nada modifique ese valor por fuera del mismo.
Si no es declarado volatile va a suponer que jamas cambia y nunca va a entrar.

Como decia, si queres probar si funciona con optimizaciones, activalo, grabalo y fijate si funciona. Si no funciona es por que el volatile es necesario en alguna parte :P

Código: C
  1. Distinto es si declaro un puntero a una variable y, por ejemplo, dentro de una interrupcion hago que ese puntero apunte a otra cosa...
  2. No tengo bien claro este tema, pero así lo entiendo yo..

Si es un puntero declarado a una variable comun, es lo mismo que antes. Posiblemente considere : Puntero constante, valor apuntado constante
Si es un puntero declarado a una variable volatile, entonces va a acceder siempre a la variable, considerando : Puntero constante, valor apuntado volatile.
Si es un puntero volatile apuntando a una variable volatile, Seria todo volatile hasta el puntero. ( volatile type * volatile ptr )

Desconectado BrunoF

  • Administrador
  • DsPIC30
  • *******
  • Mensajes: 3865
Re:Desreferenciando caracteres en una struct...
« Respuesta #17 en: 09 de Febrero de 2016, 19:31:12 »
El tema de los riesgos y si es útil o no, depende mucho de las características propias del uC en cuestión, y de cómo las explote el compilador.

Básicamente el compilador puede recurrir a dos formas de optimización (puede haber más pero se me ocurren estas dos básicas) que pueden hacer la diferencia con una variable volatile o no:
a) copia del valor de una variable a otra shadow en RAM. Es decir que en lugar de usar el registro original, el compilador genera una copia y usa la copia para realizar las operaciones temporalmente, sin refrescar el valor la variable original en cada aparición;
b) copia del valor de una variable a un registro de trabajo interno del uC. Obviamente en microcontroladores con muchos registros de trabajo es más común ver este tipo de código/optimizaciones.

No creo que suceda nada si no la ponés como volatile por lo que mencionás. Si no cambiás el valor del puntero nunca, poco puede hacer para mandarse macana con esa variable.

Sinceramente, el volatile es una forma de garantizar cierto refresco de la variable pero de ninguna forma garantiza la sincronización o coherencia en todo momento del valor de un registro.

Imaginemos un código sencillo:

volatile uint8_t activarBomba = 0;

while(1)
{
    activarBomba = 0;
    if(activarBomba)
        Explota();
}
...

y una interrupción configurada, habilitada y frecuentemente invocada que haga:
{
    activarBomba = 1;
}

explotará eventualmente? o no?
"All of the books in the world contain no more information than is broadcast as video in a single large American city in a single year. Not all bits have equal value."  -- Carl Sagan

Sólo responderé a mensajes personales, por asuntos personales. El resto de las consultas DEBEN ser escritas en el foro público. Gracias.

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:Desreferenciando caracteres en una struct...
« Respuesta #18 en: 09 de Febrero de 2016, 19:35:30 »
Segun el ejemplo que diste, para mi de forma optimizada no, de forma no optimizada puede ser.

Desconectado BrunoF

  • Administrador
  • DsPIC30
  • *******
  • Mensajes: 3865
Re:Desreferenciando caracteres en una struct...
« Respuesta #19 en: 09 de Febrero de 2016, 19:47:23 »
Podrías desarrollar un poco más tu opinión y justificar las diferencias en ambos casos?
"All of the books in the world contain no more information than is broadcast as video in a single large American city in a single year. Not all bits have equal value."  -- Carl Sagan

Sólo responderé a mensajes personales, por asuntos personales. El resto de las consultas DEBEN ser escritas en el foro público. Gracias.

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:Desreferenciando caracteres en una struct...
« Respuesta #20 en: 09 de Febrero de 2016, 20:16:07 »
Empiezo que me olvide de ver el volatile :P de la variable jeje

Ahora que veo el volatile expreso mi opinion nuevamente y ademas me extiendo con el por que lo pienso asi.

Sin optimizacion:

Posiblemente explosion:
Con volatile estas obligando al compilador que tome nuevamente la variable desde donde se necesita ( no "cachearlo"). Y de no hacerlo estaria incumpliendo la misma.

Es decir, si uno asegura que activarBomba = 0; y deja una copia en un registro interno, ( stack no ), cuando haga el if() y nuevamente se pida el valor del mismo estariamos violando ese "volatile".

Entonces supongamos que por alguna casualidad ocurre la interrupcion. En un micro que se basa en el read-modify-write como es ARM y que seria el mas "propenso" a que ocurra y no en un PIC que lo hace todo en una instruccion (me refiero a los momentos de interrupciones).
Si la interrupcion ocurre antes del if ( de la instruccion de read de memoria es la unica opcion ) habria una explosion. Ya que no tenes ningun "seguro" de que no pueda ser cambiado el valor entre esas 2 instrucciones. Al ejecutarse el if vuelve a tomar el valor de RAM ( obligado por el volatile ). Cualquier otro momento que ocurra la interrupcion no va a poder ocurrir una explosion.

Con optimizacion:
Nuevamente el volatile hace de las suyas, haciendo que cualquier optimizacion sobre la variable se descarte y por ende funcionaria al igual que lo anterior
Asi que tambien es una posible explosion. Ya que no hay nada que asegure que el valor de esa varaible no sea cambiada.

-------------------------------------

Distinto hubiera sido sin volatile. Que es lo primero que lei equivocamente.

Sin volatile funcionaria igual que lo anterior sin optimizacion.

Pero con optimizacion el compilador como no hay ninguna modificacion a esa variable directamente quitaria el if y su codigo.
El por que tomar esa decision?
No se modifica nunca la variable, es decir la variable tiene el mismo valor sea donde sea la funcion y no se espera que cambie por otro lado, asi que podria usar una version cacheada. Procedemos a quitarla. Solucionado en tiempo de compilacion.


Igual estoy asumiendo que el volatile OBLIGA al compilador a leer la memoria, cuando veo que cada compilador puede implementar el volatile como le guste.

EDIT: Creo saber a donde queres llegar con esto, y mas si es aplicado al ejemplo de elgarbe.
« Última modificación: 09 de Febrero de 2016, 20:52:32 por KILLERJC »

Desconectado BrunoF

  • Administrador
  • DsPIC30
  • *******
  • Mensajes: 3865
Re:Desreferenciando caracteres en una struct...
« Respuesta #21 en: 09 de Febrero de 2016, 20:57:17 »
Comparto tu última opinión, que al estar el modificador volatile en la variable, el riesgo de que se ejecute alguna vez el Explota(), independientemente del nivel de optimización, es prácticamente inminente.

Habría que hacer algunas pruebas para confirmar si efectivamente el compilador con las optimizaciones habilitadas suprimiría el código y solucionaría el problema de cuajo.
"All of the books in the world contain no more information than is broadcast as video in a single large American city in a single year. Not all bits have equal value."  -- Carl Sagan

Sólo responderé a mensajes personales, por asuntos personales. El resto de las consultas DEBEN ser escritas en el foro público. Gracias.

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:Desreferenciando caracteres en una struct...
« Respuesta #22 en: 09 de Febrero de 2016, 23:09:28 »
Siguiendo el tema, te agradezco Bruno por hacerme ver lo que se me escapaba. Como puse en el EDIT, creo saber adonde querias llegar con esto.

El tema principal esta en que por mas que uno lo ponga como volatil (optimizacion/sin) y ya que en la situacion real de RingBuffer, existe una pequeña posibilidad de que exista un error.

Y que las funciones como las tiene actualmente elgarbe no cubren ( incluso puesto como volatiles)

Si las funciones de ringbuffer son usadas fuera de la interrupcion tambien. Hay que proteger las variables head y tail contra una posible corrupcion de datos de la misma. El caso paso a paso que ocurra esto seria:

Programa normal - lee del registro , por lo cual toma el valor de tail y lo pone en un registro interno (para modificarlo y guardalo)
Interrupcion: Entra aqui y se procede a guardar/sacar algunos valores los cuales modifican head y tail, guardandolos y saliendo.
Programa normal: (Reestablecido el stack)Modifica y guarda la variable tail. Sobreescribiendo lo anterior.

Finalmente tenes la variable tail corrupta. Y no hay volatile que te salve. Asi que las funciones de lectura/escritura, especialmente en el momento de modificar los indices head y tail, deben ser protegidos contra esto, y la unica forma de que esto ocurra es creando una zona critica ( libre de interrupciones ).

Aunque es una ventana "pequeña" estamos hablando de 2 instrucciones. Esto puede ocurrir y es lo importante (Con o sin optimizacion, volatil o no).
« Última modificación: 09 de Febrero de 2016, 23:44:01 por KILLERJC »

Desconectado BrunoF

  • Administrador
  • DsPIC30
  • *******
  • Mensajes: 3865
Re:Desreferenciando caracteres en una struct...
« Respuesta #23 en: 10 de Febrero de 2016, 00:29:11 »
Efectivamente, KILLER, hemos desembocado en el quid de la cuestión.

Y otra vez más, estás en lo cierto viendo que la única solución potable y sencilla parecería ser deshabilitar las interrupciones.

Ahora, si elegimos una arquitectura, como por ejemplo en este caso el ARM Cortex M0+:
a) podríamos encontrar otra solución segura sin recurrir a deshabilitar las interrupciones en el código crítico?
b) realmente hacer:

- deshabilitar interrupcion/es;
- modificar variable compartida;
- rehabilitar interrupcion/es;

alcanza para garantizar la no corrupción de la variable?

Ya empezamos a rozar la filosofía en cualquier momento... :D :D
"All of the books in the world contain no more information than is broadcast as video in a single large American city in a single year. Not all bits have equal value."  -- Carl Sagan

Sólo responderé a mensajes personales, por asuntos personales. El resto de las consultas DEBEN ser escritas en el foro público. Gracias.

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:Desreferenciando caracteres en una struct...
« Respuesta #24 en: 10 de Febrero de 2016, 01:08:23 »
Y ahora nuevamente me hiciste pensar xD.. Aunque el que deberia pensar es elgarbe, pero me gusta esto como va encaminado :P..

Yo estuve viendo la arquitectura de los ARM mas que nada para meterme con ASM. Pero ya casi no me acordaba.

Respecto a la arquitectura:
Lo primero que me acorde fue del: Load-Exclusive / Store-Exclusive , pero estaba seguro que en el ARMv7-m existia, pero en el ARMv6-m no existe.

Asi que me juego por DMB/DSB. ( Aunque no me queda muy en claro su funcionamiento y que gracias a eso tal ves estoy tirando esto al azar)

Y es lo unico que se me ocurre aparte de:
-  desactivar las interrupciones
-  modificar las prioridades
-  O usar el SVC que al poseeria una mayor prioridad.

( Estos ultimos 2 ni se me ocurriria hacerlos, solo lo planteo como una posibilidad ).

Y ninguno sabria como implmentarlos sin irme por ASM. Y tampoco se si las opciones que di son en realidad lo que estas buscando. De todas formas yo me jugaba por LDREX/STREX aunque me la complicaste con el M0+

Citar
- deshabilitar interrupcion/es;
- modificar variable compartida;
- rehabilitar interrupcion/es;

alcanza para garantizar la no corrupción de la variable?

Si, pero con una salvedad, es que estemos hablando de interrupcion y programa principal. Y no estemos hablando de diferentes task como si estuviera un OS (en el que se vean involucradas otras fuentes a la corrupcion).
Como creo que no posee un OS entonces garantizaria la corrupcion de la variable, pero si preguntaste es por que hay alguna trampa ..  :D , como una excepcion pero que descarte en lo que dije antes, al quitar otras fuentes.

Respecto al software:
Crear un mutex / semaforo para indicar que no puede acceder a los datos todavia. Pero esto me deja en un problema. Si uno activa el mutex y luego se entrar a la interrupcion ( el cual leeria el mutex ) como es posible que la interrupcion se vuelva a ejecutar luego de que salga de la misma y se reestablesca el mutex.
Tal ves tener una indicador (desde la interrupcion al ver activo el mutex) que se disparo la interrupcion y con eso en el programa principal finalizado el mutex poner un pending a la interrupcion en cuestion.

Mismo impacto que deshabilitar las interrupciones. Pero esta ves extensible a otro task/thread


PD: Me siento caminando en un campo minado..
PD2: Es mas feo cuando sos al que solamente le llegan preguntas y esperan que responda bien jeje. Pero igual lo que me importa es aprender.
« Última modificación: 10 de Febrero de 2016, 01:53:54 por KILLERJC »

Desconectado elgarbe

  • Moderador Local
  • PIC24H
  • *****
  • Mensajes: 2178
Re:Desreferenciando caracteres en una struct...
« Respuesta #25 en: 10 de Febrero de 2016, 06:55:47 »
A ver si puedo dar vuelta la cosa.

En mi programa principal, yo solo saco datos usando esta funcion (la cual solo modifica TAIL):

Código: C
  1. /* Pop multiple items from Ring buffer */
  2. int RingBuffer_PopMult(RINGBUFF_T *RingBuff, void *data, int num)
  3. {
  4.         uint8_t *ptr = RingBuff->data;
  5.         int cnt1, cnt2;
  6.  
  7.         /* We cannot insert when queue is empty */
  8.         if (RingBuffer_IsEmpty(RingBuff))
  9.                 return 0;
  10.  
  11.         /* Calculate the segment lengths */
  12.         cnt1 = cnt2 = RingBuffer_GetCount(RingBuff);
  13.         if (RB_INDT(RingBuff) + cnt1 >= RingBuff->count)
  14.                 cnt1 = RingBuff->count - RB_INDT(RingBuff);
  15.         cnt2 -= cnt1;
  16.  
  17.         cnt1 = MIN(cnt1, num);
  18.         num -= cnt1;
  19.  
  20.         cnt2 = MIN(cnt2, num);
  21.         num -= cnt2;
  22.  
  23.         /* Write segment 1 */
  24.         ptr += RB_INDT(RingBuff) * RingBuff->itemSz;
  25.         memcpy(data, ptr, cnt1 * RingBuff->itemSz);
  26.         RingBuff->tail += cnt1;
  27.  
  28.         /* Write segment 2 */
  29.         ptr = (uint8_t *) RingBuff->data + RB_INDT(RingBuff) * RingBuff->itemSz;
  30.         data = (uint8_t *) data + cnt1 * RingBuff->itemSz;
  31.         memcpy(data, ptr, cnt2 * RingBuff->itemSz);
  32.         RingBuff->tail += cnt2;
  33.  
  34.         return cnt1 + cnt2;
  35. }

y en mi interrupcion, despues de seguir varios llamados a ISRs llego a esta funcion que mete cosas en el RB (la cual solo modifica HEAD):

Código: C
  1. /* Insert a single item into Ring Buffer */
  2. int RingBuffer_Insert(RINGBUFF_T *RingBuff, const void *data)
  3. {
  4.         uint8_t *ptr = RingBuff->data;
  5.  
  6.         /* We cannot insert when queue is full */
  7.         if (RingBuffer_IsFull(RingBuff))
  8.                 return 0;
  9.  
  10.         ptr += RB_INDH(RingBuff) * RingBuff->itemSz;
  11.         memcpy(ptr, data, RingBuff->itemSz);
  12.         RingBuff->head++;
  13.  
  14.         return 1;
  15. }

Como ven una modifica la tail y la otra modifica la head. Ninguna funcion modifica las dos cosas.
Entonces, mientras en el main solo haga uso de Insertar ó Quitar cosas al/del RB y en la ISR haga la accion contraria, no veo que haya problema.
Creo que los problemas con los RB es cuando se mezclan las cosas, o sea, tanto en el main como en la ISR quiero meter cosas y/o quiero quitar cosas.

Saludos!
-
Leonardo Garberoglio

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:Desreferenciando caracteres en una struct...
« Respuesta #26 en: 10 de Febrero de 2016, 13:21:31 »
Podrias pasar que hace estas funciones:

Código: [Seleccionar]
RB_INDH(RingBuff)
Código: [Seleccionar]
RB_INDT(RingBuff)
Y como decis. Si usas uno y otro no deberia haber ningun problema. A no ser que uses tambien alguna otra como la de un flush del buffer.
« Última modificación: 10 de Febrero de 2016, 13:37:43 por KILLERJC »

Desconectado BrunoF

  • Administrador
  • DsPIC30
  • *******
  • Mensajes: 3865
Re:Desreferenciando caracteres en una struct...
« Respuesta #27 en: 10 de Febrero de 2016, 14:17:05 »
Tengo pendiente responderte KILLER, perdoná. No creas que es un examen! Yo planteo las preguntas para todos! No tengo necesariamente las respuestas! Es un tema de debate, no de profesor/alumno!

y qué pasa con el miembro count de la struct del RB? acaso no lo modificás desde fuera y dentro de la interr si modificás el tail y el head?
"All of the books in the world contain no more information than is broadcast as video in a single large American city in a single year. Not all bits have equal value."  -- Carl Sagan

Sólo responderé a mensajes personales, por asuntos personales. El resto de las consultas DEBEN ser escritas en el foro público. Gracias.

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:Desreferenciando caracteres en una struct...
« Respuesta #28 en: 10 de Febrero de 2016, 17:21:48 »
Tengo pendiente responderte KILLER, perdoná. No creas que es un examen! Yo planteo las preguntas para todos! No tengo necesariamente las respuestas! Es un tema de debate, no de profesor/alumno!

y qué pasa con el miembro count de la struct del RB? acaso no lo modificás desde fuera y dentro de la interr si modificás el tail y el head?

No bruno los unicos modificables son head y tail nomas. Todo lo demas se inicia y quedaria como constante.
Por la forma que usa head y tail. Tiene que saber si o si: la cantidad de elementos + tamaño de cada uno. Explico el procedimiento

Como veras head y tail no se wrapean, lo unico que puede pasar es un integer overflow. es decir siempre estan sumando. Entonces como hace para obtener el indice ?

Suponete que tenes 3 elementos y que tu buffer es de 512 elementos, y que usaste muy mucho ya el array entonces

head es: 0xFFFF.549
tail es: 0xFFFF.546
count: 0x0200

Entonces para sacar el indice , lo que hace es restar primero head y tail y haciendo una AND con count - 1. quedando:

head - tail = 0x3
count - 1 = 0x1FF

Resultado = 0x3
Que luego afecta al puntero multiplicandose por el tamaño del item ( imtSz )

Es decir de todos los elementos de la estructura, los unicos que varian son head/tail

Desconectado elgarbe

  • Moderador Local
  • PIC24H
  • *****
  • Mensajes: 2178
Re:Desreferenciando caracteres en una struct...
« Respuesta #29 en: 10 de Febrero de 2016, 18:18:41 »
Si bien creo que todos conocen la forma de trabajar de RB que implementó NXP, acá repito un buen link sobre el tema:

http://www.simplyembedded.org/tutorials/interrupt-free-ring-buffer/

tambien otro sobre interrupt-safe RB:

http://www.downtowndougbrown.com/2013/01/microcontrollers-interrupt-safe-ring-buffers/

Podrias pasar que hace estas funciones:
Código: [Seleccionar]
RB_INDH(RingBuff)
Código: [Seleccionar]
RB_INDT(RingBuff)Y como decis. Si usas uno y otro no deberia haber ningun problema. A no ser que uses tambien alguna otra como la de un flush del buffer.

en ring_buffer.c

Código: C
  1. #define RB_INDH(rb)                ((rb)->head & ((rb)->count - 1))
  2. #define RB_INDT(rb)                ((rb)->tail & ((rb)->count - 1))

En ring_buffer.h:

Código: C
  1. /**
  2.  * @def         RB_VHEAD(rb)
  3.  * volatile typecasted head index
  4.  */
  5. #define RB_VHEAD(rb)              (*(volatile uint32_t *) &(rb)->head)
  6.  
  7. /**
  8.  * @def         RB_VTAIL(rb)
  9.  * volatile typecasted tail index
  10.  */
  11. #define RB_VTAIL(rb)              (*(volatile uint32_t *) &(rb)->tail)
  12.  
  13. /**
  14.  * @brief       Initialize ring buffer
  15.  * @param       RingBuff        : Pointer to ring buffer to initialize
  16.  * @param       buffer          : Pointer to buffer to associate with RingBuff
  17.  * @param       itemSize        : Size of each buffer item size
  18.  * @param       count           : Size of ring buffer
  19.  * @note        Memory pointed by @a buffer must have correct alignment of
  20.  *                      @a itemSize, and @a count must be a power of 2 and must at
  21.  *                      least be 2 or greater.
  22.  * @return      Nothing
  23.  */
  24. int RingBuffer_Init(RINGBUFF_T *RingBuff, void *buffer, int itemSize, int count);

" * @note   Memory pointed by @a buffer must have correct alignment of
 *          @a itemSize, and @a count must be a power of 2 and must at
 *          least be 2 or greater.
 * @return   Nothing"

No estoy en casa así que este codigo lo saque de internet y creo que es de otro chip, pero la implementacion es transparente al chip, por lo que seguro el código es el mismo.

Saludos!
-
Leonardo Garberoglio