TODOPIC

Microcontroladores PIC => Lenguaje C para microcontroladores PIC => Mensaje iniciado por: Tulkas en 21 de Abril de 2009, 10:00:29

Título: Problemas con RAM en el CCS
Publicado por: Tulkas en 21 de Abril de 2009, 10:00:29
Hola a todos,

Estoy terminando de programar un datalogger hecho con un pic18f2620 que posee una tarjeta de memoria SD y un GPS.  Resulta que hace tiempo usando el mismo hardware que estoy usando ahora hice un datalogger muy sencillo escrito en asembler, ahora lo estoy haciendo con muchas más opciones en C. Ahora que lo tengo casi terminado he empezado a tener problemas extraños como por ejemplo variables que uso como contador de repente toman un valor distinto y deja de funcionar el programa, este problema en concreto no es debido a que use una variable global y la esté modificando en otra parte del programa, creo que el problema está en que estoy usando punteros para direccionar los datos que voy adquiriendo.  El programa funciona básicamente así, voy adquiriendo datos de un conversor externo, tomo la hora de un reloj externo también y luego escribo todo eso en la memoria RAM del pic, cuando lleno 512 bytes los guardo en la tarjeta de memoria.  Tanto cuando guardo los datos en la memoria del pic como cuando los leo para guardarlos en la tarjeta SD los direcciono con un puntero y creo que el problema está ahí, en ensamblador se exactamente donde estoy escribiendo los datos, en que zona de la memoria, pero en C no, no se si el puntero me está sobreescribiendo variables que tengo en RAM o variables que tengo definidas me sobreescriben posiciones del puntero.  Además otra cosa que no entiendo es que si yo le indico a un puntero que el primer elemento va a estar en una zona concreta de la memoria por qué cuando leo la posición de memoria a la que apunta me saca cualquier número?.  No se si alguien me puede ayudar, puedo especificar más las cosas si es necesario.

Muchas gracias de antemano.

Un saludo.
Título: Re: Problemas con RAM en el CCS
Publicado por: migsantiago en 21 de Abril de 2009, 11:36:45
Hola

Cuando declaras una variable CCS no la inicializa en cero. Por eso cuando usas el puntero a una dirección ram y luego la lees, el contenido es aleatorio. Usa lo siguiente para inicializar tus variables estáticas:

#zero_ram

Si son dinámicas, como el puntero que mencionas, deberás inicializarlas a cero manualmente.

Sobre tu otro problema de que cambian los datos de tus arreglos, mientras vuelcas un arreglo desde la ram hacia la SD, ¿sigues muestreando y escribiendo en el arreglo de la ram? El escribir en una SD toma mucho tiempo y el muestreo puede estar destruyendo datos mientras estos no se han acabado de respaldar en la SD.
Título: Re: Problemas con RAM en el CCS
Publicado por: Tulkas en 21 de Abril de 2009, 15:35:26
Hola, muchas gracias por tu rápida respuesta.

En cuanto a lo primero que me indicas, lo que quería decir es que si yo le asigno una posición de memoria a un puntero, por ejemplo si tengo el siguiente puntero *ptr y le asigno ptr=0x100, le estoy indicando que el primer elemento está en esa posición de memoria, por qué al leerlo no me devuelve esa posición?, me refiero a leer ptr, no *ptr, no me refiero a leer el contenido de esa posición, sino la dirección en si misma.  Lo digo porque me gustaría asegurarme que el puntero recorre una región de RAM específica.

En cuanto a tu segunda respuesta, la adquisición es bastante lenta, guardo los datos entre conversión y conversión.

Muchas gracias
Título: Re: Problemas con RAM en el CCS
Publicado por: migsantiago en 21 de Abril de 2009, 15:57:42
No soy experto con punteros en ccs, pero Palitroquez tiene una guía excelente al respecto:

http://www.todopic.com.ar/foros/index.php?topic=16680.0
Título: Re: Problemas con RAM en el CCS
Publicado por: PalitroqueZ en 21 de Abril de 2009, 17:52:42
bueno tampoco es que yo sea experto en punteros, solo fué un poco de curiosidad  :mrgreen:

mira Tulkas, en ccs hay una directiva llamada #reserve, deberias usarla cuando declares variables en las cuales no quieres que se "toquen" durante la ejecución del programa.

Título: Re: Problemas con RAM en el CCS
Publicado por: Tulkas en 07 de Mayo de 2009, 07:06:58
Hola,  he estado varios dias fuera y no he podido contestar.

