AVR Assembly Language Programming

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

Is there a forum dedicated to AVR assembly programming?

 

AVR assembly is how I amuse myself - I say this because I don't want to be caught in the Assembly vs C debate. I'm looking for a place where AVR ASM freaks can share ideas/experience.

 

I'm using Atmel Studio with the Atmel ICE, AVR Dragon, STK600 (plus too many attachments), a gaggle of Xplained boards, and a whole herd of tiny, mega, and xmega chips. I've come a long way in the last five years but, with the exception of a few books, I'm learning in a vacuum. Data sheets provide a few tidbits. I've read a great many of them. App notes, though, seem to be exclusively C, which is really too bad.

 

Sure, building code techniques from the ground up can be very interesting. At some point, though, I'd like to check my answer.

 

If you are still with me, I'll attempt to add a small function from a larger Xmega32E5 TWI section. When combined with the whole, it works fine. But I do wonder how someone else would do it.

 

; TwiWr_Wait                                                          21May2020
; -----------------------------------------------------------------------------
; Description:
;     Waits for MSTATUS.WIF to be set. Checks ARBLOST, BUSERR, and RXACK, and
;     then returns SREG_T to indicate success (0) or error (1).
;
;     Success is defined as:
;         - WIF     = 1, and
;         - ARBLOST = 0, and
;         - BUSERR  = 0, and
;         - RXACK   = 0 (ACK)
; Parameters:
;     None.
; General-Purpose Registers:
;     Parameters - 
;     Modified   - 
; Constants:
;     TWIM_WRFLAGS_bm    -  (0b_0001_1100)  RXACK, ARBLOST, and BUSERR flags
; Returns:
;     SREG_T - success (0) or error (1)
; Note:
;     If STATUS.WIF is never set, this function never returns.
;     Just so you know.
TwiWr_Wait:
    push   r16

TwiWr_Wait_wait:
    lds    r16,    TWIC_MASTER_STATUS       ; r16 = STATUS
    sbrs   r16,    TWI_MASTER_WIF_bp        ; if (WIF == 0)
    rjmp   TwiWr_Wait_wait                  ;     goto TwiWr_Wait_wait

    andi   r16,    TWIM_WRFLAGS_bm          ; if (WRFLAGS == 0)
    breq   TwiWr_Wait_exit                  ;     success: goto exit
                                            ; else
    set                                     ;     error: SREG_T = 1

TwiWr_Wait_exit:

    pop    r16
    ret

Oh, that's rude. The code editor didn't even have an ASM option.

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

clebell wrote:
Is there a forum dedicated to AVR assembly programming?

No, there isn't.

 

As it's specific to the target chip, probably best to post in the chip-specific forum.

 

Unless it's about Atmel Studio itself - there is a forum for that.

 

clebell wrote:
The code editor didn't even have an ASM option

Not to worry: it ignores whatever option you select anyhow - it all just comes out uniform green.

 

frown

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...
Last Edited: Thu. May 21, 2020 - 04:41 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

This is the only assembly code I've written in a long time, but I had fun doing it.  It is a function to output a WS2812 LED data stream on an AVR running at 8 MHz, which meant 10 clocks per data bit.  I post it here for your amusement.  BTW, the function is called output_grb because the WS2812, for reasons I cannot imagine, requires data in G-R-B order rather than the far-more-obvious R-G-B.

 


; This code is a function callable in C. In C the function declaration is
; extern void output_grb(u8 * ptr, u16 count)

;#define __SFR_OFFSET 0 

#include <avr/io.h> 

;extern void output_grb(u8 * ptr, u16 count)
;
; r18 = data byte
; r19 = 7-bit count
; r20 = 1 output
; r21 = 0 output
; r22 = SREG save
; r24:25 = 16-bit count
; r26:27 (X) = data pointer

.equ      OUTBIT,   0

.global output_grb
output_grb:
         movw   r26, r24      ;r26:27 = X = p_buf
         movw   r24, r22      ;r24:25 = count
         in     r22, SREG     ;save SREG (global int state)
         cli                  ;no interrupts from here on, we're cycle-counting
         in     r20, PORTB
         ori    r20, (1<<OUTBIT)         ;our '1' output
         in     r21, PORTB
         andi   r21, ~(1<<OUTBIT)        ;our '0' output
         ldi    r19, 7        ;7 bit counter (8th bit is different)
         ld     r18,X+        ;get first data byte
loop1:
         out    PORTB, r20    ; 1   +0 start of a bit pulse
         lsl    r18           ; 1   +1 next bit into C, MSB first
         brcs   L1            ; 1/2 +2 branch if 1
         out    PORTB, r21    ; 1   +3 end hi for '0' bit (3 clocks hi)
         nop                  ; 1   +4
         bst    r18, 7        ; 1   +5 save last bit of data for fast branching
         subi   r19, 1        ; 1   +6 how many more bits for this byte?
         breq   bit8          ; 1/2 +7 last bit, do differently
         rjmp   loop1         ; 2   +8, 10 total for 0 bit
L1:
         nop                  ; 1   +4
         bst    r18, 7        ; 1   +5 save last bit of data for fast branching
         subi   r19, 1        ; 1   +6 how many more bits for this byte
         out    PORTB, r21    ; 1   +7 end hi for '1' bit (7 clocks hi)
         brne   loop1         ; 2/1 +8 10 total for 1 bit (fall thru if last bit)
bit8:
         ldi    r19, 7        ; 1   +9 bit count for next byte
         out    PORTB, r20    ; 1   +0 start of a bit pulse
         brts   L2            ; 1/2 +1 branch if last bit is a 1
         nop                  ; 1   +2
         out    PORTB, r21    ; 1   +3 end hi for '0' bit (3 clocks hi)
         ld     r18, X+       ; 2   +4 fetch next byte
         sbiw   r24, 1        ; 2   +6 dec byte counter
         brne   loop1         ; 2   +8 loop back or return
         out    SREG, r22     ; restore global int flag
         ret
L2:
         ld     r18, X+       ; 2   +3 fetch next byte
         sbiw   r24, 1        ; 2   +5 dec byte counter
         out     PORTB, r21   ; 1   +7 end hi for '1' bit (7 clocks hi)
         brne   loop1         ; 2   +8 loop back or return
         out    SREG, r22     ; restore global int flag
         ret

 

Last Edited: Thu. May 21, 2020 - 05:56 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clebell  I don't notice any attempt to clear T-bit for an non-error return.

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

There are a few of us around that do ASM for fun.  We mostly just put up with people telling us to just use C and go do our own thing.

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

As you know , there are many ways to skin a cat.

 

Your code looks fine, and it don't break any unwritten rules :)

 

The comment of clear T in #4, T is used as an error flag and it's the error (and init) routines job to clear it.

 

I will say that it's normally the callers job to save used registers, so if R16 aren't used there is no need for push and pop. (you should normally have some registers routines just can use),

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

andrewm1973 wrote:

There are a few of us around that do ASM for fun.


I count myself among them, although I don't count myself as good at it ;-)

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

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

sparrow2 wrote:
The comment of clear T in #4, T is used as an error flag and it's the error (and init) routines job to clear it.

I respectfully disagree, but it matters not.

 

N.Winterbottom wrote:
clebell  I don't notice any attempt to clear T-bit for an non-error return.

I'm glad to see this bug fixed in the code you posted here: https://www.avrfreaks.net/comment/2922236#comment-2922236

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

Here is a fine & handy macro you can use...keep the ASM train rolling

 

example: 

     OutReg   ADCSRA, mydog

     nop

     nop

     InReg  mycat, TIMSK

.macro InReg
    .if @1 < 0x40
        in @0, @1
    .elif ((@1 >= 0x60) && (@1 < SRAM_START))
        lds @0,@1
    .else
       .error "InReg: Invalid I/O register address"
    .endif
.endmacro 

; usage: OutReg addr, reg
.macro OutReg
    .if @0 < 0x40
        out @0, @1
    .elif ((@0 >= 0x60) && (@0 < SRAM_START))
        sts @0,@1
    .else
       .error "OutReg: Invalid I/O register address"
    .endif
.endmacro

 

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

Last Edited: Thu. May 21, 2020 - 11:28 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

T is used as an error flag and it's the error (and init) routines job to clear it.

