Página 1 de 1

Problemas na FLASH como EEPROM do QG08

MensagemEnviado: 19 Ago 2007 20:34
por Budzinski
Olá Pessoal,

Estou com dificuldades para gravar na FLASH do QG08. Estou tentando usar a flash como EEPROM, pelo exemplo do livro do Fábio não consegui rodar. Quando adiciono o arquivo doonstack.h o compilador gera um erro no linker por faltar definição para a rotina FlashProg. Se adiciono o arquivo doonstack.ASM gera outros erros na compilação... Onde posso estar errando?

Valeu !!!

MensagemEnviado: 20 Ago 2007 10:04
por Fábio Pereira
Que outros erros de compilação ?

Eu utilizo há bastante tempo estas funções e funcionam muito bem.

Outra coisa: você está utilizando o CW 6.0 ? Se estiver, tem de alterar algumas coisas (comentar os dois símbolos no início do arquivo ASM):

;mPageErase equ $40
;mByteProg equ $20

Até +

MensagemEnviado: 20 Ago 2007 10:14
por Budzinski
Isso mesmo, estou usando o Code 6... Talvez seja isso então, os erros são esses:

Imagem

MensagemEnviado: 20 Ago 2007 13:32
por Budzinski
Pelo que acompanhei no DEBUG, o bit FACCERR está indo para nivel lógico 1 quando faz uma escrita ou apagamento... Ou seja, o procedimento doonstack não está correto...

Que saudade dos HC08 !!! rsrsrsrsrsrs

MensagemEnviado: 21 Ago 2007 09:50
por Fábio Pereira
Eu não tenho saudade nenhuma ...

Uma dúvida: você tem um main.c e um main.asm. Porquê ?

T+

MensagemEnviado: 22 Ago 2007 08:42
por Budzinski
Eu tinha criado um projeto C com realocate asm... Só para teste, porém não ajudou muito...
Os erros de compilação eu arrumei, porém o bit FACCERR vai para 1 logo que roda as instruções do doonstack. Ou seja, a sequencia de programação não está correta!!!


Segue o doonstack.asm como ficou:


;**************************************************************
;* This stationery is meant to serve as the framework for a *
;* user application. For a more comprehensive program that *
;* demonstrates the more advanced functionality of this *
;* processor, please see the demonstration applications *
;* located in the examples subdirectory of the *
;* Metrowerks Codewarrior for the HC08 Program directory *
;**************************************************************
; export symbols
XDEF DoOnStack
XDEF FlashErase
XDEF FlashProg
; we use export 'Entry' as symbol. This allows us to
; reference 'Entry' either in the linker .prm file
; or from C/C++ later on

; include derivative specific macros
Include 'mc9s08qg8.inc'

; variable/data section
MY_ZEROPAGE: SECTION SHORT
; Insert here your data definition. For demonstration, temp_byte is used.
; temp_byte ds.b 1

; code section
MyCode: SECTION
;**************************************************************
; this assembly routine is called the C/C++ application
DoOnStack: pshx
pshh ;save pointer to flash
psha ;save command on stack
ldhx #SpSubEnd ;point at last byte to move to stack;
SpMoveLoop: lda ,x ;read from flash
psha ;move onto stack
aix #-1 ;next byte to move
cphx #SpSub-1 ;past end?
bne SpMoveLoop ;loop till whole sub on stack
tsx ;point to sub on stack
tpa ;move CCR to A for testing
and #$08 ;check the I mask
bne I_set ;skip if I already set
sei ;block interrupts while FLASH busy
lda SpSubSize+6,sp ;preload data for command
jsr ,x ;execute the sub on the stack
cli ;ok to clear I mask now
bra I_cont ;continue to stack de-allocation
I_set: lda SpSubSize+6,sp ;preload data for command
jsr ,x ;execute the sub on the stack
I_cont: ais #SpSubSize+3 ;deallocate sub body + H:X + command ;H:X flash pointer OK from SpSub
lsla ;A=00 & Z=1 unless PVIOL or ACCERR
rts ;to flash where DoOnStack was called
;**************************************************************
SpSub: ldhx LOW(SpSubSize+4),sp ;get flash address from stack
sta 0,x ;write to flash; latch addr and data
lda SpSubSize+3,sp ;get flash command
sta FCMD ;write the flash command
lda #FSTAT_FCBEF ;mask to initiate command
sta FSTAT ;[pwpp] register command
nop ;[p] want min 4~ from w cycle to r
ChkDone: lda FSTAT ;[prpp] so FCCF is valid
lsla ;FCCF now in MSB
bpl ChkDone ;loop if FCCF = 0
SpSubEnd: rts ;back into DoOnStack in flash
SpSubSize: equ (*-SpSub)
;**************************************************************
FlashErase: psha ;adjust sp for DoOnStack entry
lda #(FSTAT_FPVIOL+FSTAT_FACCERR) ;mask
sta FSTAT ;abort any command and clear errors
lda #mPageErase ;mask pattern for page erase command
bsr DoOnStack ;finish command from stack-based sub
ais #1 ;deallocate data location from stack
rts
;**************************************************************
FlashProg: psha ;temporarily save entry data
lda #(FSTAT_FPVIOL+FSTAT_FACCERR) ;mask
sta FSTAT ;abort any command and clear errors
lda #mByteProg ;mask pattern for byte prog command
bsr DoOnStack ;execute prog code from stack RAM
ais #1 ;deallocate data location from stack
rts
;**************************************************************

