Making sure I have enough free RAM in my AVR - Page 1
Forum section: electronics / general

author: Stonent
author_rank: Super Contributor
timestamp: December 18, 2013, 10:24:00 am
content: I'm building this for an ATTiny2313A which has 2K of flash and 128 Bytes of RAM. It produced a 3.8K HEX file and the output below. This is my first real project in AVR studio other than just blinking an LED.So if I understand this correctly the output should fit? 1.3K for the program and 44Bytes of RAM in use?I noticed also it said debug, but since I'll be flashing the hex with a third party device I don't need any debug support, so that should be something I can turn off to save space, right? Is 44Bytes of RAM all it needs total, or is that just an estimate?The code I'm using below won't be the final version. I just found a similar project and am basing mine off of it. I may need more space because I'll be adding more custom characters/symbols. So I may need a little more RAM.Also I need to make sure I don't mess up and make it so I can't reprogram the chip if I need to. I prefer to use MOSI,MISO,SCK which is easy to do from an Arduino as a programmer. I've also got a cheap chinese USB programmer that I have managed to get working with AVRDude in the past, it also programs using MOSI,MISO,SCK.Code:------ Build started: Project: Scroll, Configuration: Debug AVR ------Build started.Project "Scroll.cproj" (default targets):Target "PreBuildEvent" skipped, due to false condition; ('$(PreBuildEvent)'!='') was evaluated as (''!='').Target "CoreBuild" in file "C:\Program Files\Atmel\Atmel Studio 6.1\Vs\Compiler.targets" from project "C:\Users\stonent\Documents\Atmel Studio\6.1\Scroll\Scroll\Scroll.cproj" (target "Build" depends on it):Task "RunCompilerTask"C:\Program Files\Atmel\Atmel Studio 6.1\shellUtils\make.exe allBuilding file: .././Scroll.cInvoking: AVR/GNU C Compiler : 3.4.2"C:\Program Files\Atmel\Atmel Toolchain\AVR8 GCC\Native\3.4.2.1002\avr8-gnu-toolchain\bin\avr-gcc.exe" -funsigned-char -funsigned-bitfields -DDEBUG -O1 -ffunction-sections -fdata-sections -fpack-struct -fshort-enums -g2 -Wall -mmcu=attiny2313a -c -std=gnu99 -MD -MP -MF "Scroll.d" -MT"Scroll.d" -MT"Scroll.o" -o "Scroll.o" ".././Scroll.c"Finished building: .././Scroll.cBuilding target: Scroll.elfInvoking: AVR/GNU Linker : 3.4.2"C:\Program Files\Atmel\Atmel Toolchain\AVR8 GCC\Native\3.4.2.1002\avr8-gnu-toolchain\bin\avr-gcc.exe" -o Scroll.elf Scroll.o -Wl,-Map="Scroll.map" -Wl,--start-group -Wl,-lm -Wl,--end-group -Wl,--gc-sections -mmcu=attiny2313aFinished building target: Scroll.elf"C:\Program Files\Atmel\Atmel Toolchain\AVR8 GCC\Native\3.4.2.1002\avr8-gnu-toolchain\bin\avr-objcopy.exe" -O ihex -R .eeprom -R .fuse -R .lock -R .signature "Scroll.elf" "Scroll.hex""C:\Program Files\Atmel\Atmel Toolchain\AVR8 GCC\Native\3.4.2.1002\avr8-gnu-toolchain\bin\avr-objcopy.exe" -j .eeprom --set-section-flags=.eeprom=alloc,load --change-section-lma .eeprom=0 --no-change-warnings -O ihex "Scroll.elf" "Scroll.eep" || exit 0"C:\Program Files\Atmel\Atmel Toolchain\AVR8 GCC\Native\3.4.2.1002\avr8-gnu-toolchain\bin\avr-objdump.exe" -h -S "Scroll.elf" > "Scroll.lss""C:\Program Files\Atmel\Atmel Toolchain\AVR8 GCC\Native\3.4.2.1002\avr8-gnu-toolchain\bin\avr-objcopy.exe" -O srec -R .eeprom -R .fuse -R .lock -R .signature "Scroll.elf" "Scroll.srec""C:\Program Files\Atmel\Atmel Toolchain\AVR8 GCC\Native\3.4.2.1002\avr8-gnu-toolchain\bin\avr-size.exe" "Scroll.elf"textdatabssdechexfilename132030141364554Scroll.elfDone executing task "RunCompilerTask".Task "RunOutputFileVerifyTask"Program Memory Usage:1350 bytes 65.9 % FullData Memory Usage:44 bytes 34.4 % FullDone executing task "RunOutputFileVerifyTask".Done building target "CoreBuild" in project "Scroll.cproj".Target "PostBuildEvent" skipped, due to false condition; ('$(PostBuildEvent)' != '') was evaluated as ('' != '').Target "Build" in file "C:\Program Files\Atmel\Atmel Studio 6.1\Vs\Avr.common.targets" from project "C:\Users\stonent\Documents\Atmel Studio\6.1\Scroll\Scroll\Scroll.cproj" (entry point):Done building target "Build" in project "Scroll.cproj".Done building project "Scroll.cproj".Build succeeded.========== Build: 1 succeeded or up-to-date, 0 failed, 0 skipped ==========Code://-----------------------------------------------------------------------------// BMATRIX: NECKLACE with LED-MATRIX that displays text messages//// Based on Nuts&Volts Jul 2013 article: "Smart Necklace", p. 40//// Author : Bruce E. Hall bhall66@gmail.com// Website : http://w8bh.net// Version : 1.0// Date : 27 Jul 2013// Target : ATTINY4313 or ATTINY2313 microcontroller// Language : C, using AVR studio 6//// ---------------------------------------------------------------------------//// Uses LITE-ON LTP-757G 5x7 LED MATRIX (Column Cathode) Display//// LED to ATTINY4313 b PORTA PORTB PORTD// ---------------------------------- ------------------------// LED FUNCTION to PORT (PIN) 7 - - -// ---------------------------------- 6 - row0 -// Col 0 - PD1 // Row 0 - PB6 5 - row1 -// Col 1 - PA0 // Row 1 - PB5 4 - col2 row6// Col 2 - PB4 // Row 2 - PA1 3 - row3 row5// Col 3 - PB1 // Row 3 - PB3 2 - col4 row4// Col 4 - PB2 // Row 4 - PD2 1 row2 col3 col0// // Row 5 - PD3 0 col1 - -// // Row 6 - PD4//// Since this a column cathode display,// Columns are active LOW; to set a col, PORTx &= ~(1<<bit)// Rows are active HIGH; to set a row, PORTx ~= (1<<bit)//// Fuse settings: 4 MHz osc with 65 ms Delay, SPI enable; *NO* clock/8// ---------------------------------------------------------------------------// DEFINES#define F_CPU 4000000L // run CPU at 4 MHz#define ROWS 7 // LED matrix has 7 rows, 5 columns#define COLS 5#define SCROLLDELAY 15 // delay in cs between column shifts#define FLASHDELAY 17 // delay in cs between symbol flashes#define BEATDELAY 30 // delay in cs between heartbeats#define HEARTCHAR 99#define TEXT1 "I Love You! "#define TEXT2 "Ich Liebe Dich! "// ---------------------------------------------------------------------------// INCLUDES#include <avr/io.h> // deal with port registers#include <avr/interrupt.h> // deal with interrupt calls#include <avr/pgmspace.h> // put character data into progmem#include <util/delay.h> // used for _delay_ms function#include <string.h> // string manipulation routines#include <avr/sleep.h> // used for sleep functions// ---------------------------------------------------------------------------// GLOBAL VARIABLESchar buf; // display buffer; each byte = 1 column// buf is the left-most column (col0)// buf is the right-most column (col4)// buf is a blank column between chars// buf..buf are scrolled onto displayint curCol; // current column; values 0-4const unsigned char FONT_CHARS PROGMEM ={{ 0x00, 0x00, 0x00, 0x00, 0x00 }, // (space){ 0x00, 0x00, 0x5F, 0x00, 0x00 }, // !{ 0x00, 0x07, 0x00, 0x07, 0x00 }, // "{ 0x14, 0x7F, 0x14, 0x7F, 0x14 }, // #{ 0x24, 0x2A, 0x7F, 0x2A, 0x12 }, // ${ 0x23, 0x13, 0x08, 0x64, 0x62 }, // %{ 0x36, 0x49, 0x55, 0x22, 0x50 }, // &{ 0x00, 0x05, 0x03, 0x00, 0x00 }, // '{ 0x00, 0x1C, 0x22, 0x41, 0x00 }, // ({ 0x00, 0x41, 0x22, 0x1C, 0x00 }, // ){ 0x08, 0x2A, 0x1C, 0x2A, 0x08 }, // *{ 0x08, 0x08, 0x3E, 0x08, 0x08 }, // +{ 0x00, 0x50, 0x30, 0x00, 0x00 }, // ,{ 0x08, 0x08, 0x08, 0x08, 0x08 }, // -{ 0x00, 0x60, 0x60, 0x00, 0x00 }, // .{ 0x20, 0x10, 0x08, 0x04, 0x02 }, // /{ 0x3E, 0x51, 0x49, 0x45, 0x3E }, // 0{ 0x00, 0x42, 0x7F, 0x40, 0x00 }, // 1{ 0x42, 0x61, 0x51, 0x49, 0x46 }, // 2{ 0x21, 0x41, 0x45, 0x4B, 0x31 }, // 3{ 0x18, 0x14, 0x12, 0x7F, 0x10 }, // 4{ 0x27, 0x45, 0x45, 0x45, 0x39 }, // 5{ 0x3C, 0x4A, 0x49, 0x49, 0x30 }, // 6{ 0x01, 0x71, 0x09, 0x05, 0x03 }, // 7{ 0x36, 0x49, 0x49, 0x49, 0x36 }, // 8{ 0x06, 0x49, 0x49, 0x29, 0x1E }, // 9{ 0x00, 0x36, 0x36, 0x00, 0x00 }, // :{ 0x00, 0x56, 0x36, 0x00, 0x00 }, // ;{ 0x00, 0x08, 0x14, 0x22, 0x41 }, // <{ 0x14, 0x14, 0x14, 0x14, 0x14 }, // ={ 0x41, 0x22, 0x14, 0x08, 0x00 }, // >{ 0x02, 0x01, 0x51, 0x09, 0x06 }, // ?{ 0x32, 0x49, 0x79, 0x41, 0x3E }, // @{ 0x7E, 0x11, 0x11, 0x11, 0x7E }, // A{ 0x7F, 0x49, 0x49, 0x49, 0x36 }, // B{ 0x3E, 0x41, 0x41, 0x41, 0x22 }, // C{ 0x7F, 0x41, 0x41, 0x22, 0x1C }, // D{ 0x7F, 0x49, 0x49, 0x49, 0x41 }, // E{ 0x7F, 0x09, 0x09, 0x01, 0x01 }, // F{ 0x3E, 0x41, 0x41, 0x51, 0x32 }, // G{ 0x7F, 0x08, 0x08, 0x08, 0x7F }, // H{ 0x00, 0x41, 0x7F, 0x41, 0x00 }, // I{ 0x20, 0x40, 0x41, 0x3F, 0x01 }, // J{ 0x7F, 0x08, 0x14, 0x22, 0x41 }, // K{ 0x7F, 0x40, 0x40, 0x40, 0x40 }, // L{ 0x7F, 0x02, 0x04, 0x02, 0x7F }, // M{ 0x7F, 0x04, 0x08, 0x10, 0x7F }, // N{ 0x3E, 0x41, 0x41, 0x41, 0x3E }, // O{ 0x7F, 0x09, 0x09, 0x09, 0x06 }, // P{ 0x3E, 0x41, 0x51, 0x21, 0x5E }, // Q{ 0x7F, 0x09, 0x19, 0x29, 0x46 }, // R{ 0x46, 0x49, 0x49, 0x49, 0x31 }, // S{ 0x01, 0x01, 0x7F, 0x01, 0x01 }, // T{ 0x3F, 0x40, 0x40, 0x40, 0x3F }, // U{ 0x1F, 0x20, 0x40, 0x20, 0x1F }, // V{ 0x7F, 0x20, 0x18, 0x20, 0x7F }, // W{ 0x63, 0x14, 0x08, 0x14, 0x63 }, // X{ 0x03, 0x04, 0x78, 0x04, 0x03 }, // Y{ 0x61, 0x51, 0x49, 0x45, 0x43 }, // Z{ 0x00, 0x00, 0x7F, 0x41, 0x41 }, // [{ 0x02, 0x04, 0x08, 0x10, 0x20 }, // "\"{ 0x41, 0x41, 0x7F, 0x00, 0x00 }, // ]{ 0x04, 0x02, 0x01, 0x02, 0x04 }, // ^{ 0x40, 0x40, 0x40, 0x40, 0x40 }, // _{ 0x00, 0x01, 0x02, 0x04, 0x00 }, // `{ 0x20, 0x54, 0x54, 0x54, 0x78 }, // a{ 0x7F, 0x48, 0x44, 0x44, 0x38 }, // b{ 0x38, 0x44, 0x44, 0x44, 0x20 }, // c{ 0x38, 0x44, 0x44, 0x48, 0x7F }, // d{ 0x38, 0x54, 0x54, 0x54, 0x18 }, // e{ 0x08, 0x7E, 0x09, 0x01, 0x02 }, // f{ 0x08, 0x14, 0x54, 0x54, 0x3C }, // g{ 0x7F, 0x08, 0x04, 0x04, 0x78 }, // h{ 0x00, 0x44, 0x7D, 0x40, 0x00 }, // i{ 0x20, 0x40, 0x44, 0x3D, 0x00 }, // j{ 0x00, 0x7F, 0x10, 0x28, 0x44 }, // k{ 0x00, 0x41, 0x7F, 0x40, 0x00 }, // l{ 0x7C, 0x04, 0x18, 0x04, 0x78 }, // m{ 0x7C, 0x08, 0x04, 0x04, 0x78 }, // n{ 0x38, 0x44, 0x44, 0x44, 0x38 }, // o{ 0x7C, 0x14, 0x14, 0x14, 0x08 }, // p{ 0x08, 0x14, 0x14, 0x18, 0x7C }, // q{ 0x7C, 0x08, 0x04, 0x04, 0x08 }, // r{ 0x48, 0x54, 0x54, 0x54, 0x20 }, // s{ 0x04, 0x3F, 0x44, 0x40, 0x20 }, // t{ 0x3C, 0x40, 0x40, 0x20, 0x7C }, // u{ 0x1C, 0x20, 0x40, 0x20, 0x1C }, // v{ 0x3C, 0x40, 0x30, 0x40, 0x3C }, // w{ 0x44, 0x28, 0x10, 0x28, 0x44 }, // x{ 0x0C, 0x50, 0x50, 0x50, 0x3C }, // y{ 0x44, 0x64, 0x54, 0x4C, 0x44 }, // z{ 0x00, 0x08, 0x36, 0x41, 0x00 }, // {{ 0x00, 0x00, 0x7F, 0x00, 0x00 }, // |{ 0x00, 0x41, 0x36, 0x08, 0x00 }, // }{ 0x08, 0x08, 0x2A, 0x1C, 0x08 }, // ->{ 0x08, 0x1C, 0x2A, 0x08, 0x08 }, // <-{ 0xFF, 0x41, 0x5D, 0x41, 0xFF }, // 096: psycho 2{ 0x00, 0x3E, 0x22, 0x3E, 0x00 }, // 097: psycho 1{ 0x06, 0x15, 0x69, 0x15, 0x06 }, // 098: nuke{ 0x0C, 0x1E, 0x3C, 0x1E, 0x0C }, // 099: solid heart{ 0x0C, 0x12, 0x24, 0x12, 0x0C }, // 100: outline heart{ 0x0A, 0x00, 0x55, 0x00, 0x0A }, // 101: flower{ 0x08, 0x14, 0x2A, 0x14, 0x08 }, // 102: diamond{ 0x07, 0x49, 0x71, 0x49, 0x07 }, // 103: cup{ 0x22, 0x14, 0x6B, 0x14, 0x22 }, // 104: star2{ 0x36, 0x36, 0x08, 0x36, 0x36 }, // 105: star3{ 0x0F, 0x1A, 0x3E, 0x1A, 0x0F } // 106: fox};// ---------------------------------------------------------------------------// INTERRUPT SERVICE ROUTINE//// Function: Light a column on the LED matrix display, according to contents// of display buffer. buf = leftmost column; buf = rightmost//// This routine is called about 390 times per second, yielding a refresh// rate for the whole display of 390/5 = 78 frames per second.ISR (TIMER0_COMPA_vect){if (++curCol >= COLS) // advance column countercurCol = 0;// turn off all LEDS, by taking cathode (column) pins highPORTA = 0x01;PORTB = 0x16;PORTD = 0x02;// turn on individual row bits in this columnchar i = buf;if (i & _BV(0)) PORTB |= _BV(6);if (i & _BV(1)) PORTB |= _BV(5);if (i & _BV(2)) PORTA |= _BV(1);if (i & _BV(3)) PORTB |= _BV(3);if (i & _BV(4)) PORTD |= _BV(2);if (i & _BV(5)) PORTD |= _BV(3);if (i & _BV(6)) PORTD |= _BV(4);// turn selected column onswitch(curCol){case 0: PORTD &= ~_BV(1); break;case 1: PORTA &= ~_BV(0); break;case 2: PORTB &= ~_BV(4); break;case 3: PORTB &= ~_BV(1); break;case 4: PORTB &= ~_BV(2); break;}}// ---------------------------------------------------------------------------// PROGRAM INITIALIZATION CODEvoid init (){ // set output pinsDDRA = 0x03; // 0000.0011DDRB = 0x7E; // 0111.1110DDRD = 0x1E; // 0001.1110// setup Timer/Counter0 for LED refreshTCCR0A = _BV(WGM01); // Set CTC modeTCCR0B = _BV(CS02); // Set prescaler clk/256 = 15625 HzOCR0A = 40; // 15625/40 = 390 interrupts/sec (5 cols = ~78fps)TIMSK = _BV(OCIE0A); // Enable T/C 0A interruptMCUCR = 0x30; // 0011.0000 (sleep enabled, power down)WDTCR = 0x18; // 0001.1000 set WD turn-off and WD enable bitsWDTCR = 0x10; // 0001.0000 reset WD enable to complete WD turnoffsei(); // enable global interrupts}void DelayCS(int cs)// Delays CPU for specified time, in centiseconds (1/100 sec)// Calling _delay_ms in a routine prevents inlining, reducing code size,// at the expense of slight timing inaccuracies.{for (int i=0; i<cs; i++)_delay_ms(10);}void DelaySecond(){DelayCS(100);}// -------------------------------------------------------------------------// CHARACTER SCROLLING ROUTINESvoid ShiftLeft()// shifts the entire display buffer one column to the left{for (int i=0; i<11; i++){buf = buf[i+1]; // buf on left; buf on right} // each element represents a column} // buf[0..4] are only elements visiblevoid Scroll()// scrolls a character onto the display{for (int i=0; i<COLS+1; i++){ShiftLeft(); // shift display 1 column to leftDelayCS(SCROLLDELAY); // and wait a while} // repeat 5x for whole character}void LoadSymbol(int index)// loads a font symbol into the non-visible part of display buffer{for (int y = 0; y < COLS; y++){buf[y+5] = pgm_read_byte(&(FONT_CHARS));}buf = 0x00; // add character spacing}void MakeVisible()// copies char from non-visible to visible part of buffer{for (int i=0; i<COLS; i++){buf = buf[i+5];}}void DisplaySymbol(int index)// loads a font symbol into the visible display buffer{LoadSymbol(index);MakeVisible();}void ScrollText(const char *text)// scrolls given text across matrix, right to left{for (int i=0; i<strlen(text); i++){LoadSymbol(text-' '); // get charScroll(); // and scroll it} // repeat for all chars}void DisplayText(const char *text)// displays given text, one character at a time{for (int i=0; i<strlen(text); i++){DisplaySymbol(text-' '); // display charDelaySecond(); // wait a while} // repeat for all chars}// -------------------------------------------------------------------------// ANIMATION ROUTINESvoid FlashHeart(){DisplaySymbol(HEARTCHAR); // flash heart onDelayCS(FLASHDELAY); // waitDisplaySymbol(0); // flash heart offDelayCS(FLASHDELAY); // wait}void HeartBeat(){FlashHeart(); // heart on/offFlashHeart(); // heart on/offDelayCS(BEATDELAY); // waitFlashHeart(); // do it again!FlashHeart();DelayCS(BEATDELAY);}// -------------------------------------------------------------------------// MAIN PROGRAM LOOPvoid main_loop (){while(1){for (int i=100; i<107; i++){DisplaySymbol(i); // display a fun symbolDelaySecond();DelaySecond();HeartBeat(); // heartbeatsHeartBeat();DisplayText(TEXT1); // display text1DelaySecond();HeartBeat(); // more heartbeatsScrollText(TEXT2); // scroll text2DelaySecond();} // repeat 7 timessleep_cpu(); // turn off display}}// ---------------------------------------------------------------------------// MAINint main (void){init(); // set up ports, CPU registersmain_loop(); // do the display, then sleepreturn (0); // that's all, folks!}