Like C's "errno" - it starts out at zero, and nothing sets it unless there is an error.  Somewhere in your program you check the value, and if it's non-zero you know that somewhere before then there was some sort of error.

 

I've actually thought about putting something like that in the Arduino core, probably using one of the gpio registers.  For a single instruction in the error path of the core functions, you could remember 8 different error conditions that you could print if the user called a "printErrors" function.  It wouldn't be much, but it might be a big help for certain classes of typical beginner mistakes.

 

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

I'd like to do assembly also.  I grew up assembly.  I  know just enough C to get into trouble, but I'm trying to learn more of it, as that seems to be the way of things.  I figure with assembly, I know the heart and soul of a chip and maybe not get it to do more, but maybe more control.   But it seems like it's easier to get larger programs done in C.

 

I noticed that about the app notes too, seems everything is in, or for C.

 

Right now, since I changed processors, I figure it's good time to learn both at the same time in a parallel path.   Should be an interesting trip.

Just gettin' started, again....

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

I recall PIC having few instructions (and registers), and thinking AVR had many. That was when I first starting looking at AVR's, to my thinking at the time AVR had to be a complex instruction set. I have been glancing at RISC-V, and it feels more familiar now. RISC-V has been brewing at Berkeley for decades I guess, so I am sort of thinking AVR was derived from Berkeley RISC-[I|II...]. Any thoughts on that?

 

update: add link

 

https://en.wikipedia.org/wiki/Berkeley_RISC

my projects: https://github.com/epccs

Debugging is harder than programming - don’t write code you can’t debug! https://www.avrfreaks.net/forum/help-it-doesnt-work

Last Edited: Fri. May 22, 2020 - 04:14 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

OldMicroGuy wrote:

I noticed that about the app notes too, seems everything is in, or for C.

Remember the AVR core was conceived of and designed in collaboration with compiler designers (IAR).  That's their bread and butter.

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

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

I grew up assembly.  I  know just enough C to get into trouble

+1 wink

John Samperi

Ampertronics Pty. Ltd.

www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

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

C can significantly speed your work up & lower aggravation the bulk of the time.  My beef, which I somewhat ignore, is I haven't found a good way to force it to use registers for priority variables.  Sometimes it seems dumb as a rock & something that is core to the entire program keeps getting sts'd & lds'd to death, when none of that is needed.  That's fine for a value that is used only occasionally. Put priority values in a register where it can have quick, easy access!  Same for flags, so they use sbir & sbic checks & sbr/sbc control, no roundabout manipulations.  Two registers can provide you 16 different flags (alarms, timer tickmarks, various statuses, etc).  Many times in asm, you barely use any ram at all, except for the stack.

On the other side of the coin, some complex things make you step back & say, daggone it, glad I did that in C.

 

 

 

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

Last Edited: Fri. May 22, 2020 - 03:14 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 3

avrcandies wrote:
My beef, which I somewhat ignore, is I haven't found a good way to force it to use registers for priority variables.

Again [referring to CLR], nothing to do with C.  Rather, it is your toolchain that has a certain model of code generation.  Repaint your post, replacing each complaint about C with the identity of the offending toolchain.

 

Also again, if your chosen toolchain is open-source then you have a direct path to what might please your eye.

 

avrcandies wrote:
Two registers can provide you 16 different flags

That has to do with the toolchain you have chosen.

 

As I suggested in the other thread, perhaps you should choose a toolchain that does not offend your eye that much.

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

Last Edited: Fri. May 22, 2020 - 12:28 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

theusch wrote:
choose a toolchain that does not offend your eye that much.

I suspect that offence to the eye and offence to the wallet are probably complementary ... ?

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

clebell wrote:
AVR assembly is how I amuse myself - I say this because I don't want to be caught in the Assembly vs C debate. I'm looking for a place where AVR ASM freaks can share ideas/experience.
This very forum is a good place to discuss Asm. Many of us here are "grey beards" (more so since covid!) and have done many years of Asm whatever we may have later moved on to. So I think many of us have a soft spot for getting to the real core of things (there's even examples of posters who've designed/built CPUs from TTL!). I don't think (with a few notable exceptions) you are going to get too many people telling you to ditch Asm and change to something else so post away.

 

Moderator

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

OT

#1 Hardware Problem? https://www.avrfreaks.net/forum/...

#2 Hardware Problem? Read AVR042.

#3 All grounds are not created equal

#4 Have you proved your chip is running at xxMHz?

#5 "If you think you need floating point to solve the problem then you don't understand the problem. If you really do need floating point then you have a problem you do not understand."

Last Edited: Fri. May 22, 2020 - 03:23 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

When OP said he was only interested in Asm and wasn't interested in discussing C I wonder if it might be an idea to take the C stuff elsewhere? (I would attempt a split but it always seems to crash and lose stuff when I try!)

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

Everybody - thank you for your response. I posted and then went away for a few days, expecting maybe 1 reply. There are more .asm nuts out there than I imagined.

 

I did find a number of mistakes after posting. A few weeks ago I made some big changes in register usage. It seems I overlooked a few details.

 

Thank you. Seriously. Working in a vacuum gets old after a while.

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

Also again, if your chosen toolchain is open-source then you have a direct path to what might please your eye.

True, there could be an upgrade that the compiler uses for the latest whiz-bang feature.  It could also be implemented as part of C itself as some sort of keyword, just like volatile is added.  That was my wish, though it would be a rare use bird & not even applicable to register limited chips.

 

The keyword volatile was a relatively late addition to the ANSI standard, but is cru-

cial in many embedded applications. Normally, a compiler assumes that the...

 

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

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

I am an ASM monkey as well, I'll leave C to the smart folks. Although, I learn more than I'd like to admit porting from C or arduino C++ to assembler... so it may just be inevitable. Anyway, you're not alone clebell.

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

Same here I grew up with assembly language and never catched the C-Train. I don't know why. I tried to learn it and read some books, but due to the lack of projects done in C it all disappeared soon. Strange enough I have written many programs in many different languages like APL, PL/1, PEARL and PHP. In the past I have done quite some projects using AVR microcontrollers and all the programming was done in assembler. However I find it more and more difficult to get detailed information about how to use assembler, especially with the new AVR controller families. Currently struggling with the AVR128DA48 curiosity nano. I wished there would be a better assembler than avrasm2 which in my opinion is really only a poor mans solution. Compared to the environments using assembly language I have been using in the past this lacks everything you could imagine of a useful tool chain. The highest standards are still set by the PDP-11 and VAX-11 macro assemblers of digital with all the support of tools and examples. That said I'm glad to see that I'm not alone. I really would appreciate to exchange experiences using AVR microcontrollers programmed in assembler. Which brings me back to the clebell's question whether there is such a forum.

For more about my projects see http://www.5volts.ch

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

cbscpe wrote:

Currently struggling with the AVR128DA48 curiosity nano.

 

At the assembly language level there is no difference from previous chips. There are only really two areas of change...

 

1) The memory map - that's a one-off change that you may or may not need to make and only affects where you initialise your various .xSEGs and .ORGs to.

2) Peripheral addresses - whilst the 'new' way when using C is to access everything via a structure, at the assembly levels it's all just addresses which can be found in the usual table at the end of the datasheet.

#1 Hardware Problem? https://www.avrfreaks.net/forum/...

#2 Hardware Problem? Read AVR042.

#3 All grounds are not created equal

#4 Have you proved your chip is running at xxMHz?

#5 "If you think you need floating point to solve the problem then you don't understand the problem. If you really do need floating point then you have a problem you do not understand."

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

I think you misunderstood my struggling I should have put it in quotes. It's more avrasm2 that creates the problems and the featurefree IDE AvrStudio 7.0 that makes it difficult.  Memory map works as described, however there is this nasty bug which requires some attention. The peripheral thing as well is nothing new as already many Atmega devices required that you used ld and st instructions to access the device registeres. So just use the new offsets and bits as described in the include file. It's the lack of reasonable macro language and the missing support of a read-only data segement, the inability to define labels in the flash for this read-only data section, which would allow byte-aligned data and the use of the names without multiplying them by 2 and adding an offset. Then there is no support for sections just the three segments. The IDE has no name completion and there is no support for source code libraries. On top of that avrasm2 is still not migrated to macOS which makes MPLAB a bit useless. In addition peripherals, especially the counters, no longer work as with the Atmega architecture. No 8-bit upcounters, which requires more effort to migrate projects. Again this could have been avoided by proper macro support.

 