Att.
Vicente

MensagemEnviado: 22 Ago 2007 11:25
por Fábio Pereira
E o seu programa em C, como está ?

T+

MensagemEnviado: 24 Ago 2007 08:23
por Budzinski
Segue o código em C:
Código: Selecionar todos
#include <hidef.h> /* for EnableInterrupts macro */
#include "derivative.h" /* include peripheral declarations */

#include "main_asm.h" /* interface to the assembly module */

#include "hcs08.h"
#include "doonstack.h" // inclui as funções para manipulação da memória FLASH

  /* FCDIV: DIVLD=0,PRDIV8=0,DIV5=1,DIV4=0,DIV3=0,DIV2=1,DIV1=1,DIV0=1 */
  FCDIV = 0x27;                                     

 
const char PROTECAO[1] @0xFFBD=0b11100010;

void Start_MCU();

// lê um endereço da memória FLASH
unsigned char flash_read(unsigned int endereco)
{
  unsigned char *ponteiro;
  ponteiro = (char*) endereco;
  return (*ponteiro);
}

// escreve em um endereço da memória FLASH
unsigned char flash_write(unsigned int endereco, unsigned char dado)
{
  unsigned char *ponteiro;
  // guarda o endereço da memória em um ponteiro
  ponteiro = (char*) endereco;
  // verifica e apaga flag de erro de acesso a FLASH
  if (FSTAT_FACCERR) FSTAT_FACCERR=1;
  // chama a função de programação da FLASH
  FlashProg(ponteiro,dado);
  // se houve erro, retorna 1 caso contrário, retorna 0
  if (FSTAT_FACCERR || FSTAT_FPVIOL) return(1); else return(0);
}

// apaga uma página da memória FLASH
unsigned char flash_page_erase(unsigned int endereco)
{
  unsigned char *ponteiro;
  // guarda o endereço da memória em um ponteiro
  ponteiro = (char*) endereco;
  // verifica e apaga flag de erro de acesso a FLASH
  if (FSTAT_FACCERR) FSTAT_FACCERR=1;
  // chama a função de apagamento da FLASH
  FlashErase(ponteiro);
  // se houve erro, retorna 1 caso contrário, retorna 0
  if (FSTAT_FACCERR || FSTAT_FPVIOL) return(1); else return(0);
}