author: Rerouter
author_rank: Super Contributor
timestamp: December 18, 2013, 10:32:00 am
content: now i am no software expert so hopefully someone else can validate this,I believe your going to use more than 44bytes of RAM as that is only the static usage, such as strings and global variables that are loaded into memory first thing, not taking into account your function specific variables, like the ints in your while loops,(still in the back of my head it sounds funny describing RAM in bytes)

author: Stonent
author_rank: Super Contributor
timestamp: December 18, 2013, 10:35:02 am
content: Quote from: Rerouter on December 18, 2013, 10:32:00 amYeah that's what I wasn't really sure about, whether it truly was giving me an accurate amount or just what will be needed as a minimum. Looking back I probably should have went with the ATTiny4313A but I had ordered the parts long before the project came along.

author: DRT
author_rank: Regular Contributor
timestamp: December 18, 2013, 10:36:41 am
content: The majority of your RAM usage is here:#define TEXT1 "I Love You! "#define TEXT2 "Ich Liebe Dich! "You will need to modify your DisplayText() function, but you can put these strings in program space too as you have with your font data, eg:const char string_1[] PROGMEM = "I Love You! ";Also, you might try optimisation switch -Os instead of -O1 as your code will likely be smaller with no real speed impact.

author: Stonent
author_rank: Super Contributor
timestamp: December 18, 2013, 11:08:22 am
content: Quote from: DRT on December 18, 2013, 10:36:41 amI was an avid Gentoo Linux user for a few years and fiddling with compiler flags was always fun. I remember a lot of discussion on GCC optimization levels. I thought there was something with Os where it traded program size for ram or vice versa. But that was a while back and with x86 GCC.