Ah forgot to mention, that avrasm2 does not recogize the new cores, although this is not a problem but gives this annoying warning "Unrecognized core version: V4S" whenever I build the project.

For more about my projects see http://www.5volts.ch

Last Edited: Sat. Jun 13, 2020 - 09:28 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

cbscpe wrote:
It's the lack of reasonable macro language
It's called C devil

 

(but have you considered avr-as rather than avrasm2? It's got a completely different macro syntax)

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

Good trywink

 

I think avr-as is even worse than avrasm2 I tried it once but immediately switched back

For more about my projects see http://www.5volts.ch

Last Edited: Sat. Jun 13, 2020 - 10:04 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

cbscpe wrote:
the missing support of a read-only data segement, the inability to define labels in the flash for this read-only data section, which would allow byte-aligned data and the use of the names without multiplying them by 2 and adding an offset.

Would you then expect your assembler to sort the information somehow to avoid filler bytes? Would it then also reorder data to avoid loss of filler bytes?  [hmmm--that sounds dangerous]

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

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

clebell wrote:
Oh, that's rude. The code editor didn't even have an ASM option.

 

You can try paste.debian.net and choose the "gas" option, but posts will only last 24 hours.

 

When writing assembly, I like to be aware of the C compiler register conventions.

 

I started assembly long ago w/ the 6800.  Have done sparc, ppc, and lately avr.  Last year I wrote a multi-tasking library in ~350 bytes of assembly.

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

About 6 weeks ago wasn't there a post from someone who was writing their own AVR assembler with some advanced features? I'm on my phone so searching isn't fun.

Or am I imagining things? Too long in lockdown.

#1 Hardware Problem? https://www.avrfreaks.net/forum/...

#2 Hardware Problem? Read AVR042.

#3 All grounds are not created equal

#4 Have you proved your chip is running at xxMHz?

#5 "If you think you need floating point to solve the problem then you don't understand the problem. If you really do need floating point then you have a problem you do not understand."

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

I would like to have some sort of read-only segment for which the assembler knows, the labels need a potential offset and the region is byte aligned compatible with the mapping and used in the data space if you do not specify otherwise. The C compiler can do this why should the assembler not learn new things with new processors. In MACRO-11 for the PDP-11 (a byte-addressable 16-bit CPU) it was the default behaviour. There was a directive .even which aligned on the next 16-bit boundary if required and there was even a directive .odd that made sure then next address would be on a odd address. Yes I really expect an assembler to take care of that. And I don't want the assembler to align automatically. I.e. when your current address pointer is odd and then you use a .dw directive the assembler should throw an error message (as MACRO-11 did). Also I would like to have a better macro language, even the System/390 assembler had better macro support.

For more about my projects see http://www.5volts.ch

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

I did say to look at avr-as. In the GCC/binutils world everything uses byte addressing. 

 

(and Brian is not dreaming, there was a thread in the last couple of months about an assembler)

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

Have a look at fasmg. It says that it is easy to add new processors to the supported devices with just one custom file.

#1 Hardware Problem? https://www.avrfreaks.net/forum/...

#2 Hardware Problem? Read AVR042.

#3 All grounds are not created equal

#4 Have you proved your chip is running at xxMHz?

#5 "If you think you need floating point to solve the problem then you don't understand the problem. If you really do need floating point then you have a problem you do not understand."

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

You can tell the (GNU) assembler to put data in a read-only section (pseudo insn ".section .rodata").   Check the manual.

I don't think the assembler will catch instructions that write to that, though.

 

Edit: the insn

.section .rodata, "r"

says start the .rodata section and it is readonly.  See Section 7.82 of the manual.

Last Edited: Sat. Jun 13, 2020 - 03:06 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

AVR assembler will get another lease on life through the AT Tiny10.   This "grain of rice"-sized six pin SOT23 IC sells for 30 cents each.  But it only has 1024 bytes of flash program space,  so AVR assembler is the best way to stuff it with as much useful code as possible.

 

Here is another WD2812 (NeoPixel is Adafruit's term for this 3-color LED) assembler routine written for the 8-MHz Tiny25.  You can contrast the various program styles and formats. It is assembled using AVRASM2.EXE and works OK.

;*******************************************                                                                
; Neo.asm                                                                                                   
;                                                                                                           
                                                                                                            
                                                                                                            
;      Tiny25 fuse settings ::                                                                              
; Value    high byte                     Value  low byte               extended                             
;   1        7  - ExtResetDisable         1    7  - CKDIV8		-                                   
;   1        6  - DebugWireEnb            1    6  - CKOUT		-                                   
;   0        5  - SPIenable               1    5  - SUT1		-                                   
;   1 (dft)  4  - WatchDog ON             0    4  - SUT0		-                                   
;   1 (dft)  3  - EESAVE                  0    3  - CKSEL3		-                                   
;   1 (dft)  2  - BODlev2                 0    2  - CKSEL2		-                                   
;   1 (dft)  1  - BODlev	          1    1  - CKSEL1		-                                   
;   1 (dft)  0  - BODlev0                 0    0  - CKSEL0    SELFPRGEN self-prg enabled                    
;      111 BOD disabled                                                                                     
                                                                                                            
                                                                                                            
; Atmel AVR Tiny25 microcontroller                                                                          
;             _____                                                                                         
;     reset\ |1   8| Vcc                                                                                    
;         PB3|2   7| pb2 SCK                                                                                
;NeoPixel PB4|3	  6| pb1 MISO                                                                               
;         Gnd|4   5| pb0 MOSI                                                                               
;	     |_____|                                                                                        
                                                                                                            
.nolist                                                                                                     
.include "tn25def.inc"                                                                                      
.list                                                                                                       
                                                                                                            
.equ	Clock			= 8000000                                                                   
.equ	HeartBeatsPerSecond 	= 100                                                                       
.equ	Timer1Reload		= ~((Clock/16384) / HeartBeatsPerSecond)   ;488.28 for Tiny25               
                                                                                                            
                                                                                                            
.equ	NEOPIXELBIT		= 4	; Port B4 [pin 3]                                                   
.equ	HEARTBEATS_OFF_FRAME	= 30 ; speed at which LEDs change  units are 1/100ths of a second           
.equ	HEARTBEATS_ON_FRAME	= 18 ; speed at which LEDs change  units are 1/100ths of a second           
;5 frames per second [a frame is a snapshot of the GRB values of each Neo in                                
                                                                                                            
                                                                                                            
.def	SREGtemp		= r0                                                                        
.def	oneReg			= r1                                                                        
.def	zeroReg			= r2                                                                        
.def	NumberOfNeoPixelsReg	= r3                                                                        
.def	GreenIntensityReg	= r4                                                                        
.def	RedIntensityReg		= r5                                                                        
.def	BlueIntensityReg	= r6                                                                        
.def	LEDvalueReg		= r7                                                                        
.def	count			= r8                                                                        
.def	togglePB4maskReg 	= r9                                                                        
.def	ADCstore                = r10	; most sig 8-bits of 10-bit ADC conversion                          
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~                                                                    
.def	temp			= r16                                                                       
.def	temp2			= r17                                                                       
.def	irqtemp			= r18                                                                       
                                                                                                            
                                                                                                            
;***************************************************                                                        
;  Data Segment                                                                                             
;                                                                                                           
;  Static RAM Arrays, tables, stacks, and queues                                                            
;                                                                                                           
;***************************************************                                                        
.dseg                                                                                                       
isNeoPixelOn:		.byte   1                                                                           
                                                                                                            
heartBeat_Low:  	.byte   1                                                                           
heartBeat_Med:  	.byte   1                                                                           
heartBeat_High: 	.byte   1                                                                           
heartBeat_Count:	.byte   1                                                                           
                                                                                                            
; color data for current NeoPixel frame.  Three bytes [GRB] for each neoPixel device.                       
Green0:			.byte	1    ; a 3-byte Gn-Rd-Bl struct for each NeoPixel                           
Red0:			.byte	1                                                                           
Blue0:			.byte	1                                                                           
Green1:			.byte	1                                                                           
Red1:			.byte	1                                                                           
Blue1:			.byte	1                                                                           
Green2:			.byte	1                                                                           
Red2:			.byte	1                                                                           
Blue2:			.byte	1                                                                           
Green3:			.byte	1                                                                           
Red3:			.byte	1                                                                           
Blue3:			.byte	1                                                                           
Green4:			.byte	1                                                                           
Red4:			.byte	1                                                                           
Blue4:			.byte	1                                                                           
                                                                                                            
                                                                                                            
                                                                                                            
;***************************************************                                                        
;  Data Segment                                                                                             
;                                                                                                           
;  Static RAM Arrays, tables, stacks, and queues                                                            
;                                                                                                           
;***************************************************                                                        
.dseg                                                                                                       
heartBeat:	.byte	1                                                                                   
                                                                                                            
                                                                                                            
;*********************************                                                                          
;	Code Segment                                                                                        
;*********************************                                                                          
.cseg                                                                                                       
.org	$0000                                                                                               
	rjmp reset	; Reset handler $000                                                                
	reti		; 0x0001 External Interrupt_0                                                       
	reti		; 0x0002 Pin change Interrupt Request_0                                             
	reti		; 0x0003 Timer/Counter1 Compare Match 1A                                            
	rjmp T1CntOvflw	; 0x0004 Timer/Counter1 Overflow   // section 12 PDF june10                         
	reti		;  0x0005 Timer/Counter0 Overflow                                                   
	reti		; 0x0006 EEPROM Ready                                                               
	reti		; 0x0007 Analog comparator                                                          
	reti		; 0x0008 ADC Conversion ready                                                       
	reti		; 0x0009 Timer/Counter1 Compare Match B                                             
	reti		; 0x000a Timer/Counter0 Compare Match A                                             
	reti		; 0x000b Timer/Counter0 Compare Match B                                             
	reti		; 0x000c Watchdog Time-out                                                          
	reti		; 0x000d USI START                                                                  
	reti		; 0x000e USI Overflow                                                               
                                                                                                            
                                                                                                            
reset:                                                                                                      
; initialize Timers in the Tiny25                                                                           
	ldi	temp, (1 << TOIE1) ;| (1<< TOIE0)  ; enable timer overflow interrupts                       
	out	TIMSK, temp	; 12.3.7                                                                    
	ldi	temp, Timer1Reload ; 488 increments/sec  488*16=7808                                        
	out	TCNT1, temp	; 0x2f_sfr       13.3.3                                                     
	ldi	temp, (1<<CS13) | (1<<CS12) | (1<<CS11) | (1<<CS10) ;  CLK/16384  table 12.5                
	out	TCCR1 , temp	;                                                                           
;  compare to the Timer1 in the Tiny1634                                                                    
;   t1634 has CLK/1024 but not CLK/16384  488*16=                                                           
                                                                                                            
	ldi	temp, (1<<NEOPIXELBIT)	; 76543210 PortB bit 4 is the NeoPixel data pin                     
	mov	oneReg, temp		; 00010000                                                          
	ldi	temp, 0                                                                                     
	mov	zeroReg, temp                                                                               
                                                                                                            
	ldi	temp, (1<<NEOPIXELBIT)                                                                      
	out	DDRB, temp                                                                                  
                                                                                                            
 	clr	temp                                                                                        
	sts	heartBeat_Low, temp                                                                         
	sts	heartBeat_Med, temp                                                                         
	sts	heartBeat_High, temp                                                                        
	sts	heartBeat_Count, temp                                                                       
                                                                                                            
	sei	; interrupts needed by heartBeat counter                                                    
                                                                                                            
;  initialize the NeoPixel LED color display and sequence                                                   
	ser	temp                                                                                        
	sts	isNeoPixelOn, temp                                                                          
                                                                                                            
	clr	zl     ; ZH:ZL is a index into the flash program bytes. Values are used as random           
	clr	zh     ; which are used to light the NeoPixels in random colors.                            
                                                                                                            
	lpm	temp, z+   ; color on neo2 is from flash, color on neo1 and neo3 is prev neo2 colo          
	sts	Green0, temp   ; color on neo0 and neo4 is prev neo1:neo3 color                             
	sts	Green4, temp                                                                                
	lpm	temp, z+                                                                                    
	sts	Red0, temp                                                                                  
  	sts	Red4, temp                                                                                  
	lpm	temp, z+                                                                                    
	sts	Blue0, temp                                                                                 
  	sts	Blue4, temp                                                                                 
	lpm	temp, z+   ; color on neo2 is from flash, color on neo1 and neo3 is prev neo2 colo          
	sts	Green1, temp   ; color on neo0 and neo4 is prev neo1:neo3 color                             
	sts	Green3, temp                                                                                
	lpm	temp, z+                                                                                    
	sts	Red1, temp                                                                                  
  	sts	Red3, temp                                                                                  
	lpm	temp, z+                                                                                    
	sts	Blue1, temp                                                                                 
  	sts	Blue3, temp                                                                                 
;__________________________________________________________________________                                 
                                                                                                            
                                                                                                            
                                                                                                            
;********************************************                                                               
;********************************************                                                               
Main:                                                                                                       
                                                                                                            
m_nx0:                                                                                                      
	lds	temp, heartBeat_Count                                                                       
	cpi	temp, HEARTBEATS_ON_FRAME                                                                   
	breq	m_1                                                                                         
	rjmp	m_nx0                                                                                       
                                                                                                            
m_1:	clr	temp                                                                                        
	sts	heartBeat_Count, temp                                                                       
	rcall	NeoFrame                                                                                    
                                                                                                            
m_nx1:                                                                                                      
	lds	temp, heartBeat_Count                                                                       
	cpi	temp, HEARTBEATS_OFF_FRAME                                                                  
	breq	m_2                                                                                         
	rjmp	m_nx1                                                                                       
                                                                                                            
m_2:	clr	temp                                                                                        
	sts	heartBeat_Count, temp                                                                       
	rcall	TurnOffAllNeoPixels                                                                         
                                                                                                            
m_nx2:	rjmp	Main                                                                                        
                                                                                                            
;********************************************                                                               
;********************************************                                                               
                                                                                                            
                                                                                                            
                                                                                                            
                                                                                                            
;********************************************                                                               
;	Subroutines                                                                                         
;********************************************                                                               
NeoFrame:   ; uses ZH:ZL as a pointer in flash code to make pseudo-random #                                 
                                                                                                            
;  main code checks if   HBcount == HEARTBEATSPERFRAME.                                                     
;  If not, then NF not called.                                                                              
;  if yes, then read 3 bytes from flash, and use them as new GBR                                            
;  for neopixel color on center LED. copy other LEDs.                                                       
                                                                                                            
                                                                                                            
; check if at pseudo-random pointer is at the end of the flash program data.                                
; 0x160 is the size of the block of flash program data used to make pseudo-random colors.                   
	cpi	zh,1                                                                                        
	brne	NeoFrameOn                                                                                  
	cpi	zl, 0x60                                                                                    
	brlo	NeoFrameOn                                                                                  
	ldi	zl, 0x10                                                                                    
	clr	zh                                                                                          
                                                                                                            
; Update the SRAM array of the LED brightness values for each NeoPixel device.                              
; copy inside NeoLED colors to the outside,                                                                 
;  -- put the previous color from neoPxl#1 [and #3] on neoPxl#0 and #4 [the outer neoPixels].               
;  -- put the previous center NeoPxl's color on neoPxl#1 and #3 (the ones next to the center)               
; get three bytes from the flash program listing and                                                        
; use them to make a random GRB color on the center NeoPx [#2, of 0-4].                                     
NeoFrameOn:                                                                                                 
	lds	temp, Green1    ; copy the color of the middle pixels to the edge pixels                    
	sts	Green0, temp    ;   x C x C x  ===> C C x C C                                               
	sts	Green4, temp    ;   0 1 2 3 4       0 1 2 3 4                                               
	lds	temp, Red1                                                                                  
	sts	Red0, temp                                                                                  
	sts	Red4, temp                                                                                  
	lds	temp, Blue1                                                                                 
	sts	Blue0, temp                                                                                 
	sts	Blue4, temp                                                                                 
                                                                                                            
	lds	temp, Green2    ;  copy the color of the center pixel to the middle pixels                  
	sts	Green1, temp    ;   x x C x x  ==>  x C C C x                                               
	sts	Green3, temp    ;   0 1 2 3 4       0 1 2 3 4                                               
	lds	temp, Red2                                                                                  
	sts	Red1, temp                                                                                  
	sts	Red3, temp                                                                                  
	lds	temp, Blue2                                                                                 
	sts	Blue1, temp                                                                                 
	sts	Blue3, temp                                                                                 
                                                                                                            
	lpm	temp, z+	; put a new color [GRB:3 bytes read from flash] on the center pixel         
	sts	Green2, temp                                                                                
	lpm	temp, z+                                                                                    
	sts	Red2, temp                                                                                  
	lpm	temp, z+                                                                                    
	sts	Blue2, temp                                                                                 
                                                                                                            
NeoF_loop:    ;  change NeoPixel values on a 5-device group.                                                
	ldi	temp, 5                                                                                     
	mov	NumberOfNeoPixelsReg, temp                                                                  
	ldi	YH, high (Green0)                                                                           
	ldi	YL, low  (Green0)                                                                           
NeoF_lp2:                                                                                                   
	ld	GreenIntensityReg, y+                                                                       
	ld	RedIntensityReg, y+                                                                         
	ld	BlueIntensityReg, y+                                                                        
	rcall	LightOneNeoPixel                                                                            
	dec	NumberOfNeoPixelsReg                                                                        
	brne	NeoF_lp2                                                                                    
                                                                                                            
NeoFrameExit:                                                                                               
	ret                                                                                                 
                                                                                                            
                                                                                                            
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~                                                                   
TurnOffAllNeoPixels:                                                                                        
                                                                                                            
	clr	temp                                                                                        
	sts	heartBeat_Count, temp                                                                       
                                                                                                            
	ldi	temp, 5                                                                                     
	ldi	temp2, 0x00                                                                                 
Toff_lp:                                                                                                    
	mov	GreenIntensityReg, temp2                                                                    
	mov	RedIntensityReg, temp2                                                                      
	mov	BlueIntensityReg, temp2                                                                     
	rcall	LightOneNeoPixel                                                                            
	dec	temp                                                                                        
	brne	Toff_lp                                                                                     
                                                                                                            
TnOffExit:                                                                                                  
	ret                                                                                                 
                                                                                                            
                                                                                                            
                                                                                                            
;=================================================================                                          
;  LightOne_NeoPixel    8MHz system clock :: 800KHz neos                                                    
;   Receives three 8-bit values in low registers:                                                           
;     RedIntensityReg, GreenIntensityReg, BlueIntensityReg.                                                 
;                                                                                                           
;   Uses four additional registers: LEDvalueReg and temp as temporary storage.                              
;   and has two registers with unchanging pre-defined values:                                               
;      	oneReg  = PORTB |  pinMask                                                                          
;      	zeroReg = PORTB & ~pinMask                                                                          
;                                                                                                           
;   1st period write PortB3 high 0.4uS                                                                      
;   2nd period write PortB3 either high or low depending on bit value                                       
;   3rd period_write PortB3 low for 0.4uS                                                                   
;                                                                                                           
;                                                                                                           
;  code doesn't loop after testing and sending each bit. All 24 data bits                                   
;  sent in a long code sequence, most sig bit first. Green:Red:Blue                                         
;-----------------------------------------------------------------------                                    
LightOneNeoPixel:                                                                                           
	cli                                                                                                 
                                                                                                            
	mov	LEDvalueReg, GreenIntensityReg                                                              
 	mov	temp,	zeroReg                                                                             
	sbrc	LEDvalueReg, 7                                                                              
	mov	temp,	oneReg                                                                              
GreenLED:		; three periods per bit: High:0.4uS  data:0.45uS  Low:0.40uS                        
	out	PORTB,	oneReg		;Grn7H    1 cycles    0.000     x                                   
	mov	temp2,	zeroReg		;         1 cycle     0.125     H                                   
	out	PORTB,	temp		;Grn7D    1 cycle     0.250     H                                   
	nop				;         1 cycle     0.375     D                                   
	nop				;         1 cycle     0.500     D                                   
	sbrc	LEDvalueReg, 6		;       1_2 cycle     0.625     D                                   
	mov	temp2,	oneReg		;         1 cycle     0.870     D                                   
	out	PORTB ,	zeroReg		;Grn7L    1 cycle     1.000     D                                   
	nop				;         1 cycle     1.125     L                                   
	nop				;         1 cycle     1.250     L                                   
                                                                                                            
	out	PORTB,	oneReg		;Grn6H    1 cycle     1.375     L                                   
	mov	temp,	zeroReg		;         1 cycle     1.500     H                                   
	out	PORTB,	temp2		;Grn6D    1 cycle     1.625     H                                   
	nop				;         1 cycle     1.750     L                                   
	nop				;         1 cycle     1.870     L                                   
	sbrc	LEDvalueReg, 5		;       1_2 cycle     2.125     D                                   
	mov	temp,	oneReg 		;         1 cycle     2.250     D                                   
	out	PORTB,	zeroReg		;Grn6L    1 cycle     2.375     D                                   
	nop				;         1 cycle     2.500     L                                   
	nop				;         1 cycle     2.625     L                                   
                                                                                                            
	out	PORTB,	oneReg 		;Grn5H    1 cycle     2.750     L                                   
	mov	temp2,	zeroReg		;         1 cycle     3.000     H                                   
	out	PORTB,	temp		;Grn5D    1 cycle     3.125     H                                   
	nop				;         1 cycle     3.250     L                                   
	nop				;         1 cycle     3.375     L                                   
	sbrc	LEDvalueReg, 4		;       1/2 cycle     3.50      D                                   
	mov	temp2,	oneReg		;         1 cycle     3.75      D                                   
	out	PORTB,	zeroReg		;Grn5L    1 cycle     3.875     D                                   
	nop				;         1 cycle     4.0       L                                   
	nop				;         1 cycle     4.125     L                                   
                                                                                                            
	out	PORTB,	oneReg 		;Grn4H    1 cycle     4.250     L                                   
	mov	temp,	zeroReg		;         1 cycle     4.375     H                                   
	out	PORTB,	temp2  		;Grn4D    1 cycle     4.500                                         
	nop				;         1 cycle     4.625     L                                   
	nop				;         1 cycle     4.750     L                                   
	sbrc	LEDvalueReg, 3		;       1/2 cycle     5.000     D                                   
	mov	temp, oneReg 		;         1 cycle     5.125     D                                   
	out	PORTB, zeroReg		;Grn4L    1 cycle     5.250     D                                   
	nop				;         1 cycle     5.375     L                                   
	nop				;         1 cycle     5.500     L                                   
                                                                                                            
	out	PORTB,oneReg 		;Grn3H    1 cycle     5.625     L                                   
	mov	temp2,zeroReg		;         1 cycle     5.750     H                                   
	out	PORTB,temp		;Grn3D    1 cycle     5.875                                         
	nop				;         1 cycle     6.000     L                                   
	nop				;         1 cycle     6.125     L                                   
	sbrc	LEDvalueReg, 2		;       1/2 cycle     6.250     D                                   
	mov	temp2,	oneReg		;         1 cycle     6.375     D                                   
	out	PORTB,	zeroReg		;Grn3L    1 cycle     6.500     D                                   
	nop				;         1 cycle     6.625     L                                   
	nop				;         1 cycle     6.750     L                                   
                                                                                                            
	out	PORTB, oneReg 		;Grn2H    1 cycle     6.875     L                                   
	mov	temp, zeroReg		;         1 cycle     7.000     H                                   
	out	PORTB, temp2		;Grn2D    1 cycle     7.125     D                                   
	nop				;         1 cycle     7.250     D                                   
	nop				;         1 cycle     7.375     D                                   
	sbrc	LEDvalueReg, 1		;       1/2 cycle     7.500     D                                   
	mov	temp, oneReg 		;         1 cycle     7.750     D                                   
	out	PORTB, zeroReg		;Grn2L    1 cycle     7.875     D                                   
	nop				;         1 cycle     8.000     L                                   
	nop				;         1 cycle     8.125                                         
                                                                                                            
	out	PORTB, oneReg		;Grn1H    1 cycle     8.250     H                                   
	mov	temp2, zeroReg		;         1 cycle     8.375     H                                   
	out	PORTB, temp		;Grn1D    1 cycle     8.500     D                                   
	nop				;         1 cycle     8.625     D                                   
	nop				;         1 cycle     8.875     D                                   
	sbrc	LEDvalueReg, 0		;       1/2 cycle     9.000     L                                   
	mov	temp2, oneReg		;         1 cycle     9.125     L                                   
	out	PORTB, zeroReg		;Grn1L    1 cycle     9.250                                         
	mov	LEDvalueReg,RedIntensityReg	;  <<<<<< 2 cycle     9.375   L                             
	out	PORTB, oneReg		;Grn0H    1 cycle     9.50      L                                   
	mov	temp, zeroReg		;         1 cycle     9.625     H                                   
	out	PORTB, temp2		;Grn0D    1 cycle     9.750     H                                   
	sbrc	LEDvalueReg,  7		;	1/2 cycle     9.875     D                                   
	mov	temp, oneReg		;	  1 cycle    10.000     D                                   
	out	PORTB, zeroReg		;Grn0L	  1 cycle    10.125     D                                   
                                                                                                            
	mov	temp,	zeroReg                                                                             
	sbrc	LEDvalueReg, 7                                                                              
	mov	temp,	oneReg                                                                              
RedLED:		; three periods per bit: High:0.4uS  data:0.45uS  Low:0.40uS                                
	out	PORTB, oneReg		;Red7H    1 cycles       0     x                                    
	mov	temp2, zeroReg		;Red      1 cycle      .125    H                                    
	out	PORTB, temp		;Red7D    1 cycle      .25     H                                    
	nop				;Red      1 cycle      .375    D                                    
	nop				;Red      1 cycle      .50     D                                    
	sbrc	LEDvalueReg, 6		;Red    1_2 cycle      .625    D                                    
	mov	temp2,	oneReg		;Red      1 cycle      .87     D                                    
	out	PORTB ,	zeroReg		;Red7L    1 cycle     1.00     D                                    
	nop				;Red      1 cycle     1.125    L                                    
	nop				;Red      1 cycle     1.25     L                                    
                                                                                                            
	out	PORTB, oneReg		;Red6H    1 cycle     1.375    L                                    
	mov	temp,  zeroReg		;Red      1 cycle     1.50     H                                    
	out	PORTB, temp2		;Red6D    1 cycle     1.625    H                                    
	nop				;Red      1 cycle     1.75     L                                    
	nop				;Red      1 cycle     1.87     L                                    
	sbrc	LEDvalueReg, 5  	;Red    1/2 cycle     2.125    D                                    
	mov	temp,	oneReg 		;Red      1 cycle     2.25     D                                    
	out	PORTB,	zeroReg		;Red6L    1 cycle     2.375    D                                    
	nop				;Red      1 cycle     2.50     L                                    
	nop				;Red      1 cycle     2.625    L                                    
                                                                                                            
	out	PORTB, oneReg 		;Red5H    1 cycle     2.75     L                                    
	mov	temp2, zeroReg		;Red      1 cycle     3.0      H                                    
	out	PORTB, temp		;Red5D    1 cycle     3.125    H                                    
	nop				;Red      1 cycle     3.25     L                                    
	nop				;Red      1 cycle     3.375    L                                    
	sbrc	LEDvalueReg, 4		;Red    1/2 cycle     3.50     D                                    
	mov	temp2,	oneReg		;Red      1 cycle     3.75     D                                    
	out	PORTB,	zeroReg		;Red5L    1 cycle     3.875    D                                    
	nop				;Red      1 cycle     4.0      L                                    
	nop				;Red      1 cycle     4.125    L                                    
                                                                                                            
	out	PORTB,oneReg 		;Red4H    1 cycle     4.250    L                                    
	mov	temp, zeroReg		;Red      1 cycle     4.375    H                                    
	out	PORTB,temp2  		;Red4D    1 cycle     4.50     H                                    
	nop				;Red      1 cycle     4.625    D                                    
	nop				;Red      1 cycle     4.75     D                                    
	sbrc	LEDvalueReg, 3 		;Red    1/2 cycle     5.0      D                                    
	mov	temp, oneReg 		;Red      1 cycle     5.125    D                                    
	out	PORTB, zeroReg		;Red4L    1 cycle     5.25     D                                    
	nop				;Red      1 cycle     5.375    L                                    
	nop				;Red      1 cycle     5.50     L                                    
                                                                                                            
	out	PORTB, oneReg 		;Red3H    1 cycle     5.6250   L                                    
	mov	temp2, zeroReg		;Red      1 cycle     5.75     H                                    
	out	PORTB, temp		;Red3D    1 cycle     5.8750                                        
	nop				;Red      1 cycle     6.00     L                                    
	nop				;Red      1 cycle     6.125    L                                    
	sbrc	LEDvalueReg, 2		;Red    1/2 cycle     6.25     D                                    
	mov	temp2, oneReg  		;Red      1 cycle     6.375    D                                    
	out	PORTB, zeroReg		;Red3L    1 cycle     6.50     D                                    
	nop				;Red      1 cycle     6.625    L                                    
	nop				;Red      1 cycle     6.750    L                                    
                                                                                                            
	out	PORTB, oneReg 		;Red2H    1 cycle     6.8750   L                                    
	mov	temp , zeroReg		;Red      1 cycle     7.000    H                                    
	out	PORTB, temp2 		;Red2D    1 cycle     7.125    D                                    
	nop				;Red      1 cycle     7.250    D                                    
	nop				;Red      1 cycle     7.375    D                                    
	sbrc	LEDvalueReg, 1		;Red    1/2 cycle     7.500    D                                    
	mov	temp, oneReg 		;Red      1 cycle     7.750    D                                    
	out	PORTB, zeroReg		;Red2L    1 cycle     7.875    D                                    
	nop				;Red      1 cycle     8.000    L                                    
	nop				;Red      1 cycle     8.125                                         
                                                                                                            
	out	PORTB, oneReg		;Red1H    1 cycle     8.250    H                                    
	mov	temp2, zeroReg		;Red      1 cycle     8.375    H                                    
	out	PORTB, temp		;Red1D    1 cycle     8.500    D                                    
	nop				;Red      1 cycle     8.625    D                                    
	nop				;Red      1 cycle     8.875    D                                    
	sbrc	LEDvalueReg, 0		;Red    1/2 cycle     9.000    L                                    
	mov	temp2, oneReg		;Red      1 cycle     9.125    L                                    
	out	PORTB, zeroReg 		;Red1L    1 cycle     9.250                                         
	mov	LEDvalueReg, BlueIntensityReg	;Red      2 cycle     9.375   L                             
                                                                                                            
	out	PORTB, oneReg		;Red0H    1 cycle     9.50    L                                     
	mov	temp , zeroReg		;Red      1 cycle     9.625   H                                     
	out	PORTB, temp2		;Red0D    1 cycle     9.750   H                                     
	sbrc	LEDvalueReg, 7		;Red    1/2 cycle     9.875   D                                     
	mov	temp, oneReg		;Red      1 cycle    10.000   D                                     
	out	PORTB, zeroReg		;Red0L	  1 cycle    10.125   D                                     
                                                                                                            
	mov	temp,	zeroReg                                                                             
	sbrc	LEDvalueReg, 7                                                                              
	mov	temp, oneReg                                                                                
BlueLED:		; three periods per bit: High:0.4uS  data:0.45uS  Low:0.40uS                        
	out	PORTB, oneReg		;Blue7H    1 cycles       0     x                                   
	mov	temp2, zeroReg		;Blue      1 cycle      .125    H                                   
	out	PORTB, temp		;Blue7D    1 cycle      .25     H                                   
	nop				;Blue      1 cycle      .375    D                                   
	nop				;Blue      1 cycle      .50     D                                   
	sbrc	LEDvalueReg, 6		;Blue    1_2 cycle      .625    D                                   
	mov	temp2, oneReg		;Blue      1 cycle      .87     D                                   
	out	PORTB, zeroReg		;Blue7L    1 cycle     1.00     D                                   
	nop				;Blue      1 cycle     1.125    L                                   
	nop				;Blue      1 cycle     1.25     L                                   
                                                                                                            
	out	PORTB,	oneReg		;Blue6H    1 cycle     1.375    L                                   
	mov	temp,	zeroReg		;Blue      1 cycle     1.50     H                                   
	out	PORTB,	temp2		;Blue6D    1 cycle     1.625    H                                   
	nop				;Blue      1 cycle     1.75     L                                   
	nop				;Blue      1 cycle     1.87     L                                   
	sbrc	LEDvalueReg, 5  	;Blue    1_2 cycle     2.125    D                                   
	mov	temp,	oneReg 		;Blue      1 cycle     2.25     D                                   
	out	PORTB,	zeroReg		;Blue6L    1 cycle     2.375    D                                   
	nop				;Blue      1 cycle     2.50     L                                   
	nop				;Blue      1 cycle     2.625    L                                   
                                                                                                            
	out	PORTB,	oneReg 		;Blue5H    1 cycle     2.75     L                                   
	mov	temp2, zeroReg		;Blue      1 cycle     3.0      H                                   
	out	PORTB, temp		;Blue5D    1 cycle     3.125    H                                   
	nop				;Blue      1 cycle     3.25     L                                   
	nop				;Blue      1 cycle     3.375    L                                   
	sbrc	LEDvalueReg, 4		;Blue    1_2 cycle     3.50     D                                   
	mov	temp2,	oneReg		;Blue      1 cycle     3.75     D                                   
	out	PORTB,	zeroReg		;Blue5L    1 cycle     3.875    D                                   
	nop				;Blue      1 cycle     4.0      L                                   
	nop				;Blue      1 cycle     4.125    L                                   
                                                                                                            
	out	PORTB, oneReg		;Blue4H    1 cycle     4.250    L                                   
	mov	temp, zeroReg		;Blue      1 cycle     4.375    H                                   
	out	PORTB, temp2		;Blue4D    1 cycle     4.50                                         
	nop				;Blue      1 cycle     4.625    L                                   
	nop				;Blue      1 cycle     4.75     L                                   
	sbrc	LEDvalueReg, 3		;Blue    1_2 cycle     5.0      D                                   
	mov	temp, oneReg 		;Blue      1 cycle     5.125    D                                   
	out	PORTB, zeroReg		;Blue4L    1 cycle     5.25     D                                   
	nop				;Blue      1 cycle     5.375    L                                   
	nop				;Blue      1 cycle     5.50     L                                   
                                                                                                            
	out	PORTB, oneReg 		;Blue3H    1 cycle     5.6250   L                                   
	mov	temp2, zeroReg		;Blue      1 cycle     5.75     H                                   
	out	PORTB, temp		;Blue3D    1 cycle     5.8750                                       
	nop				;Blue      1 cycle     6.00     L                                   
	nop				;Blue      1 cycle     6.125    L                                   
	sbrc	LEDvalueReg, 2		;Blue    1_2 cycle     6.25     D                                   
	mov	temp2, oneReg  		;Blue      1 cycle     6.375    D                                   
	out	PORTB, zeroReg		;Blue3L    1 cycle     6.50     D                                   
	nop				;Blue      1 cycle     6.625    L                                   
	nop				;Blue      1 cycle     6.750    L                                   
                                                                                                            
	out	PORTB, oneReg 		;Blue2H    1 cycle     6.8750   L                                   
	mov	temp , zeroReg		;Blue      1 cycle     7.000    H                                   
	out	PORTB, temp2 		;Blue2D    1 cycle     7.125    D                                   
	nop				;Blue      1 cycle     7.250    D                                   
	nop				;Blue      1 cycle     7.375    D                                   
	sbrc	LEDvalueReg, 1		;Blue    1_2 cycle     7.500    D                                   
	mov	temp, oneReg		;Blue      1 cycle     7.750    D                                   
	out	PORTB, zeroReG		;Blue2L    1 cycle     7.875    D                                   
	nop				;Blue      1 cycle     8.000    L                                   
	nop				;Blue      1 cycle     8.125                                        
                                                                                                            
	out	PORTB, oneReg		;Blue1H    1 cycle     8.250    H                                   
	mov	temp2, zeroReg		;Blue      1 cycle     8.375    H                                   
	out	PORTB, temp		;Blue1D    1 cycle     8.500    D                                   
	nop				;Blue      1 cycle     8.625    D                                   
	nop				;Blue      1 cycle     8.875    D                                   
	sbrc	LEDvalueReg, 0		;Blue    1_2 cycle     9.000    L                                   
	mov	temp2, oneReg		;Blue      1 cycle     9.125    L                                   
	out	PORTB, zeroReg 		;Blue1L    1 cycle     9.250                                        
	mov	LEDvalueReg, GreenIntensityReg	;Blue      2 cycle     9.375    L                           
                                                                                                            
	out	PORTB, oneReg		;Blue0H    1 cycle     9.500    L                                   
	mov	temp, zeroReg		;Blue      1 cycle     9.625    H                                   
	out	PORTB, temp2		;Blue0D    1 cycle     9.750    H                                   
	sbrc	LEDvalueReg, 7		;Blue    1_2 cycle     9.875    D                                   
	mov	temp, oneReg		;Blue      1 cycle    10.000    D                                   
	out	PORTB, zeroReg		;Blue0L    1 cycle    10.125    D                                   
	sei                                                                                                 
	ret                                                                                                 
;~~~~~~~~~~~~~~~~~~~~~ end of LightOneNeoPixel ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~                         
                                                                                                            
                                                                                                            
                                                                                                            
;*********************************************************************************                          
;   doADC   - set up, run analog-to-digital convertor, then return high bits (9-2) of result                
;                                                                                                           
;   send:	The ADC channel in Temp register bits 1 and 0                                               
;   return:	left aligned upper 8 bits of result in ADCstore register                                    
;**********************************************************************************                         
doADC:	; Tiny25 version                                                                                    
	andi	temp, 0b00000011 ; preserve MUX bits                                                        
	ori	temp, (1<<ADLAR); return bits 9-2 in ADCH; REFS0 cleared for VCC reference                  
	out	ADMUX, temp; VCC is reference; ADCh=bits 9-2                                                
; ADEN = ADC enable;  ADIE = irq enable                                                                     
; ADPS2 set=clock/32 for ADCclk for 200K ADC clock 8MHz sysclk                                              
 	ldi	temp, (1 << ADEN) | (1 << ADPS2) | (0 << ADPS1) | (1 << ADPS0)                              
	out	ADCSRA, temp                                                                                
	sbi	ADCSRA, ADSC ; start conversion                                                             
doADC0:	sbic	ADCSRA, ADSC; set means ADC conversion still in progress                                    
	rjmp	doADC0                                                                                      
	in	ADCstore, ADCH                                                                              
	ret                                                                                                 
                                                                                                            
                                                                                                            
                                                                                                            
;***************************************************************************                                
  ;   Timer 1 overflows and is reloaded                                                                     
  ; heartBeat Low increments 100 times per second.                                                          
  ; heartBeat Medium byte increments every 2.56 seconds                                                     
  ; hb High increments every 655.36 sec[10.92 min]                                                          
  ; all turnover to zero after: 46.6 hrs                                                                    
  ;  an 8-bit variable called heartBeat_Count is also incremented.                                          
T1CntOvflw:                                                                                                 
	push	temp                                                                                        
 	in	SREGtemp, SREG                                                                              
	ldi	irqtemp, Timer1Reload  ; 0xdf                                                               
	out	TCNT1, irqtemp                                                                              
                                                                                                            
	lds	irqtemp, heartBeat_Count                                                                    
	inc	irqtemp                                                                                     
	sts	heartBeat_Count, irqtemp                                                                    
                                                                                                            
	ldi	irqtemp, 1                                                                                  
	lds	temp, heartBeat_Low                                                                         
	add	temp, irqtemp                                                                               
	sts	heartBeat_Low, temp                                                                         
	ldi	irqtemp, 0                                                                                  
	lds	temp, heartBeat_Med                                                                         
	adc	temp, irqtemp                                                                               
	sts	heartBeat_Med, temp                                                                         
	lds	temp, heartBeat_High                                                                        
	adc	temp, irqtemp                                                                               
	sts	heartBeat_High, temp                                                                        
                                                                                                            
	pop	temp                                                                                        
	reti                                                                                                
                                                                                                            
                                                                                                            
                                                                                                            
;===========================================================================                                
                                                                                                            
.db	"**Neo.asm  ver 1.4    Oct 16, 2017"                                                                
;  software program name, version, and date in flash program space (after all working code)                 
                                                                                                            
                                                                                                            

 

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

never catched the C-Train.

Last night I watched a movie (night school cheeky ) that may have an answer to the reason why and a solution of sort for people with C problems like me.

 

I caught up with C a little in the last few years because I had to but my main stumbling block was the cost of the compilers around 30 years ago.

 

When I started with AVRs (from Motorola) around 20 years ago I complained to one of the Atmel engineers at a seminar about the "simplicity" of AVRASM1 and wanted more features but I was pretty much told that AVRs were designed with C in mind and the assembler wasn't going to improve.

 

Then we got AVRASM2 which was somewhat better, tried to use the GNU assembler but went back to AVRASM2 for most of my projects where I didn't have to give the source to the client.

John Samperi

Ampertronics Pty. Ltd.

www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

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

js wrote:
tried to use the GNU assembler but went back to AVRASM2 for most of my projects where I didn't have to give the source to the client.

 

That does not sound right, as long as you don't put GPL on your files (or any included files with GPL) then I would hope the assembler can be expected to convert the statements into machine code without inflicting its license on the derived machine code.

 

Just to be totally transparent, I have made a Trump statement, facts were not checked and all that, e.g., its a gut reaction.

my projects: https://github.com/epccs

Debugging is harder than programming - don’t write code you can’t debug! https://www.avrfreaks.net/forum/help-it-doesnt-work

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

It was more the case of the clients being ASM impaired devil.....so they wanted the code in C.

John Samperi

Ampertronics Pty. Ltd.

www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
	nop				;Blue      1 cycle     5.375    L                                   
	nop				;Blue      1 cycle     5.50     L                                   

Replace your double-nop's with "rjmp .+1" (or whatever the syntax is for pc-relative addresses) and you'll save almost 40 bytes of code!

 

 

2) Peripheral addresses - whilst the 'new' way when using C is to access everything via a structure, at the assembly levels it's all just addresses which can be found in the usual table at the end of the datasheet.

"Good" assembler support would include a mechanism for using the structure-like definitions in ASM.  Minimally, something like:

    ld  r1, Y+CTRLA

Not to mention all the constants that have become enums in the latest io*.h files, and therefore aren't available to avr-as any more :-(  (I guess they are still in the .INC file for AVRASM...)

 

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

I tried to add some support for structure-like definitions and started with some simple macros. 

 

.set recordlength = -1
.macro  recordstart
.set recordlength = 0
.endmacro

.macro  record
.equ    @0##_##@1 = recordlength
.set recordlength = recordlength + @2
.endmacro       

.macro  recordend
.equ    @0##_##@1 = recordlength
.endmacro       

recordstart     fcb
record          fcb, cluster, 4
record          fcb, sector, 4
record          fcb, address, 2
record          fcb, flag, 1
.equ    F_Readonly              = 0                             ; File is open read-only
.equ    F_Direct                = 1                             ; File is open for direct block IO
.equ    F_Sequential    = 2                             ; File is open for sequential access
.equ    F_Image                 = 3                             ; File is a valid diskimage
record          fcb, secinclst, 1
record          fcb, drvtab, 2
record          fcb, filename, 2
record          fcb, fraglist, 2
record          fcb, position, 4
record          fcb, filesize, 4
record          fcb, byteinsec, 2
recordend       fcb, length

recordstart     Fr
record          Fr, List, 2                                     ; Linked List Head
record          Fr, Size, 4                                     ; Size of Fragment (or 0 if end if list)
record          Fr, Start, 4                            ; Start sector of fragment on device
recordend       Fr, Entry                                       ; Length of fragment list entry

 

For more about my projects see http://www.5volts.ch

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

js wrote:

It was more the case of the clients being ASM impaired devil.....so they wanted the code in C.

 

I once wrote about 30k lines of assembler before the customer's customer told me they wanted it in C.  I told them,

asm {
    ... all my code ...
}

would be, strictly technically, valid 'C'.

 

The local customer didn't like that answer, so they had an in-house chap write C wrappers for everything (including some cheerfully optimized math routines).  I'm sure the chap meant well, but he treated every entry into a routine as a 'call' instruction, and some of them were 'jump'-ed into.  Some of you may already feel like there's ice on your back teeth...

 

Yeah.  That meant every time his code 'returned' from what was supposed to be a jump, not a call, a little more got shoved onto the stack, which eventually overflowed into the working memory, and pop went the whole system.

 

This was supposed to be a nearly-complete system, too, just cleaning up the UI and fine-tuning some calibration math.  The bug report (from the customer's customer) for the first 'C' version was 'occasional screen corruption, and then non-functional, only a power-cycle fixes'.

 

I replicated the bug by turning it on, opening the lid (it had a folding lid, and a lid closed detection sensor) and closing the lid 27 times.  Guaranteed crash - probably sooner than 27 'lid cycles' if you were doing anything else with it (for a machine that was supposed to be opened and closed four times an hour...).

 

Most bugs, in my experience, you spend hours finding, ten seconds fixing, and then more hours testing.  This particular blunder by their in-house coder was not hard to find at all.  Fixing it took weeks, and testing?  I don't think it ever got fully tested.  For all I know there's still a few stray 'jump's in there treated as 'call's, and the stack still gets smashed - just a bit slower.

 

S.

 

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

I'm an asm for asm's sake kind of person.   One of my projects is a fantasy console using the AVR for it's instruction set.   It doesn't use any actually existing AVR chip.  It has 128k ROM and 64k RAM.

 

To make it friendly for people to use I have been making a little browser based IDE/Emulator for it, all client side.  

 

Long story short...   I wrote an AVR assembler in JavaScript.   it's at https://github.com/Lerc/AvrAsm ... It's not fully compatible with any other assembler.  Instead I took a fresh take at it. It has some interesting new features.

 

Using node you can run it as a command line assembler.     It output's hex files directly, but as JavaScript it should be fairly easily hackable.

 

The IDE can be seen at https://k8.fingswotidun.com/stat...

 

it  can load code from gists so that https://gist.github.com/lerc/ad9...

 

can be loaded in the ide with https://k8.fingswotidun.com/stat...

 

 

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

cbscpe wrote:
I wished there would be a better assembler than avrasm2 which in my opinion is really only a poor mans solution. Compared to the environments using assembly language I have been using in the past this lacks everything you could imagine of a useful tool chain.

 

I cannot agree with that at all, at least in the world of small 8bit controllers.

What I appreciate about assembler is even the programming language and tool chain simplicity.

 

I program a lot in assembler and don't miss anything, don't even use all the possibilities that avrasm2 offers ( for example conditional or macro assembly).

Everything you need can be assembled from the small building blocks called controller instruction plus a few assembler instructions.

You can make life beautiful and efficient in assembler too , over time.

 

That what high-level language simplifies in programming immediately complicates it again with numerous language constructions, long, confusing, cryptic expressions, special compiler particularities and options, a lot more development complexity at all. Many high-level questions do not even exist at assembler level. You don't have to declare and convert typed variables, don't make atomic blocks and so on and so on... With datasheet in your hand you know what your controller can do and make the best of it. Good feeling you have everything in your hand right down to the last bit in an easy, direct way. I don't want to miss that. In C, I strangely feel that I have limited ability to act, am bound by many restrictions. On the other hand, the world in assembler is open, with all possibilities wink

 

 

 

Last Edited: Sat. Jun 20, 2020 - 02:08 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Neil, thanks for your post. I had been looking for a simple assembler for a little plc-like bit oriented stack machine i wrote recently, so i had a look at your github repo. Through browsing your repos, i saw reference to haxe - “wtf is haxe?” I thought. So i googled it. I don’t have an immediate need for haxe, but it looks interesting as targetting multi-platforms is a common problem i face.

Such is the beauty of the interwebs - one thing leads to another..............