/*
** ===================================================================
** CONFIGURA MCU
** ===================================================================
*/
void Start_MCU()
{
   asm
   {
      lda 0x0000FFAF
      sta ICSTRM
   }
   //ICSTRM = 166; // para 8Mhz
   SOPT1 = 0b00000010; // CONFIG 1
  /*        |||||||+-- RSTPE   = PINO RESET HABILITADO ???
            ||||||+--- BKGDPE  = HABILITA BDM ???
            |||||+---- ??????  = NULL
            ||||+----- ??????  = NULL
            |||+------ ??????  = NULL
            ||+------- STOPE   = HABILITA MODO STOP ???
            |+-------- COPT    = CONTAGEM COP 0=8192 OU 1=262144
            +--------- COPE    = HABILITA COP ???
  */
   SOPT2 = 0b10000000; // CONFIG 2
  /*        |||||||+-- ACIC    = CONECTA COMPARADOR CANAL 0 ???
            ||||||+--- IICPS   = I2C 0=SDA->PTA2 SCL->PTA3
            |||||+---- ??????  = NULL
            ||||+----- ??????  = NULL
            |||+------ ??????  = NULL
            ||+------- ??????  = NULL
            |+-------- ??????  = NULL
            +--------- COPCLKS = CLOCK COP 0=1KHZ 1=FBUS
  */
  SPMSC1 =0b01010100; // REGISTRADOR BAIXA TENSÃO
  /*        |||||||+-- BGBE    = HABILITA BUFFER ???
            ||||||+--- ??????  = NULL 
            |||||+---- LVDE    = HABILITA LVD ??? 
            ||||+----- LVDSE   = HABILITA LCD MODO STOP ???
            |||+------ LVDRE   = GERA RESET CASO LVD
            ||+------- LVDIE   = GERA INTERRUPÇÃO CASO LVD
            |+-------- LVDACK  = 1 APAGA FLAG LVDF
            +--------- LVDF    = SINALIZA BAIXA TENSÃO
  */
  IRQSC = 0b01000100; // INTERRUPÇÃO EXTERNA
  /*        |||||||+-- IRQMOD  = MODO DE DISPARO
            ||||||+--- IRQIE   = HABILITAÇÃO IRQ 
            |||||+---- IRQACK  = 1 APAGA O FLAG IRQF 
            ||||+----- IRQF    = SINALIZA IRQ
            |||+------ IRQPE   = HABILITA PINO IRQ
            ||+------- IRQEDG  = BORDA x NIVEL
            |+-------- IRQDD   = PULL-UP
            +--------- ??????  = NULL 
  */
   
   ICSC2 = 0b00110100; // ICSC2
   
  ICSC1 = 0b00000110;
  /*        |||||||+-- IREFSTEN= REFERENCIA MODO STOP
            ||||||+--- IRCLKEN = CLOCK INTERNO??? 
            |||||+---- IREFS   = REFENCIA INTERNA??? 
            ||||+----- RDIV    = FATOR DE DIVISAO
            |||+------ RDIV    =
            ||+------- RDIV    =
            |+-------- IRQDD   = PULL-UP
            +--------- ??????  = NULL 
  */
  PTADD = 0b00000001; // DIREÇÃO DA PORTA A
  /*        |||||||+-- PTA0
            ||||||+--- PTA1
            |||||+---- PTA2
            ||||+----- PTA3
            |||+------ PTA4
            ||+------- PTA5
            |+-------- PTA6
            +--------- PTA7
  */
  PTADS = 0b00000001; // MODO POTENCIA NA PORTA A
  /*        |||||||+-- PTA0
            ||||||+--- PTA1
            |||||+---- PTA2
            ||||+----- PTA3
            |||+------ PTA4
            ||+------- PTA5
            |+-------- PTA6
            +--------- PTA7
  */
  PTBDD = 0b11110110; // DIREÇÃO DA PORTA B
  /*        |||||||+-- PTB0
            ||||||+--- PTB1
            |||||+---- PTB2
            ||||+----- PTB3
            |||+------ PTB4
            ||+------- PTB5
            |+-------- PTB6
            +--------- PTB7
  */
  PTBDS = 0b11110110; // MODO POTENCIA NA PORTA B
  /*        |||||||+-- PTB0
            ||||||+--- PTB1
            |||||+---- PTB2
            ||||+----- PTB3
            |||+------ PTB4
            ||+------- PTB5
            |+-------- PTB6
            +--------- PTB7
    */
   TPMSC = 0b01001000; // Configura TIM
   TPMMOD = 798;       // Timer 100uS
   
   ADCSC2 = 0b00000000;
   ADCCFG = 0b00001000;
   
   if(FSTAT_FACCERR)
      FSTAT_FACCERR=1;
   FCDIV = vFCDIV;
  DisableInterrupts;
//   __asm CLI
}


void main(void)
{
  volatile unsigned char va, vb, res;
  Start_MCU();
  va = 10;
  vb = 20;
  res = flash_page_erase(0xE000); // apaga a página da FLASH
  va = flash_write(0xE000, va); // escreve o valor de va no endereço 0xE000
  vb = flash_write(0xE001, vb); // escreve o valor de vb no endereço 0xE001
  // neste ponto, as variáveis res, va e vb devem estar com o valor 0
  // lê as posições 0xE000 e 0xE001 da FLASH e guarda em va e vb
  va = flash_read(0xE000);
  vb = flash_read(0xE001);
  // se va igual a 10 e vb igual a 20, acende o led
  if (va==10 && vb==20) PTBD_PTBD6 = 0;
  while (1); // fim do programa
}

MensagemEnviado: 24 Ago 2007 08:57
por KrafT
Vicente, arrumei o código pra vc, para que fique mais legivel.. blz?

MensagemEnviado: 24 Ago 2007 11:27
por Fábio Pereira
Você modificou o arquivo PRM para que o linker não utilize a página em 0xE000 para armazenar código ?

Os símbolos mFACCERR, mFPVIOL e mFCBEF estão definidos aonde ? Não encontrei eles no seu doonstack.asm.

Até +

MensagemEnviado: 24 Ago 2007 22:21
por Budzinski
Sim,

Mudei para 0xE400, os simbolos símbolos mFACCERR, mFPVIOL e mFCBEF estão definidos no arquivo QG08.h do codewarrior...