author: Bored@Work
author_rank: Super Contributor
timestamp: December 18, 2013, 01:08:12 pm
content: The -O1 is likely because you did compile with the Debug configuration. Somewhere in that Studio mess should be a switch where you can change to a production configuration. That configuration should include more aggressive compiler optimization settings.

author: AlfBaz
author_rank: Super Contributor
timestamp: December 18, 2013, 02:55:41 pm
content: I see -g2 as one of your compiler flags which means there's a bunch of debugging info in the output. If you manage to find where to turn off debugging there should be no -g option at all on the command line. There may also be extra code in there because the symbol DEBUG is defined on the command line with the -DDEBUG. What this means is that sections of code along the lines of #ifdef DEBUG ... will also be added to your code

author: Kremmen
author_rank: Super Contributor
timestamp: December 18, 2013, 03:44:26 pm
content: You can (in Studio 6.1) go to the Project /  Properties and from the Build header change Debug to Release but it won't change anything in this case (oh it chages the compiler flags allright). All the debug info (or not) will be in the .elf file but none of it will be flashed to the device. Both options will produce exactly the same code and static ram size.P.S. Offhand and without checking - yes your ram is fine. You have used a third of the available, no way does your stack grow so large in such a simple piece of code that you need to start worrying about that.

author: Jeroen3
author_rank: Super Contributor
timestamp: December 18, 2013, 11:23:34 pm
content: RAM usage is usually divided in two parts: Static / StackStatic is statically allocated, for example: your "char buf; int curCol;" and if the optimizer is enabled all variables in main() block (not nested blocks). And all those vars marked with "static", which gives them one fixed memory address forever,not pushing it to global scope though.Stack is temporary storage, return address of function call or ISR, function parameters/returns and temporary variables that do not fit in the cpu registers.You can save an extra 2 bytes (16 bit address) of stack by declaring your main as non-returnable. The return address to the assembly reset handler is not pushed to stack this way.__attribute__((OS_main))int main(void);And your max stack usage is at worst case the max function call depth times 2 plus all arguments.However, the compiler usually puts arguments and returns in the registers, if it fits.Also, #defines never make it to the chip, they don't even reach the compiler. If the define forms a literal (inline string/value) in the preprocessor, it is usually stored in flash and copied to ram on boot time(between the reset handler and the main routine). However, this depends on the compiler and optimizer. This can seriously damage performance on AVR due to the architecture of the chip.Also, you are using an type int for curCol which only goes from 0 to 4, you waste one full byte and double the time working with that. Make that an uint8_t, (unsigned char) 8 bits instead of 16 bits.Remember you have an 8 bit mcu which is very good with 8 bits, less good with more, a disaster with floating point.*The reset handler is where code starts, it is well hidden in the atmel toolchain. But when reading raw assembly you can find it.