Al final parece que todo funciona, pero me ha aparecido otro problema y no se si sigue siendo por el uso de la memoria.

Resulta que he estado usando un puerto serie para la salida de datos al tiempo que escribo esos datos en la tajerta de memoria, la cosa es que como no tenía un max232 a mano hice el desarrollo usando los pines del puerto serie hardware del pic pero usando el TX como RX y el RX como TX de tal forma que el CCS crea un puerto serie software y no usa el puerto serie hardware, ya que este último no soporta la opción "invert" indispensable para comunicarme con un ordenador sin usar un MAX232.  La cosa es que ahora cuando he terminado el programa quiero añadir la opción de poder parar la adquisición y hacer un reset a través del puerto serie, esto solo es posible habilitando la interrupción para el puerto serie y para ello necesito usar el hardware.  Aparentemente funciona todo, pero se suele quedar colgado muchas veces, incluso se queda colgado al inicio del programa en el que simplemente saco caracteres, cosa que no pasaba cuando usaba el puerto serie software.  No entiendo lo que ocurre, además cuando uso el puerto serie hardware, la memoria de programa del pic se libera bastante ya que no tiene que crear un puerto serie 'virtual' y por tanto no debería bloquearse ni nada por el estilo.  Alguna idea??.


Muchas gracias a todos.
Título: Re: Problemas con RAM en el CCS
Publicado por: migsantiago en 07 de Mayo de 2009, 12:55:28
Es complicado detectar un problema sin poder ver el código.
Título: Re: Problemas con RAM en el CCS
Publicado por: MLO__ en 07 de Mayo de 2009, 22:45:11
Pues cuando se usa puertos series por soft hay que ser cuidadoso con las funciones de recepcion, ya que no se gestionan por interrupcion si no por conocimiento del protocolo, lo que hace que muchas veces el PIC pareciera que se quedara colgado, pero es pura falla humana -ya ha pasado otras veces-.

seria bueno ver el codigo para poder dar mas opiniones al respecto.
Título: Re: Problemas con RAM en el CCS
Publicado por: Tulkas en 08 de Mayo de 2009, 06:18:41
Hola, gracias por responder.

Intentaré poner una parte del programa porque todo es demasiado.  En cuanto al puerto serie sofware, lo que realmente falla es cuando uso el módulo hardware, cuando uso el puerto serie por soft funciona perfecto, pero sin la capacidad de interrupción claro.  Luego postearé el programa.

Un saludo.
Título: Re: Problemas con RAM en el CCS
Publicado por: Tulkas en 08 de Mayo de 2009, 07:50:31
Hola, el codigo es algo así.  El problema me aparece al principio.

Lo que hago es inicializar la tarjeta y luego buscar el sector inicial de datos, para encontrar el sector inicial de datos necesito encontrar el sector de arranque y ahí coger lo que necesito para calcular el primer sector de datos, o lo que es lo mismo el cluster numero 2 para tarjetas fat16.

La inicialización de la tarjeta se hace con la función CARD_INI() que aparece por ahi.  En esa función simplemente inicio la MMC o SD y voy sacando por pantalla el tipo de tarjeta que se ha detectado, si entra en modo idle, si acepta el tamaño del bloque, y todo lo que respecta a la inicialización de la tarjeta, aquí el puerto serie siempre funciona bien, veo todo los mensajes.  Hasta aquí aún no he usado el puntero

A continuación busca el primer sector de datos con la función "int32 BOOT_SECTOR (int8 *punter)" que la pego más abajo.  Esta función comienza a leer todos los sectores de la tarjeta comenzando en el 0 y verificando que el primer byte de cada sector leido es 0xEB que indica si estamos en el sector de arranque, una vez encontrado este sector cojo lo que me hace falta para calcular el primer sector de datos y lo devuelvo al programa principal, donde luego lo imprimo por pantalla.  Y es aquí donde se queda colgado, he verificado que efectivamente la función que busca el sector de arranque se ejecuta pero luego se queda bloqueada en la parte donde uso el puntero.


Código: [Seleccionar]
void main()
{
   output_high(CS_CARD);

   //CREAMOS UN PUNTERO QUE RECORRA LA RAM DEL PIC PARA DATOS Y OTRO PARA LEER RELOJ

   ptr = (int8 *)malloc(768*sizeof(int8));          //puntero para datos
   ptr_rtc = (int8 *)malloc(16*sizeof(int8));      //puntero que lee y escribe hora del RTC

   delay_ms(1000);
   
   //INICIALIZACION DEL RTC
   
   RTC_CONFIG(count,counth,clock32,dm_unmask,alarm_dis);
   
   //INICIALIZACION DE LA TARJETA, CONFIGURAMOS SPI LENTO
     
   setup_spi(SPI_MASTER|SPI_L_TO_H|SPI_XMIT_L_TO_H|SPI_CLK_DIV_16);
   
   //INICIALIZACION DE LA TARJETA
   CARD_INI();
   //UNA VEZ INICIALIZADA AUMENTAMOS LA VELOCIDAD
   setup_spi(SPI_MASTER|SPI_L_TO_H|SPI_XMIT_L_TO_H|SPI_CLK_DIV_4);   
   //BUSCAMOS EL SECTOR INICIAL DE DATOS TENIENDO EN CUENTA LOS SECTORES OCULTOS
   SECTOR_INICIAL = BOOT_SECTOR(ptr);
   fprintf(data,"SECTOR INICIAL = %Lu\n\r",SECTOR_INICIAL);

....
....
....
....
....

}

Esta sería la función en la que entra y se bloquea.


Código: [Seleccionar]
int32 BOOT_SECTOR(int8 *punter)
{
   int16 RootDirSectors,BPB_RootEntCnt,BPB_BytsPerSec;
   int16 BPB_NumFATs;
   int16 BPB_FATSz16;
   int32 FirstDataSector,BPB_FATSz32,FATSz;
   HIDDEN_SECTORS = 0;
   while(1)
   {
      SINGLE_BLOCK_READ(HIDDEN_SECTORS, punter);
      if (*punter == 0xEB)
      {
         BPB_RootEntCnt = MAKE16(*(punter+18),*(punter+17));

         BPB_BytsPerSec = MAKE16(*(punter+12),*(punter+11));

         BPB_SecPerClus = *(punter+13);

         RootDirSectors = ((BPB_RootEntCnt * 32) + (BPB_BytsPerSec - 1)) / BPB_BytsPerSec ;

         BPB_FATSz16 = MAKE16(*(punter+23),*(punter+22));

         BPB_FATSz32 = MAKE32(*(punter+39),*(punter+38),*(punter+37),*(punter+36));

         if (BPB_FATSz16 != 0){FATSz = (int32) BPB_FATSz16;}
         else{FATSz = BPB_FATSz32;}

         BPB_NumFATs = *(punter+16);
         BPB_ResvSecCnt = MAKE16(*(punter+15),*(punter+14));

         
         FirstDataSector = (int32)BPB_ResvSecCnt + ((int32)BPB_NumFATs * FATSz) + (int32)RootDirSectors;

         //ESTAMOS EN EL BOOT SECTOR
         
         break;
      }
      else{HIDDEN_SECTORS++;}
   }
   return (FirstDataSector + HIDDEN_SECTORS);
}

El puerto serie lo he definido en el archivo ".h" del programa de la siguiente forma
Código: [Seleccionar]
#use rs232(stream = data,baud=19200,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8)
Cuando uso el puerto serie software y modifico esa linea de la siguiente forma
Código: [Seleccionar]
#use rs232(stream = data,baud=19200,parity=N,xmit=PIN_C7,rcv=PIN_C6,bits=8,invert)
el programa funciona correctamente y no se bloque en ningún momento.

Muchas gracias. Espero que se entienda
Título: Re: Problemas con RAM en el CCS
Publicado por: Tulkas en 12 de Mayo de 2009, 09:01:18
Hola buenos días, sigo teniendo problemas con el software y creo que es por la definición de los punteros que uso.  Si esto sigue así lo siguiente que haré es olvidarme de los punteros y usar matrices directamente, aunque será un engorro enorme modificar todo lo que he hecho.

La última pregunta es:  Alguien podría decirme como definiría dos punteros en el que uno de ellos recorrería 768 bytes mientras que el otro recorrería 128 bytes y además que estuvieran definidos en distintas regiones de ram y que no se solaparan?.

Muchas gracias.
Título: Re: Problemas con RAM en el CCS
Publicado por: PalitroqueZ en 12 de Mayo de 2009, 19:48:06
...
La última pregunta es:  Alguien podría decirme como definiría dos punteros en el que uno de ellos recorrería 768 bytes mientras que el otro recorrería 128 bytes y además que estuvieran definidos en distintas regiones de ram y que no se solaparan?.

Muchas gracias.

si es por punter, tienes que definirlo como int16 porque asi como lo tienes, solo recorrerá 255 posiciones.

en distintas regiones, no se puede, tienen que ser todas las posiciones seguidas.
Título: Re: Problemas con RAM en el CCS
Publicado por: BrunoF en 12 de Mayo de 2009, 20:12:44
...
La última pregunta es:  Alguien podría decirme como definiría dos punteros en el que uno de ellos recorrería 768 bytes mientras que el otro recorrería 128 bytes y además que estuvieran definidos en distintas regiones de ram y que no se solaparan?.

Muchas gracias.

si es por punter, tienes que definirlo como int16 porque asi como lo tienes, solo recorrerá 255 posiciones.

O ni siquiera. Si punter es un puntero a cualquier posición de la RAM, puede que apunte a una posición de memoria más allá de la 0xFF, por lo que vas a recorrer hasta 256 posiciones de memoria, tal vez, completamente equivocadas.
Título: Re: Problemas con RAM en el CCS
Publicado por: migsantiago en 13 de Mayo de 2009, 13:19:18
Tengo una duda sobre apuntadores con CCS.

Un apuntador en un procesador con arquitectura von-Neumann es capaz de apuntar cualquier dirección RAM mientras tenga una longitud de bits apropiada; por ejemplo en un procesador de 32 bits, el apuntador debe medir 32 bits.

En los pic16 se sabe que la ram no es direccionable al 100% y que hay que usar 2 bits para acompletar los 9 bits que puede tener cualquier dirección RAM.

Si declaro un apuntador como el siguiente en CCS:

int8 *apuntador;

¿Es capaz de direccionar cualquier dirección RAM de forma automática, es decir, CCS se encarga de poner los 2 bits del banco en donde corresponde?

Al declarar la variable apuntador como un int8*, CCS deberá asignarle un espacio de al menos 9 bits, por lo que internamente la creará como un int16, pero en realidad es un int8*.

 :?:
Título: Re: Problemas con RAM en el CCS
Publicado por: BrunoF en 13 de Mayo de 2009, 15:56:16
Hola Santi!

Mira, el CCS cuando utilizas punteros usa el direccionamiento indirecto a la RAM, por lo que usa los registros FSR e INDF para ello. El FSR es capaz de direccionar de a 256 posiciones a la vez ya que es de 8 bits por lo que con un puntero de 8 bits estarías en condiciones de poder direccionar a cualquiera de las primeras 256 posiciones RAM del uC. Obviamente hay modelos de la familia 16F que tienen más que eso, por lo que no alcanzaría con un puntero de 8 bits.

Me surgió la duda sobre lo que comentaste. Yo pensé que el CCS sólo direccionaría a las primeras 256 posiciones RAM si usabas un puntero de 8 bits, pero para mi asombro salió esto al desensamblar el código que probé:

;                       int8  *ptr;

MOVLW  01        ;ptr=0x100;
MOVWF  x22
CLRF      x21

Podemos ver claramente que el CCS ignora el tamaño que le indicamos(8 bits) y utiliza en realidad un puntero de 16 bits, ubicado en este caso en las posiciones 0x22 y 0x21 (byte alto y bajo respectivamente).

Un saludo.
Título: Re: Problemas con RAM en el CCS
Publicado por: migsantiago en 13 de Mayo de 2009, 18:08:08
Viendo el ensamblador es más claro.

Pero no creo que CCS esté ignorando el int8, en mi opinión es correcto.

Por ejemplo, si yo pongo...

Código: [Seleccionar]
float *valor;
Lo que CCS va a hacer es una variable apuntador de 9 bits (2 bits banco + 7 bits dirección) que indique el comienzo de una variable float normal, por lo que el apuntador tendrá un tamaño de 16bits (necesita 9 pero habrá que usar dos bytes para llenarlo) y no de 4 bytes.

En estas condiciones me atrevo a decir que para todos los siguientes apuntadores...

Código: [Seleccionar]
int8 *ent1;
int16 *ent2;
int32 *ent3;
float *valor1;
char *valor2;

... CCS siempre apartará 2 bytes ya que la máxima dirección ram direccionable para ellos siempre es de 9 bits.

