Inicio

Navegación

  • Foros
  • Buscar
  • Idiomas

Proyectos

  • Howto
  • Open Hardware
  • Open Software

Inicio de sesión

  • Crear nueva cuenta
  • Solicitar una nueva contraseña

Pulpito JM60

Tweets

Videos

Coundown Ubuntu

The next version of Ubuntu is coming soon

Utilizar flash como Eprom en la familia HC08:

Turkos — Mié, 08/26/2009 - 00:08

En algunas ocasiones necesitamos grabar ciertos datos como no volátiles para mantenerlos aún después de haber quitado la energía a nuestro sistema. Como ejemplos podemos citar "almacenar" datos temporales, variables temporales, seteos, tablas transitorias, etc.

Para estos casos es una válida opción pensar en un circuito integrado externo a nuestro microcontrolador el cual se puede conseguir en el mercado y que puede ser de diferentes características, pero lo mejor sería en el caso de poseer memoria flash excedente en nuestro microcontrolador utilizar la misma para grabar nuestros datos, esto presenta principales ventajas como por ejemplo: al no utilizarse un chip externo de memoria, se dispone de mayor cantidad de Pines I/O para usos generales y NO para el control de la memoria, se Ahorra el costo del chip externo de memoria y en el espacio en la placa, flexibilidad en el tamaño de la memoria a utilizar, ya que utilizaremos lo necesario y dejaremos el resto para la memoria del programa, circuitos adicionales integrados en el MCU como el LVI necesarios para el correcto funcionamiento de un sistema con memoria no volátil.

Algo interesante en los dispositivos hc08 a destacar es que dispone de una tecnología de memoria flash llamada Split gate, super flash o flash de segunda generación (TSMC flash) esto permite la programación en circuito tanto en modo usuario como monitor y además posee una bomba de carga que elimina la necesidad de altos voltajes al momento de la programación lo que posibilita el uso en dispositivos a pila como por ejemplo dataloggers.

Aparte implementa un mecanismo interno de protección que evita la copia del software por competidores como así también borrados accidentales y daños por software maliciosos.

Lo que permite realmente el uso como memoria EEprom dentro de las aplicaciones es que proporciona la posibilidad de programar solamente un bloque pequeño y aparte posee un menor tiempo de programación 30, 40 us por byte y ofrece como mínimo 10,000 ciclos de programación/borrado en todo el rango de temperatura de trabajo mientras que otras tecnologías de flash proporcionan solamente 100 ciclos de programación/borrado.

Este artículo pretende mostrar uno de los métodos más eficientes para la programación de la memoria flash y está inspirada en la nota de aplicación de freescale AN2346.

El método clásico de grabado en flash:

En las hojas de datos de los microcontroladores de freescale propone un método de grabado de flash, que si bien es efectivo nos exige copiar el código de la rutina en memoria Ram ya que no se puede modificar datos en la flash y correr el programa al mismo tiempo. En el siguiente diagrama de flujo podemos ver este método:

Para más información sobre este método buscar cualquier datasheet de cualquier microcontrolador hc80, ya que excede los propósitos de este artículo.

El método elegante y fácil

Estas rutinas son las que se pueden encontrar en la nota de aplicación AN2346 solo que realicé algunas modificaciones para luego llamarlas desde código en lenguaje c. Lo bueno de las mismas es que nos permiten grabar de a un byte y que ya que la unidad mínima de borrado es de 64 bytes podemos realizar el guardado de nuestros datos varias veces en ese rango antes de borrarla totalmente, entonces si solo tenemos que grabar un byte de datos lo grabaremos 64 veces consecutivamente antes de borrar toda la pagina, esto incrementará la vida útil de la memoria de nuestro MCU como piña de moto.

Las dos rutinas que trae el hc08 para el grabado de flash y se encuentran en la ROM son las siguientes:

Hay que consultar el manual del mcu a utilizar para saber cuales son las direcciones de estas rutinas para cada micro en particular.