author: Stonent
author_rank: Super Contributor
timestamp: December 19, 2013, 03:07:08 am
content: Quote from: Jeroen3 on December 18, 2013, 11:23:34 pmI find all of this fascinating. Right now the code is exactly as the original author wrote with one change, he omitted 1 semicolon which I fixed. I don't think my changes will noticeably increase the code size, I will mainly be adding some custom characters, so only a few bytes of progmem will be eaten up by that, I think.And also will put some randomization in the custom characters displaying the different symbols I've come up with.

author: AlfBaz
author_rank: Super Contributor
timestamp: December 19, 2013, 01:20:27 pm
content: Quote from: Kremmen on December 18, 2013, 03:44:26 pmI found this interesting and decided to investigate further.The elf files exhibit a marked difference in size between debug and release but the resultant binary file after having the elf file passed through objcopy is exactly the same size and content. So clearly the elf file contains all the required debugging info to be used by the debugger on the host but only the bare code is programmed to the target... Learn something new every dayMakes me wonder why I bother having debug and release versions to start with. Is it fair to say that for embedded systems it only matters on some architectures where extra onchip resources are used depending on your debugging paradigm?As for defining debugging symbols, they definitely make a difference if you have debugging constructs in your code, but depending on what you have set up it could go both way with regards to size

author: madires
author_rank: Super Contributor
timestamp: December 19, 2013, 01:45:47 pm
content: // __heap_start is declared in the linker scriptextern unsigned char __heap_start;uint16_t free_sram = SP - (uint16_t) &__heap_start;

author: hans
author_rank: Super Contributor
timestamp: December 19, 2013, 06:21:36 pm
content: The ELF contains information for the debugger to translate program addresses (the machine code) to your C code. It also knows this way what is stored on the stack and CPU registers at any given point, so your debugger can give prettier readouts.I recommended a "Debug" profile with initially no optimisations at all. The compiler may optimize some steps so single stepping code isn't as detailed. Variables may also become 'unavailable', especially those pushed onto the stack.In addition: if you turn up optimizations you may get issues running code. Like the compiler suddenly makes some assumptions which are incorrect, and you end up abusing 'volatile'.Regarding all RAM usage: any variable defined outside a method is statically allocated, and is known by the compiler how much space it occupies. Any variable defined inside functions, including function arguments & return values, is pushed and popped on/from the stack. The stack grows from the back of memory space to the front. If you call functions to deep (too many layers on layers..) and run out it will override over the statically allocated variables and overwrite them.It gets even trickier if you use malloc (which I don't recommended for controllers with little RAM): you have a 'heap' area which grows from the end of your static RAM memory towards the stack. These two can also collide and cause issues.Maybe a image borrowed from Google Images helps:So the RAM usage is only an estimate: it's the RAM used by 'code'.As said, I don't recommended using the heap.The stack is unpredictable, but can be minimized by avoiding too many levels of code and too many function arguments.

