Flashlight Firmware Repository

The attiny13a has two PWM channels which share a counter.

Got it, thanks for answering. :slight_smile: And looking at that page, I understand how flash and eeprom works but what about ram? It says 64 byte available. Should I start counting variables? Basically one byte integers I guess.

RAM gets weird. You may have to keep track of it manually, because exceeding the limit mostly just results in really bizarre behavior.

If you find your code doing things which make absolutely no sense, it might be time to check your RAM usage. I ran into issues like this when I was still using a 32-byte array in RAM to mirror the eeprom, and added some other sizable arrays on top of that. But ever since dumping the eeprom mirror and moving static arrays to progmem (ROM), I haven’t had any issues at all.

Most processors map all the different memory spaces into one linear space, so, like… 0 through 999,999 are RAM and 1,000,000 through 1,999,999 are ROM and 2,000,000 through 2,999,999 are eeprom, and so on. But the attiny doesn’t do this. All the different memory spaces overlap (use the same address space) and are instead accessed through different instructions. So, if you put an array in ROM you must use special functions to access it. The compiler doesn’t understand this though, and will happily let you access the portions of RAM which have the same address as ROM if you forget and use the wrong syntax. The attiny also doesn’t appear to segfault or otherwise crash when accessing RAM which doesn’t exist, so instead it just behaves very strangely.

So, long answer to a short question, but… yes, you might occasionally have to count variables in your head. I’m not aware of a debugger or emulator which can check these things automatically, but I haven’t really looked.

The standard Star firmware uses a 32 byte array for EEPROM block reading (was a while ago I checked, might have changed). This eats half of your memory already. As ToyKeeper already wrote, if you use more RAM space than is available some really funky things can start to happen. The first thing you can do to check is temporarily make that array much smaller while debugging problems, like 8 or even 4 bytes.

If RAM space does turn out to be your problem, you could re-write that EEPROM wear leveling routine to use the 8 byte array and loop through the EEPROM area until the mode byte is found. Then you can use the entire 64 byte EEPROM area instead of only half as the standard Star does/did. Not only RAM space is saved, wear leveling is improved too (although probably not an issue). It will however cost a little more in valuable programming space so it might not be worth it in the end, at least on the 13A. I use this method on the 84 and 85, programming space is not as much of a concern with them.

Thanks for the help, again. :slight_smile: So I’ve been trying to learn how ram works, checking the avrfreaks site and I found a patch to avr-size but it only counts global and static variables, which is understandable. It counts 42 (I can only find 41 though) bytes and yes 32 of those are the eeprom array. I found out about how PROGMEM works too. And local variables are also easy to count, not that many of them anyway. But how about constants that are not variables (c noob here)? If you got while(1) I take it the 1 is not put in ram. But if you got while(i < 1) is the 1 put in ram then?

Nope - the "1" won't be in RAM, but the "i" variable would be in RAM, assuming it's not optimized out and used only from a register. This is generally what happens...

I see thanks. Yes the “i” will be put in ram if it’s a local variable, so much I get by now. Then I think I’m all good to go then, when my flasher arrives.

You can actually eliminate the eeprom mirror entirely, and IIRC it doesn’t really increase ROM usage. I’ve been doing it that way lately. I also just found out that avr-size can do a lot of the counting for you if you run it like “avr-size -C —mcu=attiny13 foo.elf”. However, you still have to leave room for the stack, not just the variables. It’s not usually very big on a processor this small, but some temporary data still gets stored in RAM on top of the explicitly-declared variables. For example, the function call stack, and any expressions which don’t fit entirely into registers.

The extra info in that avr-size command can definitely help when you start approaching the limit.

Yes that was the avr-size command I was talking about. So the missing byte could be something else then. I think I’ll keep the eeprom mirror for now but if I need ram more than flash I know I could get rid of it. And yeah, I also read somewhere that you should keep a few bytes on ram for the mcu to use, dunno how many though. IIRC there was a figure 70% floating around. If you go above that then you might run into ram problems.

Hey TK, is the extended config mode (memory) in blf-a6 supposed to be working? I remember seeing somewhere that it wasn’t fully implemented yet, but now I’m not sure.

Sorry if it was already mentioned.

It works if recompiled with that option enabled, but it’s necessary to remove both the tactical strobe and bike flasher to make room.

The extended config mode simply converts it to use two config options (mode group and mode memory) instead of one (mode group). But if you’re recompiling anyway, you can set those both at compile time (in tk-otc.c) and have lots of room left over for other stuff.

