Uso correcto de la Flash de los módems Cinterion TC65 y XT65
Escrito por blogElectronica en 2.DISPOSITIVOS (práctico), 4.PROGRAMACIÓN, Comunic. GSM/GPRSEn muchas ocasiones podemos tener la necesidad de utilizar el FFS (File Flash System) de nuestros módems gprs Cinterion TC65 ó XT65 para realizar volcados de datos a ficheros. Ejemplo típico es el caso del XT65 y las posiciones GPS. Vamos leyendo las posiciones GPS cada X segundos y las vamos almacenando en un fichero para su posterior envío a la central. Ejemplos de este tipo hay muchos tanto para el TC65 como para el XT65.
Es fácil caer en la tentación de ir generando ficheros en la memoria Flash para el almacenaje de información. Creando ficheros y borrándolos cuando los consideremos procesados (por ejemplo, cuando los hayamos enviado por GPRS a la central o simplemente borrándolos cuando ya no los consideremos necesarios).
Realmente es la manera más sencilla de realizar una aplicación (creamos ficheros y los borramos cuando no los queremos) pero debemos tener precaución con esta técnica. Escribir datos en la memoria flash del módem no es problema, éstos se graban byte a bye (ya que la memoria FLASH de los Siemens es de tipo NOR que a diferencia de las tipo NAND la grabación puede hacerse incluso bit a bit. Con las NAND, más baratas pero también más malillas, la grabación es por bloques). El proceso de borrado, en cambio, SÍ es crítico, porque tanto con las NOR como con las NAND se realizan por bloques. El tamaño del cluster en la flash del módem es de 64KB, eso implica que cuando borramos un archivo realmente estamos borrando un bloque de 64KB. Así es, aunque borremos un fichero que tan solo contenga 100 bytes de datos en realidad estamos actuando sobre 64KB en la memoria flash del módem.
Si tenemos en cuenta que que en una memoria Flash es posible realizar unas 100.000 grabaciones y que el tamaño de la memoria Flash del TC65 es de unos 1.7MBytes y tendiendo en cuenta que el tamaño del cluster que es de 64KB, no resulta difícil ver que no debemos abusar del borrado de archivos. Es decir, veamos un ejemplo, si creamos un pequeño fichero de 100 bytes y lo borramos cada minuto, aproximadamente cada 26 minutos (1.7 / 0.064) hemos “dado un repaso” a toda la flash. Esto significa que al cabo de 100.000 x 26 = 2.600.000 minutos (o menos) nos habremos cargado la flash casi seguro. Cada día tiene 1440 minutos, un año 365 x 1440 = 525.600 minutos, lo que implica que a los 2.600.000 / 525.600 = 4.9 años (casi seguro antes, ya que hay procesos internos del módem que también escriben en flash) nuestro módem morirá. También hay que tener presente que cuando borramos un cluster (por ejemplo para borrar un fichero de 100 bytes que hay en él) en resto de la información que hay en el cluster no se debe borrar, por los que los algoritmos internos del gestor de la FFS del módem deben reescribir la información que hay en él y que no debe borrarse, es decir, más desgaste a la flash para descontar además del riesgo añadido que supone el corte de suministro eléctrico en ese momento de la copia.
¿Cómo actuar entonces?
En caso de querer utilizar ficheros con nuestra aplicación java debemos evitar en lo posible el borrado continuo de los mismos por lo comentado anteriormente. La mejor forma de evitarnos problemas es crear un fichero en la Flash (o los ficheros que precise nuestra aplicación) e intentar no borrarlos NUNCA. Es decir, por ejemplo, creamos 2 ficheros Log1.txt y Log2.txt y vamos almacenando registros (con registro me refiero, por ejemplo, una trama GPS de logitud fija).
Imaginémonos que nos marcamos un máximo de 5000 registros por fichero. Una vez escribamos los 5000 registros en Log1.txt empezamos a escribir los datos en Log2.txt y ya podemos enviar Log1.txt por GPRS a nuestro servidor central. Tras el proceso de envío de Log1.tx NO borramos el fichero. Cuando hayamos escrito otros 5000 registros en Log2.txt empezaremos a escribir en Log1.txt MACHACANDO sobre el registro 1 y así sucesivamente hasta llegar al registro 5000. Es decir, el truco está en sobreescribir los registros y no borrar los ficheros. Esta es una manera de ahorrarnos, de verdad, problemas desagradables al cabo del tiempo por desgaste de la memoria Flash.
Cuando programamos sobre los TC65 y XT65 debemos pensar que estamos trabajando sobre un módulo embebido y no sobre un Core 2 DUO con HHDD. Que sí, que son unos módulos muy potentes y al programar en java y con sistema de archivos a veces perdemos todos un poco esa perspectiva de módulo embebido, pero debemos tenerlo en cuenta.
Espero que encontréis de utilidad este post. Otro día más.
Post relacionados:
- Localizando fallos difíciles de reproducir en los módems Cinterion TC65, XT65 Si desarrollas aplicaciones en Java para los módems gprs TC65,...
- Memoria Ram y Flash de los módems TC65 y XT65 Últimamente me han preguntado bastante en relación a la memoria...
- Ejemplo de FTP Java para módems gprs Cinterion TC65 y XT65 Posiblemente en alguna ocasión tengas que hacer un programita en...
- Compresión de archivos con J2ME en módems GPRS Siemens TC65 En muchas aplicaciones con módems GPRS es necesario almacenar datos...
- Añadir datos a ficheros con módems Siemens-Cinterion desde java En bastantes ocasiones me ha llegado la pregunta de cómo...
Etiquetas: cinterion, ejemplos java, mtx65, mtx65+g, Siemens, xt65
Buen post, es algo que si no lo tienes en cuenta luego te llevas sorpresas desagradables.
Tengo dos preguntas, a ver si me puedes guiar con ellas:
- Cuando escribo en un fichero puedo hacerlo de dos maneras: o escribo desde el principio o añado al final. Cómo se hace para escribir directamente sobre el registro X?
- Cómo controlas que tienes 5000 registros en un fichero?
Hola.
Buen post … que nos llama la atención sobre el tema que existe aunque pensemos que no nos afecta.
Mi solución pasó por retardar el tiempo lo máximo posible (30-60 minutos) y “confiar” en que los dioses sean “magnánimos”.
Para (Pedro) poder escribir en una posición aleatoria del fichero puede valer este código (ojo que no lo he probado, pues escribo al final del fichero):
com.siemens.icm.io.file.FileConnection fichero= (com.siemens.icm.io.file.FileConnection) javax.microedition.io.Connector.open(rutaFichero);
java.io.DataOutputStream dos= new java.io.DataOutputStream(fichero.openOutputStream(posicionDondeEscribir));
dos.objDataOutputStream.write( datos, inicio, tamano);
La solución que se podría dar es:
- Crear un fichero con X*ctd registros máximos a almacenar.
- En otro fichero almacenar el puntero del primer y último registro (como una lista circular). Estos datos habría que actualizarlos para cada operación.
Yo no empleé esta solución pues pensé que también castigaría la memoria Flash para cada una de las actualizaciones. Según entiendo del artículo esto no es así ¿VERDAD?, el daño viene por el borrado y no por el sobreescribir los datos.
Saludos.
Perdón … se me olvidó …
Si los registros no tienen tamaño constante, la solución existe pero es más complicada (almacenar para cada registro su tamaño, meter separadores, …).
Saludos.
Hola Miguel,
efectivamente es distinto la grabación que el borrado por el tipo de memoria. Castigas mucho más con el borrado que con la escritura. Con la escritura sólo afectas a los bytes que escribes, con cada borrado afectas a 64KB.
Salu2.
Hola.
Sobre el tema hay algo a lo que estoy dándole vueltas … con la escritura afectas a los bytes que escribes PERO será de una forma mucho más continuada y en las mismas posiciones -> llevará a un degradado mucho más rápido de esas posiciones.
El problema es que se tendría que implementar un mecanismo de comprobación (grabas la información, la lees para verificar que esas posiciones siguen siendo válidas, … si no son válidas a crear otro fichero y vuelta a empezar).
Por supuesto SALVO que se disponga de un controlador de “posiciones defectuosas”.
Saludos y gracias por la respuesta.
Hola,
Según tengo entendido cuando uno escribe en una memoria flash lo que se hace es cambiar el estado de los bits que están en 1 y ponerlos a 0. (los bits que antes estaban en 1 y que luego de la escritura siguen en 1 no se tocan).
Ej. Posición de memoria 0×100 que está en blanco osea libre para escribir. Sí está en blanco el valor de la posición asumiendo una arquitectura de 8 bits sería 0xFF (0b11111111). Si en esa posición yo escribo el valor 0×30(0b00110000) lo que se hace es cambiar el estado de los bits 0,1,2,3,6 y 7 a 0. Estos bits que se han cambiado a estado 0 NO podrán ser modificados nuevamente hasta que se realice una operación de borrado sobre esa posición de memoria. Así que lo de sobreescribir la posición de memoria flash sin haberla borrado antes si es posible pero el valor que quedará almacenado no es el deseado. De modo que de acuerdo a lo anterior y según mis conocimientos la recomendación de MACHUCAR que dan acá no es muy válida que digamos.
Saludos,
Lo que se debe hacer si se necesita implementar una especie de backlog GPS o alguna otra funcionalidad en la que se deban almacenar datos temporalmente en flash mientras estos son utilizados es implementar un algoritmo de desgaste parejo para nuestra memoria flash. Averiguen bien porque me supongo que los Cinterion deben tener dicho algoritmo ya implementado y sino en la red se encuentra info acerca del tema de desgaste parejo.
Si quieren saber si el modem tiene dicha funcionalidad de desgaste parejo implementada deben hacer la sgte prueba. Cojan un modem nuevo y hagan un sencillo programa que en un ciclo infinito coja y escriba en una posición de memoria un número de un contador, luego lo lea, si hay match incrementa el contador y de nuevo empieza a guardar y así sucesivamente. Cuando no haya match, si el contador empezó en 0 entonces el último valor del contador que se almacenó equivale al número de veces que se logró sobreescribir la misma posición de memoria flash. Esta prueba se les va demorar por ahí 1 mes si el modem tiene desgaste parejo así que cuando hagan el programita tengan en cuenta que el modem podrá reiniciarse durante la prueba (el contador no debe empezar en 0 cada vez que el modem se reinicie, se debe cargar de flash el último valor escrito y arrancar con el valor leido).
Sí el número es mucho mayor a 100.000 (he obtenido valores de 40.000.000) significa que el modem tiene algoritmos de desgaste parejo para su memoria flash. Si éste es el caso ese modem ya ha quedado con TODA su memoria flash mala o gastada.
Yo he hecho la anterior prueba para varias marcas de modem y en todos he logrado escribir y leer un bloque de memoria de 30KBytes más de 20.000.000 de veces (veinte millones de veces).
Saludos.
Hola aldanajaramillo,
cuando hablo de machacar en ningún sitio estoy hablando de sobreescribir físicamente una posición de memoria interna de la flash, entre otras cosas, porque desde java no puedo especificar usar una determinada posición de memoria concreta dentro del FFS, de eso se encargan los algoritmos internos del módem.
Cuando hablo de machacar me refiero a los registros del archivo, no a posiciones de memoria concretas. ¿Si no porqué ahí arriba digo que el borrado se hace por sectores de 64KB? ¿Qué sentido tendría poder borrar si pudiese sobreescribir un único byte físico con 0xFF? Por otro lado te puedo decir que cuenta con algoritmos para escribir de forma homogénea toda la memoria, supongo que es lo que tú llamas desgaste parejo.
La estrategia de machacar los registros dentro de un archivo en el FFS no lo digo porque sí. Por mi trabajo estoy directamente relacionado con el personal técnico de M2M de Siemens / Cinterion, con quien trato bastante a menudo, y son ellos quienes recomiendan esa esta técnica de sobreescribir registros en ficheros en lugar de borrar ficheros y crear nuevos y te aseguro que ahorra problemas. Lo veo cada día entre quienes usan una técnica u otra, pero bueno, cada uno es libre de utilizar las técnicas que quiera, por supuesto.
Salu2.
Hola Blog, yo estoy usando la clase RecordStore y quiero saber si me conviene seguir usando esta Mini Base de Datos en mi aplicacion. Yo tb voy creando, agregando, modifiando y eliminando registros, y viene funcionando muy bien.
Que me aconcejas?
Hola Ulises,
no veo ningún problema al uso de RecordStore.
Salu2.
Una pregunta, si no borro ninguno de mis ficheros, pero sí que los trunco (función .truncate() ) para que tengan tamaño 0 y vuelvo a escribirlos ¿Es correcto? Técnicamente no los estoy borrando pero no sé si es correcto a nivel físico de la memoria. ¿Es correcto o tendré problemas a la larga?
Hola Pablo,
sinceramente no lo se. No se a nivel físico qué es lo que hace el método truncate con la memoria. Si lo averiguo te cuento.
Salu2.
Buenas tardes!
Soy brasileño ….
Artículo muy bueno, pero tiene una duda, este mismo procedimiento puede ser
hacer uso de RMS, que ya tiene un índice. Si es posible tener un montón de cambios
la filosofía de desarrollo más allá de las específicas para trabajar con RMS
Me queda una duda, como bien dices en la nota, siempre es conveniente sobreescribir ántes que borrar un archivo (más precisamente en el párrafo donde hablas de los archivos Log1.txt y Log2.txt, de “machacar” los registros), ahora bien, para poder “sobreescribir” en la memoria, internamente no debe borrar primero el sector a escribir? porque de ser así cada vez que sobreescribimos estamos en la misma de borrar el archivo…
Hola Juan Manuel,
no, no tiene por qué. ¿Acaso tu no borras archivos de tu disco duro y aunque los borres siguen estando ahí, es decir, que son recuperables con ciertos software? Pues aquí lo mismo. La decisión de en qué sectores se escribe en la Flash es tomada por algoritmos internos del módulo, que según me dijeron en su día (aquí si me tengo que fiar de lo que me dicen desde Siemens, ya que yo no tengo el código fuente para darle un vistazo a ver qué hace) están correctamente diseñados para tal fin.
Salu2
Pues entonces a confiar en ellos, no tenemos motivos para no hacerlo hasta ahora, jejeje, gracias por la respuesta, salu2!
Estaba leyendo este articulo tan interesante y me ha surgido una duda.
Cuando escribo en un fichero ¿como puedo escribir el final de fichero?.
Me explico. Yo tengo que guardar un dato de configuración. Ese dato no es siempre igual de largo con lo que si escribo en el fichero un nuevo dato más corto, aun se me guarda la parte final del dato anterior y al leerlo me da problemas. Por ejemplo:
Dato viejo: activado
Dato nuevo: parado
Al escribir en el fichero el dato nuevo obtengo: paradodo
He probado a poner un null al final del dato y con el caracter ctrl+z pero no funciona.
Tambien he leido en los comentarios lo de la funcion truncate pero no he sabido hacerla funcionar.
En el fondo esto no es un problema porque ese dato se va a cambiar en muy contadas ocasiones y me basta borrar el fichero y crear otro pero tal vez en un futuro necesite hacerlo con mucha frecuencia y me gustaria saber la manera.
Muchas gracias
Bien, olvidad lo del truncate. Acabo de darme cuenta de que no le ponia el argumento. En cualquier caso, me gustaría saber como escribir el fin de fichero.
Gracias por su tiempo