Hi guys,
I'm trying to wrap my head around an strange behavior of a ATmega32A.
The AVR sits on a board like this:
https://www.aliexpress.com/item/872521098.html (but bought 1 year before from a serious Dealer).
Its my first test drive with a Atmega32, usually Im working with the smaller ones (Mega8, Tinys) or take ARMs (STM32, AT90SAM..), so "I can spell MCU"
.
I try to build up a I2C slave, and get strange results. So I have taken an proofed TWI Slave code,
and put this in the chip. Without any big changes, and an almost empty main loop, the I2C slave works: takes values, puts them in register a and answers I2C-readings with register b. To see a main loop running, I count slowly a register f down and put this on PORTB. This works too.
But if add any instruction - even a Nop in the start code (I tried to insert several things, examples are the lines with **), the Interrput Service Routine doesnt work, but the main loop works.
Even if I insert something like
.DB "test", it breaks the running of the ISR. But I could insert the "rcall ente" with leaving the ISR running.
For test reasons, I have also set up the ISR (TWSI) on a certain well defined adress, (.org 0x0060), so the Insert of any byte doesnt cause a move of TWSI. (strangely, this doesnt work with RESET and .org 0x0020).
I thougt of absolute addresses mixup, but there is no absolute address. RJMP too far is also not the case, (its about 300 bytes for all).
Fuses are also okay (high=E4, low =D9), pretty standard: Internal 8MHZ Osc, Jtag disabled, Boot at 0x0000, no Sleep etc). the Int vector is also in the right place (0x0026, checked in the hex file). If the ISR runs, it runs every time I call from the master. even after a power cycle. If it doesnt work, its works never. So no random start condition or similar.
The Chip gets programmed with an USBASP (that works too, checked with another ATMega8). The Assembler in use is AVR Studio 4.18 SP1 with AVR Simulator2. (Simulation works too, but the TWI Int cannot be simulated).
The I2C-Master is a Raspi, clocked with 100Khz SCL (checked with Logic analyzer).
Unfortunately, this is the only ATmega32/16 I have at hands. but I'm now suspect a faulty chip. Before I sit myself down to rewrite this to a Mega8 just for test proposes, I want to ask, if anyone has had similar behavior seen before, or you can point to things I havent watched?
Has anyone an idea?
Greetings
Bernie79
Below is the shortened Code:
; Based on: TWI I2C SLAVE
; 10/2005 (c) Bernhard.Erfurt
; Freq=1.0 MHZ internal (Fuses: E4,D9)
; tested example
.include "m32Adef.inc"
; TWI Slave Receiver Codes
.equ TW_SR_SLA_ACK = 0x60; x60 (SLA+W recv-ACK send)
.equ TW_SR_ARB_LOST_SLA_ACK = 0x68; x68 (ArbLost in SLA+R/W as MASTER; SLA+W recv; ACK send
.equ TW_SR_GCALL_ACK = 0x70; x70 (GenAdr recv; ACK send
.equ TW_SR_ARB_LOST_GCALL_ACK=0x78; x78 (ArbLost in SLA+R/W as MASTER;GenAdr recv; ACK send
.equ TW_SR_DATA_ACK = 0x80; x80 (preAdr (SLA+W) Data recv; ACK send
.equ TW_SR_DATA_NACK = 0x88; x88 (preAdr (SLA+W) Data recv; NACK send
.equ TW_SR_GCALL_DATA_ACK = 0x90; x90 (preAdr (Gencall) Data recv; ACK send
.equ TW_SR_GCALL_DATA_NACK = 0x98; x98 (preAdr (Gencall) Data recv; NACK send
.equ TW_SR_STOP = 0xA0; xA0 (STOP recv, or repStart)
; TWI Slave Transmitter Codes
.equ TW_ST_SLA_ACK = 0xA8; xA8 (SLA+R recv; ACK send)
.equ TW_ST_ARB_LOST_SLA_ACK = 0xB0; xB0 (ArbLost SLA+R/W as MASTER, ACK send)
.equ TW_ST_DATA_ACK = 0xB8; xB8 (TWDR send ACK recv
.equ TW_ST_DATA_NACK = 0xC0; xC0 (TWDR send NACK recv
.equ TW_ST_LAST_DATA = 0xC8; xC8 (Last byte in TWDR send (TWEA = "0"); Ack recv
.equ TW_NO_INFO = 0xF8; xF8 (No Statinfo; TWINT = "0"; idle
.equ TW_BUS_ERROR = 0x00; x00 (Bus-Error:invalid START or STOP cond.; idle
; TWI SLAVE settings
.equ TWI_SLAVE_ADRESSE = 0x2e ; own SLAVE ADR 1...127
.equ TWI_GENERAL_CALL_enable = 0 ; 1=General Call enabled / 0=disabled
; REGISTER
.DEF a = R16 ; Universalregister wo Int
.DEF b = R17 ; Universalregister at Int
.DEF c = R18 ; Flagregister, Bit 0=ADC done
.DEF d = R19 ; Bitlevel-Counter for ADC
.DEF e = R24 ; Cycle Counter for ADC, LSB
.DEF f = R25 ; sreg
.cseg ;Start of Code-Segment
.org 0 ;start adrress=0
rjmp RESET ; 1 Reset Handler
reti ;rjmp EXT_INT0 ; 2 INT0 Handler
reti ;rjmp EXT_INT1 ; 3 INT1 Handler
reti ;rjmp EXT_INT2 ; 4 INT2 Handler
reti ;rjmp TIM2_COMP ; 5 Timer2 Compare Handler
reti ;rjmp TIM2_OVF ; 6 Timer2 Overflow Handler
reti ;rjmp TIM1_CAPT ; 7 Timer1 Capture Handler
reti ;rjmp TIM1_COMPA ; 8 Timer1 CompareA Handler
reti ;rjmp TIM1_COMPB ; 9 Timer1 CompareB Handler
reti ;rjmp TIM1_OVF ; 10 Timer1 Overflow Handler
reti ;rjmp TIM0_COMP ; 11 Timer0 Compare Handler
reti ;rjmp TIM0_OVF ; 12 Timer0 Overflow Handler
reti ;rjmp SPI_STC ; 13 SPI Transfer Complete Handler
reti ;rjmp USART_RXC ; 14 USART RX Complete Handler
reti ;rjmp USART_UDRE ; 15 UDR Empty Handler
reti ;rjmp USART_TXC ; 16 USART TX Complete Handler
reti ;rjmp ADC ; 17 ADC Conversion Complete Handler
reti ;rjmp EE_RDY ; 18 EEPROM Ready Handler
reti ;rjmp ANA_COMP ; 19 Analog Comparator Handler
; twi on atmega8=18, on atmega32=20
rjmp TWSI ; 20 Two-wire Serial Interface Handler
reti ;rjmp SPM_RDY ; 21 Store Program Memory Ready Handler
;rcall ente ;**
;reti ;**
;nop ;**
;.db "v0.0001" ;**
;.org 0x0020 ;**
RESET:
;rjmp Reset2 ;**
;nop ;**
;Reset2:
ldi a, LOW(RAMEND) ;STACK init
out SPL, a
ldi a, HIGH(RAMEND)
out SPH, a
; PORT B + D all output
ldi a, 0b11111111
out DDRB, a
out PORTB,a
out DDRD, a
out PORTD,a
; PORT C all input
clr a
out DDRC,a
rcall TWI_INI ; TWI INIT
; STARTvalues
clr b
ldi b,0x11
sei
LOOP:
rcall ente ;*** this insert works
; nop ;**
; nop ;**
rjmp LOOP
.org 0x0060
; #############################################################################
; TWI int-serviceroutine
TWSI: nop
push a
in a,SREG
push a
in a, TWSR ; read Status-Register
andi a, 0xF8
cpi a, TW_SR_SLA_ACK ; x60
breq TWSI_TW_SR_SLA_ACK
cpi a, TW_SR_ARB_LOST_SLA_ACK ; x68
breq TWSI_TW_SR_ARB_LOST_SLA_ACK
cpi a, TW_SR_GCALL_ACK ; x70
breq ....
;proofed ISR for I2C, works this way on many Mega8 before, works also here.
....
pop a
out SREG,A
pop a
reti
;---------------------------------
;the Workload for the Main Loop. very simple but with a rcall to check Stack integrity:
;---------------------------------
ente:
ldi e, 5
clr d
clr c
ente2:
dec c
brne ente2
dec d
brne ente2
dec e
brne ente2
out PORTB,f
dec f
ret