I might still be able to reduce the size a little, and I’ll definitely try… but for now the default is one config-mode option and one star-based option.

So by ‘enable’ you just mean un-comment it? I prefer to be able to toggle both mode group and memory without disassembly. I also have no problem deleting blinkies.

Another weird question: is it possible to have lvp protection enabled in one mode group, and disabled in the other?

Still got some time before my flasher arrives and I got a little interested in this. So to use the whole 64 byte eeprom I first must change the 31 to 63 in this line?
eepos=(eepos+1)&31; // wear leveling, use next cell

And then I decrease the eeprom array from 32 to 8 byte and loop over it 8 times? Sounds not very difficult to do and will not take that many more bytes in flash.

Or you could copy save_state() and restore_state() from blf-a6/tk-otc.c, which already fixed the issue. The array is completely unnecessary, since you can simply read one byte at a time. We don’t really care about speed here, just space. It uses all 64 bytes of eeprom, but only requires 1 byte of global-scope RAM and up to 2 more bytes of local-scope RAM.

TK - you probably haven't re-visited the Ferrero-Rocher driver in a while, but today I saved a bunch of bytes by taking "inline" off of next_mode() and prev_mode(). Basically if you call a function more than once, chances are "inline" will waste space. I did this to my version of the e-switch driver the other day, and same thing - saved a lot on program space.

Basically, comment out the ‘#define CONFIG_STARS’ line. Then make room by commenting out the two strobey modes.

I did some code changes today to make this easier. Also, I found some new ways to reduce the size overall, so it’s possible to put in the full config mode plus one of the two strobes, or full config plus both (with the bike flasher simplified). You can try that version here: Index of /torches/pilotdog68

In full config mode, it will blink twice for each config option. Turn the light off between the two blinks to toggle that option. There are only two options though, mode group and mode memory (in that order).

I’m still merging changes into tk-otc.c and generally cleaning up, but it should get published in the trunk branch soon.

Possible, yes. But there is no code for this right now so someone would need to write it. I think it would be reasonably simple though, just wrapping the whole LVP logic clause inside an “if (modegroup == 0)” or similar.

I tried that, actually. I think it’s a matter of compile options, but for me it made no difference at all in the size or content of the build. But if it helps at least sometimes I don’t mind making it default. :slight_smile:

Here is what I see when building it (same with/without inline):

~/src/torches/trunk/ToyKeeper/Ferrero_Rocher/> ../../bin/build.sh Ferrero_Rocher
avr-gcc -Wall -g -Os -mmcu=attiny13 -o Ferrero_Rocher.o -c Ferrero_Rocher.c
avr-gcc -Wall -g -Os -mmcu=attiny13 -o Ferrero_Rocher.elf Ferrero_Rocher.o
avr-objcopy --set-section-flags=.eeprom=alloc,load --change-section-lma .eeprom=0 --no-change-warnings -O ihex Ferrero_Rocher.elf Ferrero_Rocher.hex
Program:     970 bytes (94.7% Full)
Data:         26 bytes (40.6% Full)

If my guess is correct, the “-Os” option will automatically un-inline everything which has been used more than once.

Weird - just tried it again, and the difference is 48 bytes saved - 984 with inline, 948 without. I'm using Atmel Studio 6.2, and the -Os option is specified.

This is what 6.2 studio invokes for compiling:

Invoking: AVR/GNU C Compiler : 4.8.1

"C:\Program Files (x86)\Atmel\Atmel Toolchain\AVR8 GCC\Native\3.4.1056\avr8-gnu-toolchain\bin\avr-gcc.exe" -x c -funsigned-char -funsigned-bitfields -Os -ffunction-sections -fdata-sections -fpack-struct -fshort-enums -Wall -mmcu=attiny13a -c -std=gnu99 -MD -MP -MF "Ferrero_Rocher.d" -MT"Ferrero_Rocher.d" -MT"Ferrero_Rocher.o" -o "Ferrero_Rocher.o" ".././Ferrero_Rocher.c"

Thanks!

The important option there was “-c -std=gnu99”. I added this to my build script and am now getting the same results you are. This also has reduced the size of every firmware I’ve tried so far, so I’m leaving it in as a permanent thing. :slight_smile:

This also saved enough room to let the full config mode fit into the blf-a6 firmware without having to remove anything. :smiley: