Stránka 1 z 3
ATmega - problemek s eeprom
Napsal: 27 říj 2010, 11:19
od WLAB
Objevil se mi problemek pri praci s eeprom v ATmega128 (nebo ATmega128L).
SW je CodeVison C verze 1.24.9
Je tam nejaka restrikce pro praci s eeprom v cyklech? ASM vypada na prvni pohled dobre. V nize uvede casti kodu se ale zapisi se jen prvni 4 bajty, pak kod pokracuje dal. Kdyz za nej dam while(1); a nasledne vyctu eeprom jsou tam prave ty 4 bajty.... po te, co jsem jako "debug" zacal davat do pole i, maji hodnotu 01 02 03 04
--------------------------------
if(dac_first_eep) //first run after programming
{
unsigned int i;
dac_first_eep=0;
for(i=1;i<DAC_CALTABLE_LEN;i++) //start at index 1
{
dac_cal_data_eep
=i;//-128; //-128 = not set
}
}
------------------------------------------
dac_cal_data_eep je:
eeprom char dac_cal_data_eep[DAC_CALTABLE_LEN];
DAC_CALTABLE_LEN je:
#define DAC_CALTABLE_LEN 3000
Napsal: 27 říj 2010, 13:29
od Galileo
Ukládáš unsigned int do charu takže do eeprom se ti uloží jen spodni byte proměnne i ,ale jinak to musi chodit, v AVrku mi ten kód naplnil všech 3000 byte eeprom, možná bude chyba jinde ....
Napsal: 27 říj 2010, 13:55
od WLAB
Ze davam uint do charu vim, to je tam jen jako "debug", abych alespon malinko vedel, co se tam deje, normalne se tam ma ukladat ta "-128" (0x80)....
Krom toho se mi zda, ze nechodi radne ani jine operace s eeprom vykovanane v cyklu.....
Nemam ted zadny napad co s tim.
Jeste mne napadlo, ze je tam prvadepodobne Atmega128L na 5V@16MHz, nikdy jsem ale problem s L verzi na 5V@16MHz nemel.
Napsal: 27 říj 2010, 14:06
od Galileo
pokud máš povolenej watchdog tak ho zkus zakázat, jinak nevím, může ti tam přetékat proměnná, to umí dělat kouzla ,hoď sem toho kódu víc (pokud to není tajný)
![Wink :wink:](./images/smilies/icon_wink.gif)
mrknem a uvidíme
Napsal: 27 říj 2010, 14:17
od WLAB
WDT je zakazano. Tohle je na zacatku - inicializace v mainu, dal ten program bezi celkem normalne (az na ty eep operace) nerestartuje se, nepada....
Kod tajny neni, ale ma asi 1500 radek bez knihoven, coz je problem... udelam vyber relevantnich casti. Taky jemozny, ze je to nejaka trapna bota, pac je to kod psany po nocich
![Very Happy :D](./images/smilies/icon_biggrin.gif)
.
Necituj pořád celý bezprostředně předcházející příspěvek, když je zjevné, že na něj odpovídáš, prosím.
Hill
Napsal: 27 říj 2010, 14:30
od WLAB
void main()
{
unsigned char tmp;
mode=MODE_NORM;
input_data_valid=0;
DAC_MPC=DAC_MPC_eep;
DAC_ADC=DAC_ADC_eep;
input_data_sscnt=INPUT_DATA_SSVAL;
SPI_busy=0;
MCU_init();
//RS485_init();
DACLR;
SWT_init();
indicate_init();
DAUNCLR;
*( ( (unsigned char*)(&input_data_tmp) )+0 )=~PINA;
*( ( (unsigned char*)(&input_data_tmp) )+1 )=(~PINC&0x3f);
input_data_valid=1;
input_data=input_data_tmp;
input_data_old=input_data_tmp;
dac_cal_state=dac_cal_state_eep;
if(dac_first_eep) //prvni beh po naprogramovani
{
unsigned int i;
dac_first_eep=0;
for(i=1;i<DAC_CALTABLE_LEN;i++)
{
dac_cal_data_eep=i;//-128; //-128 = not set
}
}
/*->*/ while(1); //<- kdyz necham zde zaseknout a vyctu eep, jsou tam jen ty 4 bajty
#asm("sei")
LED2_on;LED1_off;LED0_off;LED3_off;
...................................
MCU_init() je funkce obsahujici nastaveni z CodeVision Wizardu
void indicate_init()
{
SWT_timset(TIM_IND,0);
SWT_timset(TIM_IND_TOTAL,0);
SWT_timstart(TIM_IND);
SWT_timstart(TIM_IND_TOTAL);
}
SWT_init() je fce z knihovny, dle pdmineneho prekladu je to nyni zcela prazdna fce
void SWT_timset(unsigned char timer, unsigned int val)
{
#asm("in r30,SREG");
#asm("push r30");
#asm("cli");
SWT_SWTVAL[timer]=val;
#asm("pop r30");
#asm("out SREG,r30");
}
void SWT_timstart(unsigned char timer)
{
#asm("in r30,SREG");
#asm("push r30");
#asm("cli");
SWT_SWTDIR[timer]=-1;
#asm("pop r30");
#asm("out SREG,r30");
}
staticka pole knihovny:
char SWT_SWTDIR[SWT_TIMERS];
unsigned int SWT_SWTVAL[SWT_TIMERS];
---------------------------------------------------
nic jineho se do toho while(1) nevola
Napsal: 27 říj 2010, 18:23
od Galileo
A co to zkusit v té smyčce for po zápisu do eeprom trošku pozdžet
for(i=1;i<DAC_CALTABLE_LEN;i++)
{
dac_cal_data_eep=i;//-128; //-128 = not set
delay_us(100);
}
Napsal: 27 říj 2010, 20:23
od WLAB
To uz jsem zkousel take.... marne. V asm je ale videt, ze se testuje pripravenost eepromky.
Uz mne proste nic neapada. Krom spatne eep, ale chip je novy a do jinych mist lze psat.
Napsal: 27 říj 2010, 20:52
od Andrea
V tom asm by také mělo být vidět, za jakých okolností to ten cyklus může opustit. Přerušení máš zakázaná (máš?), watchdog taky, tak do toho nemůže nic zasahovat.
Napsal: 27 říj 2010, 21:01
od WLAB
Opusti ho to pri i=3000... Alespon, co jsem si zhluboke noci pamatuji...
tady jsem to nasel:
0009de e0e0 LDI R30,LOW(0)
0009df e0a8 LDI R26,LOW(_dac_first_eep)
0009e0 e0b0 LDI R27,HIGH(_dac_first_eep)
0009e1 940e 0bbe CALL __EEPROMWRB
; 1044 for(i=1;i<DAC_CALTABLE_LEN;i++)
0009e3 e0e1 LDI R30,LOW(1)
0009e4 e0f0 LDI R31,HIGH(1)
0009e5 83e8 ST Y,R30
0009e6 83f9 STD Y+1,R31
_0xA6:
0009e7 81a8 LD R26,Y
0009e8 81b9 LDD R27,Y+1
0009e9 3ba8 CPI R26,LOW(0xBB8)
0009ea e0eb LDI R30,HIGH(0xBB8)
0009eb 07be CPC R27,R30
0009ec f450 BRSH _0xA7
; 1045 {
; 1046 dac_cal_data_eep=i;//-128; //-128 = not set
0009ed 5fa7 SUBI R26,LOW(-_dac_cal_data_eep)
0009ee 4fbf SBCI R27,HIGH(-_dac_cal_data_eep)
0009ef 81e8 LD R30,Y
0009f0 81f9 LDD R31,Y+1
0009f1 940e 0bbe CALL __EEPROMWRB
; 1047 }
0009f3 9631 ADIW R30,1
0009f4 83e8 ST Y,R30
0009f5 83f9 STD Y+1,R31
0009f6 cff0 RJMP _0xA6
Napsal: 27 říj 2010, 21:16
od Andrea
Funkce __EEPROMWRB by se tam taky našla?
Napsal: 27 říj 2010, 21:46
od WLAB
Jasne... ve 3 v noci vypadala ok.
__EEPROMWRB:
000bbe 99e1 SBIC EECR,EEWE
000bbf cffe RJMP __EEPROMWRB
000bc0 b79f IN R25,SREG
000bc1 94f8 CLI
000bc2 bbae OUT EEARL,R26
000bc3 bbbf OUT EEARH,R27
000bc4 9ae0 SBI EECR,EERE
000bc5 b38d IN R24,EEDR
000bc6 17e8 CP R30,R24
000bc7 f019 BREQ __EEPROMWRB0
000bc8 bbed OUT EEDR,R30
000bc9 9ae2 SBI EECR,EEMWE
000bca 9ae1 SBI EECR,EEWE
__EEPROMWRB0:
000bcb bf9f OUT SREG,R25
000bcc 9508 RET
Napsal: 27 říj 2010, 23:02
od WLAB
zkusebne jsem odstranil veskery kod pred tou smyckou - beze zmeny. Vetsinou jsou zapsane 4 bajty, obcas 6. Leda, ze by to codevision spatne nacital...
jeste se ponorim do toho asmu...
Zkouska na druhem, identickem kusu, se stejnym vysledkem...
Zajimave zjisteni, kdyz ve vyctene eeprom upravim dac_first_eep na nenulovou hodnotu, coz zapricini novy beh smycky po resetu a poslu to zpet do mcu, tak vzdy skoncim o cca 4 bajty dal.... zapisova fce eepromwrb neprovadi zapis, pokud jsou data shodna, takze se provedou jen ty cca 4 dalsi zapisy....
dalsi poznatek: umistenim
for(i=65535;i;i--);
pred prvni zapis do eep problem zmizi.
aha, tak jeste upresneni - cekani treba vlozit mezi testovani flagu dac_first_eep v ifu a jeho nulovani, nebo toto nulovani zrusit, takze se zda, ze cteni nasledovane relativne bezprostrednim zapisem do toho sameho mista tomu dela nejak spatne...
![Shocked 8O](./images/smilies/icon_eek.gif)
A zpozdeni vyse uvedenym cyklem je na hranici, ponevadz, kdyz se pouzije misto "i" jiny int ktery je alokovan v registrech a operuje se s nim tudiz rychleji, tak uz to nestaci a zas to nefunguje.....
Napsal: 28 říj 2010, 08:55
od Andrea
WLAB píše: takze se zda, ze cteni nasledovane relativne bezprostrednim zapisem do toho sameho mista tomu dela nejak spatne.
To je divný, vždyť přesně totéž dělá ta fce __EEPROMWRB, přečte a při neshodě zapíše.
Napsal: 28 říj 2010, 11:31
od WLAB
Ano a krom toho read-modify-write obvykle funguje bez problemu....
nejak mi dosly napady
v okamziku, kdy to selhava, smycka rychle dobehne, zadne cekani, az eeprom zapise se tedy nedeje.