Aparte de estas rutinas necesitamos algunas variables en ram, estas son: CPUSpd(($89) para determinar la frecuencia del bus, LstAddr ($8A y $8B) para grabar la ultima dirección de flash y un buffer de datos BfrStrt ($8C). El tamaño del buffer de datos es del tamaño de un block de datos.

Rutina de búsqueda de memoria en blanco:

Esta rutina busca el último dato grabado para poder volver a grabar en la misma página sobre los bytes que están en blancos, estas memorias están en blanco cuando todos los bits del mismo están en uno (0xFF) en hexadecimal, esto nos obliga a hacer que nuestra aplicación no utilice ese valor como dato valido para grabar en flash.

Rutina de escritura en flash:

Esta rutina llamada “WrtBlock” inicializa el inicio de la memoria Ram donde se encuentran las variables CtrlByt y CPUSpd y empila dentro del stack el tamaño del block de memoria y después llama a la rutina “FindClear”. Entonces chequea el acumulador y si este se encuentra en 0xFF y graba el block de datos usando el valor en el registro de 16 bits (H:X) Si el acumulador no se encuentra en cero quiere decir que no hay lugar en la room para otro bloque de datos y entonces se borra la página y se inicializa la dirección en el principio de la página.

Archivos a incorporar en el proyecto de codewarrior:

Para que sea mas fácil de usar realicé dos archivos con las variables, constantes y funciones a utilizar para que solamente tengamos que anexarlo en nuestro proyecto y luego llamarlas para grabar en flash. Las funciones fueron programadas en assembler, pero luego incluidas en funciones.



/********************************************************************************/
/* Write_Flash.h */
/* Archivo cabecera con las funciones, variables y constantes */
/* Necesarias para el grabado de flash */
/* */
/* */
/********************************************************************************/
#ifndef __Write_Flash
#define __write_Flash

/*Dirección del bloque a grabar*/
#include "derivative.h"

#define EraRnge 0x2806 ;//FLASH erase routine in ROM
#define PgrRnge 0x2809 ;//FLASH programming routine in ROM
#define CtrlByt 0x88 ;//control byte for ROM subroutines
#define CPUSpd 0x89 ;//CPU speed in units of 0.25MHz
#define LstAddr 0x8A ;//last FLASH address to be programmed
#define Blklpace 0xEE00;
#define BlkSize 0x05;

byte Escritura[7] @LstAddr;

void RdBlock(void);

void WrtBlock(void);

#endif

/***********************************************************************/
/* Write_Flash.c */
/* */
/* */
/* */
/* */
/***********************************************************************/

/*----------------------------------------------------
*RdBlock:
*Lee un block de datos desde la flash y la guarda en RAM
*Parámetros:
* Blklpage Inicio del bloque de FLASH de datos
* BlklSize Tamaño del bloque
*Retorna:
* Punto donde empiezan los datos grabados de FLASH
* Dato del primer byte del bloque
*
*
*
*
*
*
*
*
*
-----------------------------------------------------*/
void RdBlock(void) {

asm{
SEI
ldhx #Blklpace;
lda #BlkSize;

RdBlock: psha; //Empila BlSize
bsr FindClear; //busca el primer bloque borrado

cmp #$FF; //Está en blanco???
bne skipdec;//
txa;
and #$3F;
beq skipdec;
txa
sub 1,sp
tax

skipdec: lda ,x;
ais #1;
rts;

FindClear: lda #$40 ;
sub 3,sp ;
psha ;
floop:
lda ,x ;
cmp #$FF;
beq finish1;

pula ;
sub 3,sp ;
psha ;
bmi finish2 ;

txa ;
add 4,sp ;
tax ;
bra floop ;

finish2: clra ;
finish1: ais #1 ;
cli
rts

}

}

void WrtBlock(void){

asm{
SEI
ldhx #Blklpace;
lda #BlkSize;

WrtBlock: mov #13,CPUSpd ;
clr CtrlByt ;
psha ;
bsr FindClear;
cmp #$FF ;
beq blkfnd ;
jsr EraRnge ;
txa ;
and #$C0 ;
tax ;

blkfnd: pula ;
pshx ;
add 1,sp ;
deca ;
tax ;
sthx LstAddr ;
pulx ;
jmp PgrRnge ;

FindClear: lda #$40 ;
sub 3,sp ;
psha ;
floop:
lda ,x ;
cmp #$FF;
beq finish1;

pula ;
sub 3,sp ;
psha ;
bmi finish2 ;

txa ;
add 4,sp ;
tax ;
bra floop ;

finish2: clra ;
finish1: ais #1 ;
cli
rts

}
}

Quiero aclarar que yo no realicé algunas simplificaciones que se pueden hacer, por ejemplo la función en assembler FindClear puede escribirse solamente una vez y luego llamarla de las otras dos funciones, así ahorrarnos un poco de Flash.

Para llamar estas funciones desde nuestro programa principal lo que debemos hacer es escribir el siguiente código:



RdBlock(); //Para leer el bloque de memoria grabado

asm
{
sthx LecAddr; //Pasamos el valor del registro (H:X) a un puntero
//LecAddr es el principio del vector de tamaño igual
//al tamaño de bloque a leer y contendrá los datos leídos
}

Para escribir en RAM hacemos lo siguiente:



WrtBlock() //Si llamamos a esta función lo
//que pasará es que el contenido en el vector
//con dirección LstAddr en mi caso lo llamé Escritura[ ]
//se grabará en el próximo lugar de flash en blanco

Bueno amigo, eso es todo, espero que lo entiendan. Lo que se puede hacer después es debugearlo en el codewarrior, ya que no se puede simular porque el simulador no tiene implementadas estas rutinas. Cualquier duda no duden en dejar comentarios.

Comparta este post con:
  • Delicious
  • Digg
  • StumbleUpon
  • Newsvine
  • Facebook
  • Google
  • Yahoo
  • Twitter
  • Inicie sesión o regístrese para enviar comentarios

Gracias...

JuanJo_SeSe — Jue, 08/27/2009 - 12:43

Turkex, ni bien pueda voy a hacer pruebas con este asunto... gracias!

  • Inicie sesión o regístrese para enviar comentarios
Imagen de sebest

Gracias

sebest — Mié, 08/26/2009 - 22:09

Gracias Turkos, muy completo tu informe, apenas termine las cosas que estoy haciendo, me voy a poner a probar esto que se ve muy interesante.
Nos vemos

  • Inicie sesión o regístrese para enviar comentarios

Seguinos en Twitter
Seguir a sebastianoldani en Twitter