TODOPIC

Microcontroladores PIC => Lenguaje C para microcontroladores PIC => Mensaje iniciado por: Nocturno en 25 de Febrero de 2007, 16:36:32

Título: Cómo emular punteros a constantes en CCS
Publicado por: Nocturno en 25 de Febrero de 2007, 16:36:32
Está bien clarito en el manual del compilador: "En CCS no se admiten punteros a constantes".

Pero me niego a pensar que no haya forma de hacer lo que pretendo, aunque no soy capaz de encontrarla.

Resumiendo, tengo esta constante:

char const consigna[] = {"Me encanta que los planes salgan bien\0"};

Y tengo esta función, que va perfecta con variables string no constantes:
void glcd_texto(  char *text )

Pues bien, si llamo a la función de esta guisa:
glcd_texto(consigna);

me devuelve esta palabrota:
Error: Attempt to create a pointer to a constant

He probado múltiples combinaciones, pero no consigo que furule, ¿alguna sugerencia?
Título: Re: Cómo emular punteros a constantes en CCS
Publicado por: RedPic en 25 de Febrero de 2007, 17:03:07
Querido Manolo, con la iglesia hemos topado.  :(

Por activa y por pasiva lo he intentado y el muro me ha sido insalvable. Me uno a tu petición: Si alguien conoce un truco para solventar esto por favor que lo haga público y recibirá mis gracias mas efusivas, saltarinas, festeras y aplausibles ...  :D

Título: Re: Cómo emular punteros a constantes en CCS
Publicado por: IIIC en 25 de Febrero de 2007, 17:30:56
Creo que ese problema ya lo solventaron, aqui un extracto para la version 4 de ccs

busquen en el tema "Variable length constant strings" de la pagina   http://www.ccsinfo.com/content.php?page=v4compiler

y de ahi en adelante encontraran la solucion.

Título: Re: Cómo emular punteros a constantes en CCS
Publicado por: Modulay en 25 de Febrero de 2007, 20:43:23
¿Probaste con esto?

char const consigna[] = {"Me encanta que los planes salgan bien\0"};
char *texto;

texto = consigna;
glcd_texto( texto );
Título: Re: Cómo emular punteros a constantes en CCS
Publicado por: Nocturno en 26 de Febrero de 2007, 03:00:05
No entiendo cómo dice CCS que en su versión 4 ya funcionan los punteros a constantes, puesto que no para de salirme el dichoso Error: Attempt to create a pointer to a constant.

He encontrado una solución que no me gusta, por el consumo de recursos que representa, pero que al menos funciona. Si establecemos al principio del programa el siguiente parámetro:
#device PASS_STRINGS=IN_RAM
el compilador copiará las constantes a la RAM antes de trabajar con ellas y las utilizará normalmente.

Si alguien consigue lo de los punteros a constantes, sigo estando interesado. Gracias
Título: Re: Cómo emular punteros a constantes en CCS
Publicado por: djpalas en 26 de Febrero de 2007, 08:40:24
Hola amigos!!


Viendo en la web CCS sale "Version 4 adds new ways of allowing pointers to constant data. First, Version 4 adds pointers to constants"

Según  he visto en los ejemplos usan punteros constantes a datos constantes. Prueba estos cambios a ver como va.

Código: C++
  1. char const consigna[] = {"Me encanta que los planes salgan bien\0"}; // Me suena del EquipoA, aqui seria el Equipo TodoPIC  :D :D
  2. const char *ptr;
  3.  
  4. ptr = consigna[];
  5. glcd_texto(ptr);

Supongo que en la función se necesita un puntero que no sea constante, por lo que se podría hacer la siguiente modificación en la función:
Código: C++
  1. void glcd_texto( const char *ptrfijo ){   // Admitimos punteros constantes
  2.  
  3. char *text;      // Creamos un puntero variable
  4. text = ptrfijo;   // Asignamos la dirección de memoria del puntero constante al puntero fijo con el que se trabajará
  5.  
  6. //.... instrucciones que haya .....
  7. }

Otro asunto sería la creación de sobrecargas de funciones, que no estoy seguro si lo admitiría el CCS. Si lo admite sería mejor solución ;)

PD: Hace mucho que no toco punteros, así que pruebalo y ya me contaras Manolo.

Saludos!
Diego J.
Título: Re: Cómo emular punteros a constantes en CCS
Publicado por: Nocturno en 26 de Febrero de 2007, 13:07:58
Lo he probado, querido DJ, pero sigue fallando. No entiendo cómo dicen que ya funciona...  :x
Título: Re: Cómo emular punteros a constantes en CCS
Publicado por: PalitroqueZ en 26 de Febrero de 2007, 13:21:38
bueno nocturno, si no puedes conseguirlo, tendras que hacerlo a lo clásico: usar el puntero del primer carácter y después hacer un barrido de direcciones.

Salu2
Pedro
Título: Re: Cómo emular punteros a constantes en CCS
Publicado por: IIIC en 26 de Febrero de 2007, 13:39:08
Realmente aun no he tenido la necesidad de implementar ese tipo de codigo, pero haciendo unas pruebas  he encontrado que de estas dos formas me compilan perfecto.

////////////EJEMPLO 1:

void glcd_texto(  char *text );

void main()
{
  const char consigna[] = "Me encanta que los planes salgan bien\0";
  char *ptr;

     ptr = consigna;

     glcd_texto(  ptr );
}


void glcd_texto(  char *text ){}


////////////Ejemplo 2

void glcd_texto(  char *text );

void main()
{
char consigna[] = "Me encanta que los planes salgan bien\0";
char *ptr;

ptr = &consigna[0];

     glcd_texto(  ptr );
}

void glcd_texto(  char *text ){}


espero ayude en algo. saludos
Título: Re: Cómo emular punteros a constantes en CCS
Publicado por: Nocturno en 26 de Febrero de 2007, 16:44:37
Nada, que no hay manera. La primera de tus opciones sí compila, pero no funciona; en vez de el mensaje correcto aparece texto en arameo. El puntero no apunta donde debería.

El segundo ejemplo ni me compila, me aparece este error "Expenting an identifier" en esta línea:
ptr=&consigna[0];
Título: Re: Cómo emular punteros a constantes en CCS
Publicado por: reiniertl en 26 de Febrero de 2007, 17:10:47
Manolo la  primera línea debe estar bien, el problema es que ese puntero está apuntando a memoria de programas y por tanto creo que tendrías que utilizar el operador sizeof() para obtener el tamaño del dato y luego cuando incrementes el índice le pasas ese valor por ejemplo:


int16 addres;
for(int i = 0; i < strlen(consigna); i++)
  {
     addres = ptr + sizeof(consigna[0])*i;
     putc(&addres);
  }

Espero que con eso elimines las jerigonzas. Dime si sale bien para guardarlo en mi sesoteca.

Saludos Reinier
Título: Re: Cómo emular punteros a constantes en CCS
Publicado por: Nocturno en 27 de Febrero de 2007, 02:46:15
Ah, claro. Si le quito "const" sí funciona, pero entonces deja de ser una constante.

No entiendo bien tu ejemplo, Reinier. ¿De dónde sale "ptr"?
Título: Re: Cómo emular punteros a constantes en CCS
Publicado por: RedPic en 27 de Febrero de 2007, 03:56:12
Claro, sin const es una variable que ocupa RAM, con const es una constante que ocupa ROM

El truco estriba en usar una porcion de ROM direccionandola como si fuese RAM. En el curso que dimos sobre dsPIC éstos lo hacían directamente .... Pero parece que en los 16F y los 18F esto es más dificil (cuanto menos)

Título: Re: Cómo emular punteros a constantes en CCS
Publicado por: Nocturno en 27 de Febrero de 2007, 04:10:05
Sí, con C30 y dsPIC sale fácil. De hecho ya lo uso y por eso estoy encabezonado con conseguirlo en CCS para 18F.

Avanzando en mi investigación, observo que el printf se lo traga bien sin distinguir si son constantes o no. Ahora intento comparar el tratamiento que el comando "printf" hace de las strings que están en RAM  con el que hace de las que están en ROM.

Pego aquí un trozo de programa y su compilación. Sólo tiene dos líneas, cuya única diferencia es que en la primera intento imprimir la constante "yo" y en la segunda el string "consigna", que no es constante:

Código: ASM
  1. 71:                   printf (glcd_caracter,yo);
  2.   04CA    6A31     CLRF 0x31, ACCESS
  3.   04CC    5031     MOVF 0x31, W, ACCESS
  4.   04CE    DD9A     RCALL 0x4
  5.   04D0    2A31     INCF 0x31, F, ACCESS
  6.   04D2    6E00     MOVWF 0, ACCESS
  7.   04D4    6A34     CLRF 0x34, ACCESS
  8.   04D6    6E33     MOVWF 0x33, ACCESS
  9.   04D8    DE87     RCALL 0x1e8
  10.   04DA    0E0F     MOVLW 0xf
  11.   04DC    5C31     SUBWF 0x31, W, ACCESS
  12.   04DE    E1F6     BNZ 0x4cc
  13. 72:                   printf (glcd_caracter,consigna);
  14.   04E0    6AEA     CLRF 0xfea, ACCESS
  15.   04E2    0E08     MOVLW 0x8
  16.   04E4    6EE9     MOVWF 0xfe9, ACCESS
  17.   04E6    0E00     MOVLW 0
  18.   04E8    10EF     IORWF 0xfef, W, ACCESS
  19.   04EA    E010     BZ 0x50c
  20.   04EC    CFEA     MOVFF 0xfea, 0x32
  21.   04F0    CFE9     MOVFF 0xfe9, 0x31
  22.   04F4    6A34     CLRF 0x34, ACCESS
  23.   04F6    CFEF     MOVFF 0xfef, 0x33
  24.   04FA    DE76     RCALL 0x1e8
  25.   04FC    C032     MOVFF 0x32, 0xfea
  26.   0500    C031     MOVFF 0x31, 0xfe9
  27.   0504    2AE9     INCF 0xfe9, F, ACCESS
  28.   0506    B4D8     BTFSC 0xfd8, 0x2, ACCESS
  29.   0508    2AEA     INCF 0xfea, F, ACCESS
  30.   050A    D7ED     BRA 0x4e6

Ahora ya estoy de fango hasta las orejas, porque el ASM y yo no nos llevamos bien. Si alguno de vosotros lo ve claro en eso que he pegado, agradeceré su ayuda.
Título: Re: Cómo emular punteros a constantes en CCS
Publicado por: PalitroqueZ en 21 de Marzo de 2007, 14:05:38
Claro, sin const es una variable que ocupa RAM, con const es una constante que ocupa ROM

El truco estriba en usar una porcion de ROM direccionandola como si fuese RAM. En el curso que dimos sobre dsPIC éstos lo hacían directamente .... Pero parece que en los 16F y los 18F esto es más dificil (cuanto menos)



ahora que analizo mejor el comentario de Diego,  pienso que la aplicación de punteros a constantes si es fáctible, porque la idea es liberar la RAM de las largas tablas y dejar esto para la ROM, el problema es que para acceder a ella se necesita un puntero.

dicho de otra forma, los datos declarados como constantes se alojan en la ROM y su acceso es a través de su dirección.

es lo mismo que dijo RedPic, estoy viendo que en los PIC18 existe una instrucción TBLRD para leer y TBLWT para escribir en  la memoria de programa. pero ya es ensamblador :(

Título: Re: Cómo emular punteros a constantes en CCS
Publicado por: PalitroqueZ en 22 de Marzo de 2007, 11:04:36
Hola Nocturno. Sabes que estuve viendo detenidamente la instrucción TBLRD para leer datos de la ROM

entre unos ejemplitos que escribí e investigando en la ayuda del CCS, llegué al siguiente resultado:

- una forma de guardar tablas en la ROM es usando

#rom direccion = {'datos'}

y la función para leerla es

READ_PROGRAM_MEMORY (direccion, dataptr, count );

dataptr es el arreglo donde se guardaran los datos y count la cantidad de bytes


aquí hay un ejemplo que hice

Código: C
  1. #include <18f4550.h> //archivo de cabecera
  2. #use delay(clock=48000000) // el clock que tendremos a la entrada del CPU
  3.  
  4. #rom 0x600 = {"Me encanta que los planes salgan bien\0"}
  5.  
  6. void main(){
  7. int   i[39], t;
  8.    for(t=0;t<39;t++){
  9.       i[t]=0;  // limpiamos el arreglo
  10.    }
  11.     delay_cycles(1);
  12.     read_program_memory(0x600,i,39);
  13.     // cargamos la direccion del puntero y guardamos la tabla en
  14.     // el arreglo i
  15.     delay_cycles(1);
  16. }

una simulación en MPLAB:

ver imagen en el adjunto.

si miramos el listado en asm por un momento veremos

Código: ASM
  1. 13:                    read_program_memory(0x600,i,39);
  2.   0056    6AF8     CLRF 0xff8, ACCESS   ; TBLPTRU <- 0
  3.   0058    0E06     MOVLW 0x6
  4.   005A    6EF7     MOVWF 0xff7, ACCESS  ; TBLPTRH <- 0x6
  5.   005C    6AF6     CLRF 0xff6, ACCESS   ; TBLPTRL <- 0

ese pedacito de código está cargando a 0x600 en el el registro de 21 bits TBLPTR sospecho y casi que estoy seguro que hacen la lectura a través del Table Latch (TABLAT) para después tomar los datos a partir de esa dirección.


no se como se implementaría en tu programa, pero haz la prueba a ver si esto te sirve.

si hay que estar pendiente que la direccion esté desocupada (el inconveniente), pero se puede solucionar si asignas al resto del código un #org start, end es cuestión de jugar con la cantidad de espacio que se lleve tu programa.

Título: Re: Cómo emular punteros a constantes en CCS
Publicado por: Nocturno en 22 de Marzo de 2007, 14:06:28
Gracias Palitroquez. Ahora estoy metido en otra guerra, pero cuando pueda lo probaré.