author: Stonent
author_rank: Super Contributor
timestamp: December 23, 2013, 08:22:34 am
content: Well I finally got a chance to load the hex file, and well it flickers really bad and some of the characters seem messed up. I've got all my wires in the right place, and every once in a while, putting 5V to it fixes it or dropping to a CR2032 battery which is significantly dimmer seems to work as well, but the 3.3v supply from my Arduino seems to mess it up.So the dimness of the CR2032 will be a problem, anyone have any other battery ideas that are small but with a bit more kick than the CR2032? I seem to remember some sort of battery that's a little wider than a AAA but shorter. The datasheet on the ATTiny2313A says 1.8 to 5.5 so I can go higher. Small and discreet though is what I need or the necklace will be too bulky.I'm guessing where the speed is defined is not actually setting the speed in the code, just what the program thinks the speed is. Either way I need to kick it up. Playing with the number in the software just seems to make it cycle between parts faster but still bad flicker.

author: Bored@Work
author_rank: Super Contributor
timestamp: December 23, 2013, 10:30:17 am
content: Quote from: Stonent on December 23, 2013, 08:22:34 amYes, F_CPU does not define the CPU clock frequency. It just needs to be set to whatever the clock frequency is.Depending on type and age of the AVR, the CPU clock source and frequency is set by a combination of fuses and programmable registers, in conjunction with an external oscillator, an external crystal, or the internal RC oscillator.Setting fuses to the wrong clock source is probably the most common way how beginner "brick" an AVR. So be careful when you play with the clock-related fuses.(BTW I recommend against those unbrick fuse doctor gimmicks. One costs more than a few AVRs and if you really want to unbrick an AVR with a wrong clock source fuse, instead of just throwing it away, almost any source of a 1 MHz, rectangular, logic level signal will do.)

