Como mencioné aquí , he tenido problemas con la EEPROM en dsPIC30F6012A . Dado que mi antigua biblioteca EEPROM era difícil de analizar y admitir, volví al punto de partida y la reescribí usando las nuevas rutinas integradas de EEPROM del compilador C30 (¡más nuevas que mi biblioteca!). Tomé el código de demostración de Microchip e intenté ejecutarlo. Compilado, programado, sin problemas, pero no parecía funcionar correctamente. Hice una versión modificada de su demo, también sin éxito.
Ejecuto este programa, leo el contenido del chip en MPLAB X y observo el contenido de la EEPROM. Las operaciones de borrado funcionan correctamente, cualquier dirección que borre vuelve como 0xFFFF. Pero las operaciones de escritura no hacen nada. Probé varias combinaciones, escrituras repetidas, diferentes direcciones, nada parece estar escrito.
#include <p30fxxxx.h>
#include <libpic30.h>
_FOSC(CSW_FSCM_OFF & FRC_PLL16);
_FWDT(WDT_OFF); /* Turn off the Watch-Dog Timer. */
_FBORPOR(MCLR_EN & PWRT_OFF); /* Enable MCLR reset pin and turn off the power-up timers. */
_FGS(CODE_PROT_OFF); /* Disable Code Protection */
typedef struct _eestruct {
unsigned char testdata[10];
} eestruct;
eestruct eedata __attribute__((space(eedata)));
eestruct backup_eedata __attribute__((space(eedata)));
int main(){
_prog_addressT EE_addr;
//_init_prog_address(EE_addr, eedata);
EE_addr = 0x7FF000;
int temp_word = 0x0102;
_erase_eedata(EE_addr, _EE_WORD);
_wait_eedata();
_write_eedata_word(EE_addr, temp_word);
_wait_eedata();
while(1){
ClrWdt();
};
return 0;
}
Tengo cuatro teorías:
He publicado en los foros de Microchip sin resultado. Abrí un ticket con Microchip, y lo único que hicieron fue decirme que usara/escribiera una convocatoria de asamblea. Parecen desinteresados en si/por qué estas llamadas a funciones integradas no funcionan.
¿Alguien tiene alguna sugerencia?
En caso de duda, refactorice.
No es probable que sea un problema de hardware, pero para descartarlo, intentaría reemplazar las llamadas C con las instrucciones de ensamblaje en línea exactas descritas en la sección 7 de la hoja de datos, siguiendo todas sus recomendaciones (deshabilitar interrupciones, sondear WR para probar si está listo, etc.)
Si lo hace funcionar, cree su propia función/biblioteca a partir del ensamblado en línea y continúe.
En primer lugar, una buena manera de comprobar si la EEPROM se ha escrito correctamente es volver a leerla a través de la ventana PSV (Program Space Visibility). En muchos casos no necesito la ventana PSV para nada más, así que la dejo permanentemente configurada para acceder a la EEPROM.
En segundo lugar, no miré su código C, pero aquí hay un fragmento de un proyecto 30F4013 que configura la ventana PSV para leer y escribe un byte en la EEPROM:
;**************************************************** **************************** ; ; Subrutina IEE_INIT ; ; Inicializa el estado del hardware y software gestionado por este módulo. ; glbsub iee_initregf0 ; ; Configure la ventana de visibilidad del espacio del programa para mapear la EEPROM de datos internos ; al espacio de datos. ; mov #psvpage(ieestart), w0 mov w0, Psvpag; qué región de la memoria de programación asignar a los datos adr 8000-FFFF bset Corcon, #Psv ;habilitar la ventana de visibilidad del espacio del programa descansar ;**************************************************** **************************** ; ; Macro ESPERAR_EEPROM ; ; Espere a que se complete cualquier operación anterior de EEPROM. TASK_YIELD se llama en ; un bucle durante la duración de la espera. TASK_YIELD no se llama si la EEPROM ; no está activo en la entrada. ; .macro esperar_eeprom 1: ;Vuelva aquí para comprobar que la EEPROM está ocupada de nuevo btss Nvmcon, #Wr ;¿La EEPROM está ocupada? saltar 2f ;no, todo hecho gcall task_yield; dar a otras tareas la oportunidad de ejecutarse salta 1b; vuelve a comprobar que la EEPROM está ocupada de nuevo 2: ;la EEPROM ahora está inactiva .endm ;**************************************************** **************************** ; ; Subrutina IEE_WRITE ; ; Escriba el valor en W0 en la palabra EEPROM en el desplazamiento en W1. W1 debe ; contener los 16 bits bajos de la ubicación de la EEPROM como se mapea en el programa ; memoria. Esto se puede encontrar, por ejemplo, usando la función TBLOFFSET en ; cualquiera de los símbolos de dirección definidos en la sección .EEPROM anterior. Ya que hay ; son dos direcciones por palabra EEPROM y siempre se escribe una palabra completa, la ; bit bajo de W1 es irrelevante. ; ; W1 se devuelve incrementado en 2, que es la dirección de la siguiente EEPROM ; palabra. Llamadas sucesivas a esta rutina sin modificar W1 por lo tanto ; establecer palabras secuenciales de EEPROM. ; ; Esta rutina regresa después de que se haya completado la escritura. Esto puede tomar varios ; milisegundos. TASK_YIELD se llama en un bucle durante cualquier espera. ; ; Este procesador tiene 512 palabras de EEPROM. ; glbsub iee_write, regf2 wait_eeprom; esperar a que se complete cualquier operación anterior ; ; Obtenga el valor actual de la palabra objetivo de la EEPROM en W2. ; mov #tblpage(ieestart), w2 mov w2, Tblpag ;seleccione la página de memoria del programa para acceder tblrdl [w1], w2 ;leer la palabra EEPROM de destino cp w0, w2 ;comparar el nuevo valor con el existente bra z, iew_leave ;sin cambios, nada que hacer ? ; ; Borre la palabra EEPROM si algún bit 0 se cambia a 1 bit. El ; el valor existente de la palabra está en W2. TBLPAG ya está configurado adecuadamente para ; la dirección de la EEPROM. ; com w2, w2 ;hacer máscara de bits actualmente establecida en 0 y w2, w0, w2 ;hacer máscara de 0 bits para cambiar a 1 bra z, iew_derase; no hay 1 bits que cambien a 0, omita el borrado ; ; Realiza el borrado. ; ; De acuerdo con el manual de referencia familiar, para realizar un borrado ; necesita configurar la dirección y luego borrar una palabra. Sin embargo, tenemos ; encontré que esto no funciona para el primer intento de escritura desde el inicio. ; Después de un poco de experimentación, se descubrió que cargar un pestillo de escritura ; una vez parece ser lo que permite que los borrados funcionen. Por lo tanto, cargamos el ; escriba pestillo antes de hacer un borrado, aunque esto no es necesario ; según la documentación. Desde que se cargó el pestillo de escritura para ; la palabra para borrar también establece la dirección, no necesitamos configurar ; NVMADR explícitamente. Los datos escritos en el pestillo de escritura probablemente ; no importa, pero escribimos el valor de borrado ya que eso hace que el ; más sentido y tiene la mejor oportunidad de trabajar en torno a cualquier adicional ; comportamiento no documentado. ; movimiento #0xFFFF, w2 tblwtl w2, [w1] ;cargar pestillo con el valor de borrado, establecer dirección movimiento #0b0100000001000100, w2 ; 0--------------- no iniciar la operación ahora ; -1-------------- habilitar la operación de borrado ; --0------------- borra cualquier condición de error anterior ; ---XXXXX-------- sin usar ; --------0100---- seleccionar borrar operación ; ------------0100 una palabra de datos mov w2, Nvmcon ;configure para la operación de borrado disi #5; deshabilitar interrupciones alrededor de la secuencia de desbloqueo mov #0x55, w2 ;realizar secuencia de desbloqueo mov w2, tecla Nvm movimiento #0xAA, w2 mov w2, tecla Nvm bset Nvmcon, #Wr ;iniciar el borrado wait_eeprom; esperar a que se complete el borrado iew_derase: ;hecho de borrar la palabra ; ; Escribe la palabra. ; tblwtl w0, [w1] ;escriba la palabra, incremente la dirección movimiento #0b0100000000000100, w2 ; 0--------------- no iniciar la operación ahora ; -1-------------- habilitar la operación de borrado ; --0------------- borra cualquier condición de error anterior ; ---XXXXX-------- sin usar ; --------0000---- seleccionar operación de escritura ; ------------0100 una palabra de datos mov w2, Nvmcon ;configure para la operación de borrado disi #5; deshabilitar interrupciones alrededor de la secuencia de desbloqueo mov #0x55, w2 ;realizar secuencia de desbloqueo mov w2, tecla Nvm movimiento #0xAA, w2 mov w2, tecla Nvm bset Nvmcon, #Wr ;iniciar el borrado wait_eeprom; esperar a que se complete la escritura iew_leave: ;punto de salida común agregue w1, #2, w1; incremente la dirección a la siguiente palabra EEPROM descansar
Tenga en cuenta que esta rutina hace algunas cosas buenas más allá de simplemente escribir a ciegas los nuevos datos en la EEPROM. No hace nada si la palabra EEPROM ya está configurada como se desea, y también omite el borrado si solo 1 bit se cambia a 0. Esto desgastará menos la EEPROM, especialmente si algún otro código entra accidentalmente en un bucle escribiendo en EEPROM. .
leon heller
W5VO
dsPIC30F6012a
Esteban Collings
gbarry
Esteban Collings