T bit, does gcc ever use it?

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

I want to use the T bit, but would like to know if the gcc compiler would ever use it.

I've never seen it, but that doesn't mean anything. I've tried to look at the source code (gcc) and search for any sign that the t bit is used, but don't see anything (not sure I'm looking at the correct code- gcc/gcc/config/avr/avr.c+avr.h?). I suspect it would be kinda odd for it to use the T bit in any way.

I want to claim it as my own little personal bit with a little set of instructions to go with it (if no one else wants to claim it). If gcc happens to use it, I better keep my paws off.

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

I don't think gcc uses it. I was looking into claiming that bit for myself (as it so happens yesterday), but had to drop it since it gets flushed in ISRs (and I needed fast access to a global flag from within main and ISRs).

Luckily (for me) the newer AVRs have at least one GPIOR which I can use for my purpose (and gives me 8 bits instead of 1).

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

Quote:

Luckily (for me) the newer AVRs have at least one GPIOR which I can use for my purpose (and gives me 8 bits instead of 1).

I don't know about your apps, but in mine I rarely use all the peripheral subsystems. There are often a few I/O registers in low address space just dying to be used, or at least a few bits of them after avoiding enable bits and the like. So when you need "just 3 more flags" you can roll-your-own GPIOR.

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

I've been known to cast a bit struct onto TWAR which is a handy 8 bit R/W register giving you 8 "bit vars" in te 0x00..0x1F range where the compiler will use SBIs and CBIs. 'course some people are mad enough to want to actually use I2C!

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

I'll save those registers for a rainy day ;).

BTW, I was more interested in SBIC and SBIS, to check for an abort condition in an SPI slave (using USI where every clock cycle counts).

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

I will plant the flag, and claim T as mine.

I wanted a 'universal' bit that is not otherwise used. T fits to a 'T'. Plus I get my very own little instruction set to go with it.

I was working on my 4AvrBugTrapper, when it occurred to me there is nothing in my bootloader that keeps an app from accidentally jumping inside and possibly doing an spm, or getting 'stuck' inside (I have wdr's in the loops there).

The T bit will be the pass key to my bootloader. I will give the key out to all who enter via the front door (at boot reset address- first instruction will be 'set'). The second door will check if porf=1 AND wdrf=0 (and kick you out if not a power up). Once inside my bootloader, I need to periodically check you for your pass key (check if T bit set in the loops where I do wdr). If I find that you don't have your pass key, you get kicked out of the bootloader. So if you try to enter via some back door (screwed up application jumped into it), you get kicked out. Also before any spm, a 'brtc .+2' will be placed so if you jump into my bootloader at 1 instruction (or more) before spm, it will just skip the spm command, no harm done to the app (bootloader has lock bits on, so no worries there). If you 'fall' into the bootloader via the front door, you will be prevented from entering because the reset flags will be cleared in app startup code, and not make it through the second door.

Any jump that doesn't first hit the boot reset address will not get the T bit set. Any jump that does hit the boot reset address will then have to go through the second door (porf=1,wdrf=0).

So, to do some 'damage', you would either have to be messing around with the T bit (unlikely), or happen to setup the spm reg, then make a pinpoint jump right to the spm command.

Maybe.

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

GCC itself doesn't use it but the floating-point library does.

Jörg Wunsch

Please don't send me PMs, use email if you want to approach me personally.

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

At least someone's putting it to use then (that poor t bit has an unexciting life). I now see it in fplib source. I may have to do more thinking. I'm not sending an avr to Pluto or anything. I think the odds are better if I use the T bit, rather than use nothing at all. I also don't have much more room for doing anything elaborate anyway. Whatever I do will have to fit between spm and and the previous spm setup instruction.

Thanks for the info on fplib, I never would have figured that out on my own.

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

I've used that "pass key" idea before. You can of course just use a variable in RAM as the key - make sure a byte is 0x5A or something before the "dangerous" stuff can execute though I guess it's a few more cycles than using a bit.

In my case this was actually for securing a bootloader. During the init the PC app effectively did a kind of CHAP authentication (though it used SHA256 rather than MD5 as the hash function) and only once "unlocked" was the variable set to say "it's OK to do programming"

Cliff

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

I vote for the RAM variable, as it's less likely to get altered to the correct state by errant code (you get 8 bits of security instead of just one). Also note that while GCC is not currently using the T bit, there is nothing stopping future optimizations from taking advantage of it.

Writing code is like having sex.... make one little mistake, and you're supporting it for life.

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

Ram is nice, but I need to fit it in 3 cycles. LDS takes 2, that only leaves 1 to test and branch.

Plan B.

Move irq vector table to bootloader section (not going to use irq's, though). This will now be the 'pass key'. MCUCR seems to be in i/o 'IN' territory for all the avr's I'm looking at.

sts spm_reg,page_erase_cmd //load up spm command
in r10,mcucr //get mcucr
sbrc r10,1 //if ivsel=0, skip spm
spm //ivsel=1, so do it

and I even get to use one of the oddball registers (

No application in their right mind is going to move the vectors to the bootloader section. Right?. (especially since my bootloader with no irq's will be the one that's there).

I may be looking at this all wrong, though. The self-erasing errant code could be a feature, not a problem :)

Last Edited: Wed. Nov 28, 2007 - 11:47 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Why have you discounted the GPIOR or (unused) things like TWAR? You get EIGHT of your own bit variables that way and they can generally be set/reset/tested with single cyle ops (even the C compilers know this!). You just got to pick something in IO space addressing 0x00 to 0x1F

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

since you're trashing r10 anyway, why not store your passkey in r10 from the start?

About the pretty good shooting, if it can happen, it will at one point. I kind of like the idea about IVSEL, but it excludes a lot of processors.

The only really safe way to tell where you're coming from is to verify where you're coming from. In this case that would mean that the stack has to be in a certain state. But I guess that doesn't satisfy your 3 cycles constraint.

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

Would like to use one method that works for both mega88/mega16 types. Although a simple #ifdef GPIOR0 would take care of it. I also have some registers

To make it easier to think about, assume the errant jump lands right on the spm setup instruction. If I use sbic/sbis on an i/o register <=0x1F, or sbrc/sbrs on a register, those don't seem like very good odds (50/50, I think). If I do a in/cpi/brne, that's 1 in 256 (assuming all numbers are equally probable, which is most likely not the case). If I use brtc, that seems hard to calculate, unless the t bit is never used in the app (then odds would be very much in my favor). If fplib happens to be used for example, I think it goes downhill fast. (I may have to pick up my planted flag on the T bit, and give up my claim on it).

My latest thought may be the best so far (thats not saying much). IVSEL is not going to be accidentally turned on in an app (that's why they made IVCE). And loading a register with mcucr every time before the spm keeps it from becoming a 1 in 256 thing again (or worse, if using sbrs/sbrc).

I assume IVSEL is available on all avr's with bootloader sections (I'm not concerned about avr's with no 'real' bootloader capability).

Stupid bootloaders. They're never finished.

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

Ok. The T bit was thrown out the window, never to be seen again.

New plan. It works. I think I like it. I think.

http://www.mtcnet.net/~henryvm/A...

If no ivsel=1, you will get kicked out of the bootloader if you 'sneak' in (safeT_check() in the 3 places code loops). If you get in the 'front' door before or at the instruction that enables ivce, you will still need to pass the porf=1 test. If no powerup, or a watchdog reset, you leave the bootloader with all i/o registers in initial values, including sreg (assuming a reset, of course).

The spm is also protected. There is only 1 spm command in the bootloader. The only 2 ways for an spm to occur from an 'errant' jump, is to either get ivsel=1 first, or setup the spm register and jump exactly on it. Both are very unlikely.

The instruction prior to the spm instruction is an rjmp out of the bootloader. That eliminates that one. The previous 2 to that check if ivsel=1. If ivsel=0, you get the rjmp out (neither matter to an errant jump, though, as you can't meet the 4 cycle requirement, even if it did setup spm first). Any jump at or prior to the spm setup instruction will have to go through the ivsel test.

I can also use (if wanted) the do_spm function from the application section. Would have to disable irq's, change ivsel to 1, setup address, command, (and data if needed), call function, function will do spm command, enable rww and return.

I do have one question left. I am using r21 for a register variable, but it is needed after the do_spm() function. The compiler thinks it will not survive past the function call (its a call-used register), so it optimizes it away. So I decided to tell the compiler what is actually modified by the called function-

//AV("movw  r0, %0" :: "r" (rx_buffer.DDDD
)); //do_spm(address,__BOOT_PAGE_FILL); //replaced by- __asm__ __volatile__ ( "movw r0,%[buf] \n\t" "movw r24,%[addr] \n\t" "ldi r22,%[bpf] \n\t" "rcall do_spm \n\t" :: [buf] "r" (rx_buffer.DDDD
), [addr] "r" (address), [bpf] "M" (__BOOT_PAGE_FILL) : "r30","r31" );

I think I'm telling the compiler that in addition to r24,r25,and r22, r30 and r31 will be clobbered by the do_spm rcall. Which ends up leaving my r21 'not' optimized away (good). Am I doing this correctly? (I clear r1 in the do_spm).

And one last question (honest), is there any way to determine which avr's need the stack set? (besides actually naming all of them). Any common theme, like all without extended i/o (0x60-0xFF) or something?

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

curtvm wrote:
safeT_check()

Ah, I get it now, your whole desire to use the T bit previously was simply so you could coin this rather glorious pun! :lol:

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

Yes. The memory of the T bit will live on. Its not really gone if I can find some way to remember it. (And I can't call it safeIVSEL_check).