author: Kremmen
author_rank: Super Contributor
timestamp: December 23, 2013, 10:49:01 am
content: It could be that the actual clock has not been set properly, although the sensitivity to voltages is a bit disturbing. But do as Bored says; it is pretty easy to from the Studio if you have a live connection from there (which i have always recommended). Just set an internal RC oscillator to something reasonable.Other than that the led matrix control in the interrupt service routine is done amateurishly - you cannot easily come up with a slower way than that to set up the I/O pins. The worst case runtime @4MHz clock is 20,25 us (81 cycles). Maybe not a problem in this case but you need better than that if there is much more data to set up.But first make sure the chip is actually running at the clock you think it is.

author: Psi
author_rank: Super Contributor
timestamp: December 23, 2013, 12:30:31 pm
content: Yep, screwing with the clock bits can be a pain, as you have to find an external clock to get the chip running again.But the only AVR fuse bits you really have to be careful with are;- RSTDISBL, It permanently removes the reset pin functionality, without it you cant talk to the chip over SPI for serial reprogramming so you cant change it back. (Need parallel programmer to fix it)- SPIEN, It permanently disables SPI serial reprogramming, same effect as above. You cant do anything unless you have a parallel programmer.It is possible though, to wire up 16 switches to the control lines and data bus. Then manually reset the fuses by toggling switches to send the right commands. Basically you become the parallel programmerIt is, after all, how early computers were programmed.There was a website somewhere which had an example of someone doing this.Its not as hard as it sounds, you just follow the datasheet programming instructions and prey you've not made any mistakes.

author: Unknown
author_rank: Unknown
timestamp: December 23, 2013, 12:47:46 pm
content: Quote from: Psi on December 23, 2013, 12:30:31 pmIf you manage to set it to low frequency crystal, you actually need a 32 kHz watch crystal, it won't just accept a 1 MHz square wave. And obviously the ISP frequency well need to be lower than 8 kHz or so to work with a 32 kHz clock.Quote from: Psi on December 23, 2013, 12:30:31 pmFortunately most if not all AVRs refuse to change SPIEN via ISP. You can change both SPIEN and JTAGEN via JTAG, however.

author: Stonent
author_rank: Super Contributor
timestamp: December 23, 2013, 07:35:57 pm
content: The only pins I need are the center six to drive the LED matrix and of course top right and bottom left for power. I want to keep SPI and RST available though. I have some spare 2313A chips.The chip seems to program just fine with the LED matrix connected. I can program at 19200 using AVRDUDE, but 38400 gets me a timeout. As far as I know, the chip is running at its factory setting, but I think Div/8 may be set by default.This is the first time working with the Tiny2313A, before that I had used the 45 and 85 but used an Arduino plugin or whatever that you could use to automatically set the target with 1/4/8MHz.Some further thinking has me remembering that this CR2032 may not be new. It was in a small bag, but now that I think about it, I may have taken the one out of the bag and put it in my car remote and put the old one in the bag.With the occasional corruption of the display, I wonder if that's a result of a brown out? I wonder if a small capacitor may help with voltage dips?

author: Jeroen3
author_rank: Super Contributor
timestamp: December 23, 2013, 09:24:34 pm
content: Quote from: Psi on December 23, 2013, 12:30:31 pmFortunately most if not all AVRs refuse to change SPIEN via ISP. You can change both SPIEN and JTAGEN via JTAG, however.Most disappointing they don't check chip ID before programming and fusing the wrong bits when you've selected the wrong file...

author: Jeroen3
author_rank: Super Contributor
timestamp: December 23, 2013, 09:25:27 pm
content: Quote from: alm on December 23, 2013, 12:47:46 pmMost disappointing they don't check chip ID before programming and fusing the wrong bits when you've selected the wrong file...

author: Stonent
author_rank: Super Contributor
timestamp: December 24, 2013, 12:31:10 am
content: Ok well I got the fuses set and got the flickering gone. However, I think it browned-out during one of my numerous reprogrammings of a tweaked program and "bricked" the chip because now it won't respond any more.Here's the other strange thing. The chip seems now to run great at 3.3V but when I bump it up to 5V, it just flickers the LEDs.That and all my symbols I created using an excel file designed for exporting HEX from a 5x8 grid (I'm using a 5x7 matrix) I had started from 8 and not 0 unbeknownst to me, so all the characters have one blank row and are shifted down.That and the characters inside the program are flipped 180 degrees from what the other one was, so basically:Have to change from 3.3 to 5 to program otherwise I start getting programming errors.After programming change from 5 back to 3.3 or it will just flicker.Need to flip all my symbols 180 degrees and shift back one spot.Anyone know of an easy way to correct these?The "Tree 1" with the comment marker is one that is wrong, Tree 1 without the comment marker is corrected.All the ones underneath that need to be fixed.Code://{ 0x28, 0x78, 0xFE, 0x78, 0x28 }, // 107: Tree 1{ 0x14, 0x1E, 0x7F, 0x1E, 0x14 }, // 107: Tree 1{ 0x10, 0x38, 0xEE, 0x38, 0x10 }, // 108: Star 1{ 0x10, 0x54, 0xEE, 0x54, 0x10 }, // 109: Star 2{ 0x20, 0x20, 0xFE, 0x20, 0x20 }, // 110: Cross{ 0x10, 0x38, 0x6C, 0x38, 0x10 }, // 112: Small Star 1{ 0x38, 0x54, 0xEE, 0x54, 0x38 }, // 113: Ornament 1{ 0x80, 0x8C, 0x64, 0x74, 0xFE }, // 114: Sleigh{ 0x54, 0x38, 0xEE, 0x38, 0x54 }, // 115: Big Flake 1{ 0x54, 0x28, 0xBA, 0x28, 0x54 }, // 116: Big Flake 2{ 0x1E, 0x32, 0x76, 0x32, 0x9E }, // 117: Manger{ 0x24, 0x6C, 0xFE, 0x6C, 0x24 }, // 118: Tree 2{ 0xD6, 0xD6, 0xFE, 0xD6, 0xD6 }, // 119: Present 1{ 0xFE, 0xD6, 0xFE, 0xD6, 0xFE }, // 120: Present 2{ 0x3E, 0x52, 0xBE, 0x2A, 0x3E }, // 121: Church{ 0x86, 0x22, 0xA2, 0x22, 0x26 }, // 122: Snow Face{ 0xFE, 0x32, 0xF2, 0x32, 0xFE }, // 123: Crown{ 0x5E, 0x6A, 0xBE, 0x6A, 0x5E }, // 124: Present 3{ 0x10, 0x28, 0x54, 0x28, 0x10 } // 125: Small Star 2

author: Stonent
author_rank: Super Contributor
timestamp: December 24, 2013, 01:35:42 am
content: Darn, thought I had it figured out in Excel but it drops the ending bit when really I would need that ending bit shifted to the next column.

author: Stonent
author_rank: Super Contributor
timestamp: December 24, 2013, 05:06:28 am
content: Ok manually flipped and moved my stuff around. A few graphical glitches keep coming up but I think I can hopefully work those out.Still strange that it has to program at 5V, but has to run at 3.3V

author: leb120
author_rank: Contributor
timestamp: December 24, 2013, 09:16:32 am
content: Looked at the website in the code in your OPhttp://w8bh.net. The PDF going into the construction of the necklacehttp://w8bh.net/avr/Necklace1.pdfhe doesn't seem to be using any current limiting in series with the led matrix's columns or rows (such as resistors). If i'm not mistaken that means he is using the internal resistance of the CR2032 battery to limit current and not fry anything; this does work and is used in throwieshttp://www.instructables.com/id/E9D2ZJ3FG0EP286JEJ(yes instructables sucks).Looking at the datasheet for the LED matrix mentioned in the above PDF he is using a LiteOn LTP-757 Greenhttp://optoelectronics.liteon.com/upload/download/DS-30-97-210/P_100_P2057AG.pdf. The Datasheet specs 2.1 typical at 20mA, but I would guess they are not pulling the full 20mA (as you mentioned they are dim) this would have an even smaller voltage drop maybe even getting near the minimum of the micro.I believe without current limiting resisters between micro and an LED the LED will drive the voltage of the micro to it's Vd theoretically pulling a lot of current to do so, working like a zener diode based voltage regulator. Again with the internal resistance of the CR2032 the input voltage to the micro is just held at Vd when the LEDs are being driven.Now, if you were to use a 3.3v or 5v source with a decent supply current it seems like it would fry your LEDs basically like driving the LEDs directly, again no resisters anywhere; or the micro itself is you current limiting resistor in which case it will probably be fried.Ok, so you want the full brightness of the display and you have a decent supply and are pushing the LEDs at their rated ~50 mA at 1/5 duty cycle.7 led could be on at any given time so 50mA * 7 leds = 350mAThis is well outside the spec of the micro's pins 40mA per I/O pin and 200mA on Vcc and Gnd pins.when you have 7 leds on at a time:50 mA is being sinked through 7 I/O pins driving the rows (each rated for only 40 mA)the full 350mA is being sourced by 1 I/O pin driving the column (rated for only 40 mA)and 350mA is being pulled through both the Vcc and Gnd pins (rated for 200mA)You would have to employ some transistors, buffers, or something to get anywhere near the rated brightness of the LED matrix.Multiplication is a pain, 5 LEDs no problem, 7 LEDs no problem, 5x7 = 35 LEDs that a lot of LEDs for a micro to drive solo.