Pero ahora que nos ponemos quisquillosos... ¿qué pasará con un apuntador a int1? Bueno, nada... porque la gente de CCS todavía no se anima a implementarlos  :D Ya existen los arreglos de int1, pero no se vale usarlos apuntados.

Código: [Seleccionar]
int1 superbits[20]; //Válido
int1 *apunta;        //Inválido

Por cierto, con tu ejemplo en ensamblador resolví otra duda que ya tenía hace tiempo... ¿qué endian usa CCS? Se ve que el 0x0100 se guarda en little endian. Primero el 0x00 y después el 0x01.  :wink:
Título: Re: Problemas con RAM en el CCS
Publicado por: BrunoF en 13 de Mayo de 2009, 18:44:32
Si, es verdad lo que decís. Se me chispoteó. :D
Título: Re: Problemas con RAM en el CCS
Publicado por: PalitroqueZ en 13 de Mayo de 2009, 19:05:06
Una cosa que yo aprendí es que el size del puntero no tiene que ver con el tipo de datos del puntero. Cuando se declara un puntero con un tipo de datos, al recorrerlo, se incrementa en el ancho dado por el tipo de datos.

y el ccs adopta por default el size de 2 bytes (aunque es posible cambiárselo por directivas)

Título: Re: Problemas con RAM en el CCS
Publicado por: BrunoF en 13 de Mayo de 2009, 19:19:48
Exáctamente Pedro. El tipo de datos con el que se declara al puntero sirve para saber en cuántas direcciones de memoria deberá incrementarse o decrementarse el puntero si fuese necesario. Buen dato.
Título: Re: Problemas con RAM en el CCS
Publicado por: Tulkas en 14 de Mayo de 2009, 07:09:31
Hola chicos, gracias por responder.

Lo que no entiendo ahora es que si yo quiero almacenar 512 bytes de datos y cada dato es de 1 byte, si creo un puntero de 16 bits y hago  *(ptr+1), pasará por ejemplo de la posición de memoria 0x300 a la 0x301 o hará un salto de 2 bytes y estaríamos en la 0x302?. Si esto es así, como podría incrementar el puntero en 1 byte pero llegando a superar los 256 bytes de ram?

Muchas gracias.

Un saludo.


Título: Re: Problemas con RAM en el CCS
Publicado por: BrunoF en 14 de Mayo de 2009, 13:15:19
Hola!

Vamos a resumir la cosa:

Cuando un declara un puntero, lo hace de esta manera:

tipo *nombre_puntero;

"tipo" es el que le indica al compilador de qué tamaño es la variable o estructura a la que apunta. Esto sirve para que el compilador sepa en cuántas direccionas debe incrementar el puntero si deseas incrementarlo, cuántas(posiciones) restar en caso de querer decrementarlo, etc...

Y nombre_puntero es un nombre que uno elije.

El tamaño del puntero es elegido por el compilador automáticamente.

Si vos declarás:

int8 *ptr;                   
ptr=0x300                  //ptr=0x300
ptr++;                       //ptr=0x301

En cambio si hacés, por ejemplo:

int32 *ptr;                   
ptr=0x300                  //ptr=0x300
ptr++;                       //ptr=0x304

Saludos.
Título: Re: Problemas con RAM en el CCS
Publicado por: migsantiago en 14 de Mayo de 2009, 14:31:06
Yo pensaba que siempre incrementaba en 1 sin importar que tipo de apuntador era pero estaba mal. Bruno está en lo correcto...

Código: [Seleccionar]
.................... int8 *apuntador;
.................... int32 *apunta32;
.................... float *flota;
.................... 
.................... apuntador=0x20;
000D:  BCF    03.5
000E:  CLRF   22
000F:  MOVLW  20
0010:  MOVWF  21
.................... apunta32=0x30;
0011:  CLRF   24
0012:  MOVLW  30
0013:  MOVWF  23
.................... flota=0x40;
0014:  CLRF   26
0015:  MOVLW  40
0016:  MOVWF  25
.................... 
.................... ++apuntador;
0017:  INCF   21,F
0018:  BTFSC  03.2
0019:  INCF   22,F
.................... ++apunta32;
001A:  MOVLW  04
001B:  ADDWF  23,F
001C:  BTFSC  03.0
001D:  INCF   24,F
.................... ++flota;
001E:  MOVLW  04
001F:  ADDWF  25,F
0020:  BTFSC  03.0
0021:  INCF   26,F

Para el int8* un simple INCF basta, pero para los que miden 4 bytes es necesario sumar 4.