ask for code testing (asm for ATmega328p)

Go To Last Post
10 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I wrote an asm program for Atmega328P, so the OCR0A is connected to PD6, and OCR0B to PD5.

 

In attachment is my code, the first one: code-10-27-good goes well.

 

Second one: code-10-28-test1 is to create a pwm effect on led connected to PD6, it doesn't work, seemingly the timer0 Overflow Interrupt not work properly.

 

To find out what's going wrong, I tried the third one: code-10-28-test3, to toggle a led connected into PB0, it not work either.

 

The timer0 Overflow interrupt not work as desired.

 

Anyone know what's wrong with it?

Attachment(s): 

This topic has a solution.
Last Edited: Thu. Oct 29, 2020 - 12:40 PM
This reply has been marked as the solution. 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Your list of ISR table is screwed up  for 328 you should use JMP , NOT reti in your long list of isrs.... JMP is 2 words, reti only 1 word, throwing everything out of sync.  or you could put some different 2 word command there, you MUST use 2 words

 

With the addresses all messed up  you are not getting to the correct ISR.  

 

Keep simple and use jmp  ...not you don't have to use the entire list, only from beginning to up to the last IRQ you are actually using.

 

USE JMP!!!!

0x0006 jmp PCINT0 ; PCINT0 Handler   ;note your list MUST start with reset , not with this one, i just did a partial paste.
0x0008 jmp PCINT1 ; PCINT1 Handler
0x000A jmp PCINT2 ; PCINT2 Handler
0x000C jmp WDT ; Watchdog Timer Handler
0x000E jmp TIM2_COMPA ; Timer2 Compare A Handler
0x0010 jmp TIM2_COMPB ; Timer2 Compare B Handler
0x0012 jmp TIM2_OVF ; Timer2 Overflow Handler
0x0014 jmp TIM1_CAPT ; Timer1 Capture Handler
0x0016 jmp TIM1_COMPA ; Timer1 Compare A Handler

ETC

PCINT1:

PCINT2:

;;;    WDT: Commented out, using this irq !!

TIM2_COMPA:

TIM2_COMPB:

TIM2_OVF:

TIM1_CAPT:

etc

nop

