CS453 Colorado State University ========================================== Meggy Jr Simple Library and avr-gcc ========================================== ----------------- Plan for today Look at some of the cool MiniSVG examples you all wrote Meggy Jr Simple library avr-gcc tool chain and provided Makefile ATmega328p chip avr assembly ----------------- Meggy Jr Simple Meggy Jr Simple concepts and their interface LED screen 8x8 grid x coordinate goes from left to right, 0 through 7 y coordinate goes from bottom to top, 0 through 7 Colors are single integers Auxiliary LEDs SetAUXLEDs( number ); Least significant bit for number represented by left-most LED. Buttons GetButtons() returns a byte. B is represented with least significant bit, value 1. A with 2. Up with 4. Down with 8. Left with 16. Right with 32. Two options, no opinion yet on which is better (1) if (4 & GetButtons()) (2) CheckButtonsDown(); if (Button_Up) Speaker Takes a tone frequency divisor and a duration in milliseconds. -> show the tone definitions in MeggyJrSimple.h and frequency equation exercise-MeggyJrSimple.cpp Logistics, or Interfaces? - layered on top of Meggy library Color indices appear to be one of the main reasons. - what it adds Color indices Pre-defined tone divisors Nice programming guide. =) - what we add to it delay_ms GetButtons ------------------ avr-gcc tool chain and provided Makefile http://www.cs.colostate.edu/~cs453/yr2011/MeggyJavaInfo/building-for-meggy.html - there have been some minor modifications to MeggyJrSimple.h and MeggyJrSimple.cpp, so go get the new ones - how to take out optimization flag in Makefile - the key difference between our build process and Arduino's ----------------- ATmega328p chip (slide 3) Terminology http://www.engineersgarage.com/articles/avr-microcontroller, really useful Uses a Harvard Architecture Separate memory and data Thriving programming community email and website resources http://www.avrfreaks.net/ http://www.arduino.cc/ --------------- Why is it useful to be comfortable with assembly? -programs for embedded processors are sometimes written in assembly -some of these low-level concepts are needed to implement drivers -useful to understand an example of how data is organized in memory because might have to use a hexdump to do some nasty debugging some day -translating to C avoids the joy of learning how the run-time stack works in gory detail =================== avr assembly ISA: instruction set architecture, interface machine provides - ld-store architecture -> draw picture of abstraction: memory (data, text, heap, stack), registers, CPU - only load-store operations have access to memory - AVR has some stack architecture features such as push and pop -> draw stack architecture alternative where operations only performed on a stack -------------------- Loads and Stores in r28,__SP_L__ // putting the stack pointer into r29:r28 in r29,__SP_H__ ldd r24, Y+3 // load byte that is 3 bytes from address in r29:r28 // r24 = M[r29:r28 + 3] std Y+1, r24 // store value in r24 to address r29:r28+1 // M[r29:r28 + 1] = r24 ------------------- add r30, r24 // perform some addressing arithmetic into r31:r30 add r31, r25 ldd r24, Z+0 // load byte at the address in r31:r30 -------------------- Registers http://www.nongnu.org/avr-libc/user-manual/FAQ.html caller saved r18-r27, r30-r31 callee saved r2-r17, r28-r29 Y is 29:28, used for stack pointer Z is 31:30, can be used for other pointers -------------------- Pushes and Pops -> Why do we need a run-time stack? What feature in almost all programming languages requires something like the run-time stack? Dated hint: Fortran 77 does not have this feature. - Talk about what pushes and pops do in AVR. -------------------- Learning AVR with avr-gcc General approach For each language feature, write an example .cpp program, compile it to a .s file, and then figure out the .s file. Examples: PA3bluedot.cpp and PA4buttondot.cpp make PA3bluedot.s make PA4buttondot.s TRICKY BITS (1) Will want to try with optimization for space on and off -> Show how to change the compiler options in the Makefile (2) The AVR simulator Ryan is writing called MJSIM will NOT simulate ALL of the AVR instructions. Your compiler will be required to generate a subset of instructions. --> Look at the PA4Cyclon.java.s example sent out last night and run it on device. ----------------------------------------------------- Probable AVR instruction subset See http://www.atmel.com/dyn/resources/prod_documents/doc0856.pdf for details on these instructions. --> show them these instructions ----------------- main prologue and epilogue __SREG__ = 0x3f __SP_H__ = 0x3e __SP_L__ = 0x3d __tmp_reg__ = 0 __zero_reg__ = 1 .global __do_copy_data .global __do_clear_bss .text .global main .type main, @function main: push r29 push r28 in r28,__SP_L__ in r29,__SP_H__ /* prologue: function */ call _Z18MeggyJrSimpleSetupv /* Need to call this so that the meggy library gets set up */ ... /* epilogue start */ endLabel: jmp endLabel ret .size main, .-main -------------------------------------------- examples of other instructions the simulator will handle pop r24 // pop byte from RTS and put into r24 push r25 // push byte in r25 onto RTS ldi r24, 42 // load constant 42 into r24 ldi r22, lo(352) // load 8 lo bits of 352 into r22 ldi r23, hi(352) // load 8 hi bits of 352 into r23 muls r22, r18 // r1:r0 = r22 * r18 add r22, r18 // r22 = r22 + r18 adc r23, r19 // add with carry, r23 = r23 + r19 + C sub r22, r18 // r22 = r22 - r18 sbc r23, r19 // subtract with carry, r23 = r23 - r19 - C and r22, r18 // r22 = r22 & r18, bitwise AND cp r24, r18 // compare two bytes and set condition codes brne L1 // branch if not equal to label cp r24, r18 // compare lo bits cpc r25, r19 // compare hi bits with carry from lo bits breq L5 // conditional branch, this one is branch if equal jmp L2 // jump to label anywhere in memory L3: // label to jump to call funcname // call function, funcname is just a label in r28,__SP_L__ // putting the stack pointer into r29:r28 in r29,__SP_H__ ldd r24, Y+3 // load byte that is 3 bytes from address in r29:r28 // r24 = M[r29:r28 + 3] std Y+1, r24 // store value in r24 to address r29:r28+1 // M[r29:r28 + 1] = r24 ------------------------------ calling convention reference: http://www.nongnu.org/avr-libc/user-manual/FAQ.html - calling convention is interface between caller and callee - callers have to pass parameters to callee - callees have to pass return values to caller - callers and callees have to agree who is storing what registers - stack pointer and frame pointer are used to keep track of the runtime stack Arguments - allocated left to right, r25 to r8 r24, r25 parameter 1, only use r24 if just a byte parameter r22, r23 parameter 2 r20, r21 parameter 3 r18, r19 parameter 4 ... r8, r9 parameter 9 Return values 8-bit in r24 (not r25!), 16-bit in r25:r24, up to 32 bits in r22-r25, up to 64 bits in r18-r25. 8-bit return values are zero/sign-extended to 16 bits by the called function (unsigned char is more efficient than signed char - just clr r25). Arguments to functions with variable argument lists (printf etc.) are all passed on stack, and char is extended to int. Who saves what registers caller saved r18-r27, r30-r31 callee saved r2-r17, r28-r29 Stack pointer and frame pointer ---------------------------------------- Allocating space on the heap with malloc See PA7rainbow.cpp and PA7rainbow.s example. void* malloc(int n): Allocates n consecutive bytes in the heap and returns the address of the first byte allocated. Reference: http://www.nongnu.org/avr-libc/user-manual/malloc.html ------------------------ mstrout@cs.colostate.edu, 2/10/11