ATM32 strange behavior - Page 1
Forum section: electronics / general

author: bernie79
author_rank: Contributor
timestamp: September 30, 2021, 11:43:56 pm
content: 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?GreetingsBernie79Below is the shortened Code: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=0rjmp RESET ; 1 Reset Handlerreti ;rjmp EXT_INT0 ; 2 INT0 Handlerreti ;rjmp EXT_INT1 ; 3 INT1 Handlerreti ;rjmp EXT_INT2 ; 4 INT2 Handlerreti ;rjmp TIM2_COMP ; 5 Timer2 Compare Handlerreti ;rjmp TIM2_OVF ; 6 Timer2 Overflow Handlerreti ;rjmp TIM1_CAPT ; 7 Timer1 Capture Handlerreti ;rjmp TIM1_COMPA ; 8 Timer1 CompareA Handlerreti ;rjmp TIM1_COMPB ; 9 Timer1 CompareB Handlerreti ;rjmp TIM1_OVF ; 10 Timer1 Overflow Handlerreti ;rjmp TIM0_COMP ; 11 Timer0 Compare Handlerreti ;rjmp TIM0_OVF ; 12 Timer0 Overflow Handlerreti ;rjmp SPI_STC ; 13 SPI Transfer Complete Handlerreti ;rjmp USART_RXC ; 14 USART RX Complete Handlerreti ;rjmp USART_UDRE ; 15 UDR Empty Handlerreti ;rjmp USART_TXC ; 16 USART TX Complete Handlerreti ;rjmp ADC ; 17 ADC Conversion Complete Handlerreti ;rjmp EE_RDY ; 18 EEPROM Ready Handlerreti ;rjmp ANA_COMP ; 19 Analog Comparator Handler; twi on atmega8=18, on atmega32=20rjmp TWSI; 20 Two-wire Serial Interface Handlerreti ;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 initout SPL, aldi a, HIGH(RAMEND)out SPH, a; PORT B + D all outputldi a, 0b11111111out DDRB, aout PORTB,aout DDRD, aout PORTD,a; PORT C all inputclr aout DDRC,arcall TWI_INI ; TWI INIT; STARTvaluesclr bldi b,0x11seiLOOP:rcall ente ;*** this insert works;nop ;**;nop ;**rjmp LOOP.org 0x0060; #############################################################################; TWI int-serviceroutineTWSI: noppush ain a,SREGpush ain a, TWSR; read Status-Registerandi a, 0xF8cpi a, TW_SR_SLA_ACK; x60breq TWSI_TW_SR_SLA_ACKcpi a, TW_SR_ARB_LOST_SLA_ACK; x68breq TWSI_TW_SR_ARB_LOST_SLA_ACKcpi a, TW_SR_GCALL_ACK; x70breq ....;proofed ISR for I2C, works this way on many Mega8 before, works also here.....pop aout SREG,Apop areti;---------------------------------;the Workload for the Main Loop. very simple but with a rcall to check Stack integrity:;---------------------------------ente:ldi e, 5clr dclr cente2:deccbrneente2decdbrneente2decebrneente2out PORTB,fdec fret

author: T3sl4co1l
author_rank: Super Contributor
timestamp: October 01, 2021, 07:11:33 am
content: Read the output listing?Tim

author: Alti
author_rank: Frequent Contributor
timestamp: October 01, 2021, 07:48:58 am
content: This chip has JTAG, you can debug the code.

author: westfw
author_rank: Super Contributor
timestamp: October 01, 2021, 09:58:52 am
content: Mega32 has 4 byte isr vectors, but you’ve tried to fill it with two byte instructions.

author: bernie79
author_rank: Contributor
timestamp: October 01, 2021, 12:01:58 pm
content: @T3sl4co1l:You are talking about the output on the TWI-pins or the output of the diag-LEDs on PORTB?The LEDs showing the expected pattern on PortB. A logic analyser shows the incoming data and clock from the Master, and the correct answer from this slave (or no reaction in case of code changes). So this all clears doubts of the watched behavior but gives no new information.@AltiYes, but I dont have a Jtag debugger. Until now, there was no need. All projects in the past could worked out without this. Maybe its time for a shopping tour.@westfwI take a look in the datasheet:https://ww1.microchip.com/downloads/en/DeviceDoc/ATmega32A-DataSheet-Complete-DS40002072A.pdfThe interrupt vector table on page 51 also lists the absolute adresses of each vector and on the next page is an example vector list. you are right, its 4 byte for each vector. Putting the same page of a ATmega8 next to it, there is a slight difference: the absolute addresses. The ATMega8 has 2 byte for each vector.To justify the vector table I could use many .org declarations or I can add a nop after each reti, but to have the code nice readable, I did this:Code:.cseg;start of code-segment.org 0;start adr=0jmp RESET ; 1 Reset Handlerjmp NOTUSED ;jmp EXT_INT0 ; 2 INT0 Handlerjmp NOTUSED ;jmp EXT_INT1 ; 3 INT1 Handlerjmp NOTUSED ;jmp EXT_INT2 ; 4 INT2 Handlerjmp NOTUSED ;jmp TIM2_COMP ; 5 Timer2 Compare Handlerjmp NOTUSED ;jmp TIM2_OVF ; 6 Timer2 Overflow Handlerjmp NOTUSED ;jmp TIM1_CAPT ; 7 Timer1 Capture Handlerjmp NOTUSED ;jmp TIM1_COMPA ; 8 Timer1 CompareA Handlerjmp NOTUSED ;jmp TIM1_COMPB ; 9 Timer1 CompareB Handlerjmp NOTUSED ;jmp TIM1_OVF ; 10 Timer1 Overflow Handlerjmp NOTUSED ;jmp TIM0_COMP ; 11 Timer0 Compare Handlerjmp NOTUSED ;jmp TIM0_OVF ; 12 Timer0 Overflow Handlerjmp NOTUSED ;jmp SPI_STC ; 13 SPI Transfer Complete Handlerjmp NOTUSED ;jmp USART_RXC ; 14 USART RX Complete Handlerjmp NOTUSED ;jmp USART_UDRE ; 15 UDR Empty Handlerjmp NOTUSED ;jmp USART_TXC ; 16 USART TX Complete Handlerjmp NOTUSED ;jmp ADC ; 17 ADC Conversion Complete Handlerjmp NOTUSED ;jmp EE_RDY ; 18 EEPROM Ready Handlerjmp NOTUSED ;jmp ANA_COMP ; 19 Analog Comparator Handlerjmp TWSI; 20 Two-wire Serial Interface Handlerjmp NOTUSED ;jmp SPM_RDY ; 21 Store Program Memory Ready Handler;rjmp ente;reti; twi on atmega8=18 on atmega32=20;nop.db "v0.0001";.org 0x0020NOTUSED: reti ;Dummy ISR routine for not used int vectors.RESET:;rjmp Reset2;nop;Reset2:ldi a, LOW(RAMEND) ;STACK initout SPL, aldi a, HIGH(RAMEND)out SPH, a......and it works! (even the .db part). I should have read the data sheet more carefully.Thanks @westfw.There is the golden rule again: "If you get stuck on a problem, you need another fresh point of view!".And thanks to T3sl4co1l and Alti for trying to provide a another point of view.GreetingsBernie79

author: westfw
author_rank: Super Contributor
timestamp: October 01, 2021, 08:31:06 pm
content: Quoteyou're welcome. I find it particularly rewarding when a brief comment like mine is sufficient for the OP to fix their problem.QuoteIndeed!