abc: rjmp abc  ;do nothing stay here forever :( 

 

 

WDT:  PUSH XL

          MOV XL, SREG   ;IMPORTANT!!!

          PUSH XL

          ADD DOG, CAT

         

JMP!!!

https://www.youtube.com/watch?v=...

 

 

 

 

 

 

When in the dark remember-the future looks brighter than ever.   I look forward to being able to predict the future!

Last Edited: Thu. Oct 29, 2020 - 04:11 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

There was a "nop" between the last "etc" and "abc:", is it necessary?

 

and, the last "JMP" hasn't destination, is that OK? or maybe as your syntax, it ought to be: "JMP ;;;"?

Last Edited: Thu. Oct 29, 2020 - 09:24 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Note that m328pdef.inc contains:

; ***** INTERRUPT VECTORS ************************************************
.equ	INT0addr	= 0x0002	; External Interrupt Request 0
.equ	INT1addr	= 0x0004	; External Interrupt Request 1
.equ	PCI0addr	= 0x0006	; Pin Change Interrupt Request 0
.equ	PCI1addr	= 0x0008	; Pin Change Interrupt Request 0
.equ	PCI2addr	= 0x000a	; Pin Change Interrupt Request 1
.equ	WDTaddr	= 0x000c	; Watchdog Time-out Interrupt
.equ	OC2Aaddr	= 0x000e	; Timer/Counter2 Compare Match A
.equ	OC2Baddr	= 0x0010	; Timer/Counter2 Compare Match A
.equ	OVF2addr	= 0x0012	; Timer/Counter2 Overflow
.equ	ICP1addr	= 0x0014	; Timer/Counter1 Capture Event
.equ	OC1Aaddr	= 0x0016	; Timer/Counter1 Compare Match A
.equ	OC1Baddr	= 0x0018	; Timer/Counter1 Compare Match B
.equ	OVF1addr	= 0x001a	; Timer/Counter1 Overflow
.equ	OC0Aaddr	= 0x001c	; TimerCounter0 Compare Match A
.equ	OC0Baddr	= 0x001e	; TimerCounter0 Compare Match B
.equ	OVF0addr	= 0x0020	; Timer/Couner0 Overflow
.equ	SPIaddr	= 0x0022	; SPI Serial Transfer Complete
.equ	URXCaddr	= 0x0024	; USART Rx Complete
.equ	UDREaddr	= 0x0026	; USART, Data Register Empty
.equ	UTXCaddr	= 0x0028	; USART Tx Complete
.equ	ADCCaddr	= 0x002a	; ADC Conversion Complete
.equ	ERDYaddr	= 0x002c	; EEPROM Ready
.equ	ACIaddr	= 0x002e	; Analog Comparator
.equ	TWIaddr	= 0x0030	; Two-wire Serial Interface
.equ	SPMRaddr	= 0x0032	; Store Program Memory Read

The idea here is that instead of something like:

.cseg
.org 0x00
rjmp START; reset
reti; INT0
reti; INT1
reti; PCINT0
reti; PCINT1
reti; PCINT2
reti; WDT
reti; TIMER2 COMPA
reti; TIMER2 COMPB
reti; TIMER2 OVF
reti; TIMER1 CAPT
reti; TIMER1 COMPA
reti; TIMER1 COMPB
reti; TIMER1 OVF
reti; TIMER0 COMPA
reti; TIMER0 COMPB
rjmp Tc0Isr0; TIMER0 OVF
reti; SPI,STC
reti; USART,RX
reti; USART,UDRE
reti; USART,TX
reti; ADC
reti; EE READY
reti; ANALOG COMP
reti; TWI
reti; SPM READY
;

START:

You could use:

.cseg
.org 0x00
rjmp START; reset

.org OVF0addr
rjmp Tc0Isr0; TIMER0 OVF

START:

If you do it this way START will be positioned immediately after the last vector you are using (so it's "on top" of the vectors for SPI, URXC etc). If there's some reason you want to waste the space to position it "after" the entire vector table you could do something like:

.cseg
.org 0x00
rjmp START; reset

.org OVF0addr
rjmp Tc0Isr0; TIMER0 OVF

.org INT_VECTORS_SIZE
START:

If you now come back to this code and want to add use of the WDT interrupt (say) you could simply then add:

.cseg
.org 0x00
rjmp START; reset

.org WDTaddr
.rjmp WDT_handler

.org OVF0addr
rjmp Tc0Isr0; TIMER0 OVF

.org INT_VECTORS_SIZE
START:

etc etc.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

There was a "nop" between the last "etc" and "abc:", is it necessary?

NO, however you should be able to answer that yourself---get more practice & it will soon go easy!

 

JMP!!! JMP!!!

https://www.youtube.com/watch?v=...

 

Hope you enjoyed it

 

its very simple...the lower chips use a 1 word separation (rjmp) between each vector table location, the higher chips like 328 require 2 words.  So you must use jmp (not  rjmp)

 or nop nop...something to fill 2 spots.  reti only fills one spot & that is your problem.  

 

low end chips

vect A  rjmp 1

vect B  rjmp 2

vect C  rjmp 3   ...perfection

...

 

328 chips

vect A rjmp 1

vect A rjmp 2

vect B rjmp 3

vect B

vect C

vect C

....SEE ALL MESSED UP!!

 

328 chips

vect A jmp 1

vect A jmp 1

vect B jmp 2

vect B jmp 2

vect C jmp 3

vect C jmp 3  ...perfection

    if you don't want to use B...you have 2 spots to fill!!

 

 

As clawson points out if you don't feel like filling in all these vector table spots, you can grab only the addresses  needed and just fill in those need spots with either code or rjmp, or jmp.  Really, code can only go after the last one in the list you wish to use (you can't put useful code between, say, the 3rd and 5th vector table location).  Any table spots you skip filling still have something in them, regardless.  After the last spot you use, any remaining vector spots can have code instead of vector info--so it's less waste of unused space.

 

 

 

When in the dark remember-the future looks brighter than ever.   I look forward to being able to predict the future!

Last Edited: Thu. Oct 29, 2020 - 10:20 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

I don't know your background but here are some info that should make it more clear:

 

The AVR don't have at ISR vector table with pointers, but start running code at a specific place.

now Atmel (today I guess I should say the designers) have put them in the beginning of the memory next to each other

so they take up the least amount of flash.

Now come the problem is how big should the space between them be. And that is to be able to jump out to any place where 

the code can be.

On chips with 8K of flash or less rjmp (that is a 1 word instruction) can reach the entire flash, but for chips like the 328 you need

a jmp (that is a 2 word instruction) to do that, so there is the double spacing.   

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks, this problem has been solved on your solutions, now there is another problem I found when I debugged this program in Atmel Studio 7.0:

 

code:

START:
ldi regCommon, LOW(RAMEND)		; init stackpointer
out SPL, regCommon
ldi regCommon, HIGH(RAMEND)
out SPH, regCommon

but, I watch the address of SPL and SPH (0x3D and 0x3E), it was always "00 00", not as I expected "08FF", why?

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

MianQi wrote:
but, I watch the address of SPL and SPH (0x3D and 0x3E),
Be careful as there two views of memory - one offset by 0x20 (the size of the 32 CPu registers) from the other. So IO addres 3D/3E would also appear as RAM addresses 5D/5E so if you are not seeing anything at 3D/3E in the view you are looking at take a look at 5D/5E instead.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

MianQi wrote:
this problem has been solved

Jolly good! So please mark the solution - see Tip #5 in my signature, below, for instructions.

 

 

now there is another problem

If it's a different problem, start a new thread 

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

sparrow2 wrote:

I don't know your background...   

 

I just shifted from Arduino, and I want to use avr-libc, but I found that knowing asm for ATmega is critical, so I learned tutorials here:http://www.avr-asm-tutorial.net/...

it is excellent, but the author used ATiny13, I used ATmega328p, so there was some difference and difficulty.

 

Have anyone here recommend tutorials suitable for me?