Searching \ for 'Defining registers' in subject line. ()
Make payments with PayPal - it's fast, free and secure! Help us get a faster server
FAQ page: massmind.org/techref/index.htm?key=defining+registers
Search entire site for: 'Defining registers'.

Truncated match.
PICList Thread
'Defining registers'
1996\07\25@032558 by Steve Hardy

flavicon
face
> From: NEIL GANDLER <spam_OUTV064MB9KTakeThisOuTspamUBVMS.CC.BUFFALO.EDU>
>
>   1. When entering an interrupt routine, the pic data book instructs
> to store the current values of the W and STATUS registers. They
> say that the register W_TEMP must be defined in both banks. So
> I assume I can do just that by putting the following in my code
>
>         W_TEMP EQU 25
>         W_TEMP EQU 0xA5
>
>         But I get errors, stating that symbol can not be redefined.
>
>
>         How else Can I do this?


One possible correct way is to go...

       include "pic16c74.inc"


       cblock  20h
       w_temp          ; Regs 'common' to both banks
       s_temp

       my_reg_1        ; your bank 0 registers
       my_reg_2
       ; etc...
       endc

last_common  equ  s_temp        ; Define the last register common to
                               ; both banks (temp status save area).

       cblock  80h+last_common+1

       my_reg_11       ; your bank 1 registers
       my_reg_21
       ; etc...
       endc

; in the interrupt routine...

       movwf   w_temp          ; Will actually store in bank 0 or 1
                               ; area depending on status.rp0 bit.


{Quote hidden}

Yes, this is usually acceptable.  It occurs when accessing registers
defined in bank 1 because their 'address' is over 127.  Don't worry,
just ensure that your code is setting status.rp0 appropriately so that
the device is really accessing the second bank.

The same message may occur if you try to set the '9th bit' of a register
e.g.  BSF my_reg,8.  This is a worry, becasue you probably are making
use of an equate for the bit number which is all awry.  The above example
would actually set bit 0 (the LSB) since there ain't no 9th bit in an
8 bit register!

Regards,
SJH
Canberra, Australia

1996\07\25@150857 by Martin J. Maney

flavicon
face
On Thu, 25 Jul 1996, Steve Hardy wrote:

> > From: NEIL GANDLER <.....V064MB9KKILLspamspam@spam@UBVMS.CC.BUFFALO.EDU>
> > 2. When refining my code, I eliminate all assembling errors, but I

I find it more productive, at least in the long run, to track these down
as soon as they appear.  If it's really spurious, figure out how to shut
it up, but "testing" code that contains errors that can be detected by
the assembler seems really pointless.

{Quote hidden}

"Don't worry, be happy" is, unfortunately, about all you can do here, yes.
The idea of trapping such errors was a good one, but it hasn't been taken
nearly far enough in Microchip's assembler to be useful.  Working with
what's available, it would be at least a little bit better to mask the
address so as to eliminate the warning.  Best of all would be something a
bit smarter, and I've implemented a set of macros to manage this, but I'm
far too unhappy with the result to wish to share it in ts current form.

Last time I was involved in a discussion of this I think I was
misunderstood just a little bit.  It's almost certainly impossible to
guarantee correct automatic determination of the setting of the register
page select bit(s) at assembly time, but that wasn't what I was
suggesting.  It seems to me that a considerable assistance - say, about as
useful, but less cumbersome, than the macro hackery I've been using - in
keeping track of the settings would be easy to add, and with modest
additional effort it could become a lot better.  I don't expect that it
will be perfect, and some manual "hinting" will certainly be necessary,
but based on actual experience in a non-trivial project I gotta tell
y'all, getting it right MOST of the time without manually tracing the code
is worth a lot of development time.  My experience may be biased a bit by
the way the design kept shifting as the rest of the design team dreamed up
new hoops for the firmware to jump through and discarded old ones, but I
expect that's not too uncommon.  It was during the revision of code that
the checking the macros provided was most often called upon to catch an
oversight in fiddling the page bits.

> The same message may occur if you try to set the '9th bit' of a register
> e.g.  BSF my_reg,8.  This is a worry, becasue you probably are making
> use of an equate for the bit number which is all awry.  The above example
> would actually set bit 0 (the LSB) since there ain't no 9th bit in an
> 8 bit register!

And that's the other reason I hate the idea of "just ignoring" these
warnings: they aren't really spurious, they're just set off far too often
by perfectly okay code.  But unlike the ugly but (nearly always) harmless
sprinkling of (void) on every function used as a procedure in order to get
lint to shut up (sorry, C roots showing there), mechanically adding a
mask to register addresses to shut this up is likely to turn off the only
diagnostic of a serious and easily-committed error.  Only warning, that
is, aside from "it doesn't work".  :-(

1996\07\25@160011 by fastfwd

face
flavicon
face
Martin J. Maney <PICLISTspamKILLspamMITVMA.MIT.EDU> wrote:

>     [.... a lot of good stuff that I'm too tired to respond to,
>     then.... ]
>
> mechanically adding a mask to register addresses to shut this up is
> likely to turn off the only diagnostic of a serious and
> easily-committed error [attempting to store a 9-bit value in an
> 8-bit register, etc.].

Martin:

If the masking is performed the way some people INSIST that it
should be done -- that is, by ANDing the value with 0x7F -- this is
true; the mask will force all values to 7 bits, and there will be no
indication that you've screwed up.

If, on the other hand, you "mask" the value by XORing it with 0x80,
attempts to store 9-bit values will still generate errors, as will
attempts to mask addresses that already ARE only 7 bits wide.

-Andy

Andrew Warren - .....fastfwdKILLspamspam.....ix.netcom.com
Fast Forward Engineering, Vista, California
http://www.geocities.com/SiliconValley/2499

1996\07\26@020343 by Martin J. Maney

flavicon
face
On Thu, 25 Jul 1996, Andrew Warren wrote:

> Martin J. Maney <EraseMEPICLISTspam_OUTspamTakeThisOuTMITVMA.MIT.EDU> wrote:
> > mechanically adding a mask to register addresses to shut this up is
> > likely to turn off the only diagnostic of a serious and
> > easily-committed error [attempting to store a 9-bit value in an
> > 8-bit register, etc.].

Actually, I was thinking there of the all-too-easy error of accessing a
register without getting the page select bit correctly set.  The attempt
to use bsf on "bit 8" or loading a literal that doesn't fit into 8 bits
is the sort of error the assembler diagnoses correctly (actually, I'm
taking the bit-index-out-of-range on faith, as I can't recall ever having
seen that).

> If the masking is performed the way some people INSIST that it
> should be done -- that is, by ANDing the value with 0x7F -- this is
> true; the mask will force all values to 7 bits, and there will be no
> indication that you've screwed up.

As a matter of fact, my macro hack uses XOR to translate the true
addresses into 7-bit addresses.  This allows a simple representation for
"unknown" in the current-page state variable, too.  ;-)

> If, on the other hand, you "mask" the value by XORing it with 0x80,
> attempts to store 9-bit values will still generate errors, as will
> attempts to mask addresses that already ARE only 7 bits wide.

What I feel falls short about this sort of masking - and it doesn't make
any matter whether you AND or XOR - is that there's no checking at all
that the correct page is selected.  Aside from its value as an eyecatcher
that says "here's a page 1 address, dude," all this does is make sure you
"know" which page a particular register is on.  Now, getting even that
limited visibility of the register's page into the code is a good thing,
but I've found that an imperfect, rather cumbersome macro package that
provides a more dynamic check is worth its weight in gold.  I can see ways
to make it even better, but I'm about at the limit of what I feel is
practical for the rather weak macro language of MPASM (1), and this would
all be a lot easier to implement from inside the assembler.  Or maybe not,
depending on how bad its internal structure has become after years of
incremental modification.  :-(


 1) barring a complete rethinking of the basic approach, maybe.

1996\07\26@122709 by John Payson

flavicon
face
> What I feel falls short about this sort of masking - and it doesn't make
> any matter whether you AND or XOR - is that there's no checking at all
> that the correct page is selected.  Aside from its value as an eyecatcher
> that says "here's a page 1 address, dude," all this does is make sure you
> "know" which page a particular register is on.  Now, getting even that
> limited visibility of the register's page into the code is a good thing,
> but I've found that an imperfect, rather cumbersome macro package that
> provides a more dynamic check is worth its weight in gold.  I can see ways
> to make it even better, but I'm about at the limit of what I feel is
> practical for the rather weak macro language of MPASM (1), and this would
> all be a lot easier to implement from inside the assembler.  Or maybe not,
> depending on how bad its internal structure has become after years of
> incremental modification.  :-(

What I'd like to see would be the following:

[1] Since labels are probably going to be handled by the assembler as 16-bit
   values even though the PIC only uses at most the bottom 9 (and I don't
   think any 16Cxx's use anything more than the bottom 8), what I'd like
   to see would be something like this:

   00- 7F : Page 0 addresses
   80- FF : Page 1 addresses
  100-17F : Shared addresses [same in both pages]

   Thus, on a PIC16C84, the RAM would go from $10C to $12F; on a 16C622, it
   would go from [I think] $20 to $FF and $A0 to $E0.

[2] The ability to specify what the RP flag should be assumed to be in a
   range of code.

[3] The ability to specify what should be dome with the RP flag if it's
   "wrong" [error, change/do instruction/change back, or change/do
   instruction/keep changed until an instruction that needs it back, or
   until a "goto", "call", or label is encountered].

PS--On the 16C620/16C621, how should one save registers in an ISR since
   there's no address available in both banks for storing them?

1996\07\26@134931 by Martin J. Maney

flavicon
face
On Fri, 26 Jul 1996, John Payson wrote:

{Quote hidden}

This would work, but I'd much rather see this added inside the assembler
as an attribute: that way the value of the symbol can be the actual
address in all cases, and as a bonus it wouldn't have to be changed no
matter how many registers, in banks of whatever size, some remote
descendent of the current PICs might have.

> [2] The ability to specify what the RP flag should be assumed to be in a
>     range of code.

That's necessary, but I've found that at least for the project I've been
working on about 99% of this can be handled by using a macro in place of
a literal bsf of the register page bit.  Well, in conjunction with a
fixed assumption of "unknown" at each subroutine entry point.  :-)

Where this discussion got in trouble last time was, I think, here, where
I suggest that borrowing a little from modern compiler technology the
assembler could do a lot better than this.  Certainly it would need some
additional hints, but again IME the vast majority of this is covered by
identifying subroutine entry points and computed gotos.  When you're
doing something really tricky I think it's entirely reasonable for the
assembler not to understand it without some hints.  Personally I wouldn't
even care if it recognized even the "standard" ways of, eg, setting and
clearing the page select bits, though that would be a plus.

For portability... well, a simple method would be to have a pseudo-op
that flags a block of code as "nasty old style", which would make the
assembler treat it as being "unknown" (that is, page select status on
return from a call into any address in the range would make the
assumption after the call "unknown page": this is a place you might use a
hint to tell the assembler what it can't deduce).

But again, all this goes well beyond anything I expect to see any time
soon, unless I win the lottery and decide that this is a project that
really needs doing.  :-)  Since I don't buy lottery tickets...  :-(

> [3] The ability to specify what should be dome with the RP flag if it's
>     "wrong" [error, change/do instruction/change back, or change/do
>     instruction/keep changed until an instruction that needs it back, or
>     until a "goto", "call", or label is encountered].

I'll settle for a nice assemble-time error: that's a huge improvement
over any runtime fault!

> PS--On the 16C620/16C621, how should one save registers in an ISR since
>     there's no address available in both banks for storing them?

<blink> That's cute.  I guess you'd have to do all page1 operations either
with interrupts masked, or else through INDF, or only access page1 when
interrupts can't occur (this might be viable if you use interrupts in a
restricted manner) if you're going to use interrupts!

1996\07\26@141543 by Eric Smith

flavicon
face
"Martin J. Maney" <maneyspamspam_OUTMCS.COM> wrote:

> What I feel falls short about this sort of masking - and it doesn't make
> any matter whether you AND or XOR - is that there's no checking at all
> that the correct page is selected.  Aside from its value as an eyecatcher

I added to my own assembler an "assume" directive (inspired by the disgusting
Intel x86 stuff) that lets me explicitly tell the assembler what page will
be selected.  It's not uncommon for my code to use sequences like:

       bsf     status,rp0
       assume  1
; muck about in bank 1, assembler will generate errors for any attempt to
; directly access registers in bank 0
       ...
       bcf     status,rp0
       assume  0

Actually I usually use a macro that does both the rp0 twiddling and the
assume.  I didn't make the assembler automatically track the bsf and bcf
instructions because that leads to sloppy thinking and problems like:

subr1:  bsf     status,rp0
       ...
       call    subr2
       ...
       bcf     status,rp0
       return

subr2:  movwf   porta
       ...
       return

If the assembler tried to do simple automatic bank tracking based on the bcf
and bsf instructions, it would incorrectly think that subr2 was executed in
bank 0.  Also, moves to the status register would confuse it.

I also had to add a directive that tells the assembler which locations are
identical in both banks.  For example, PCL, RTCC, and in some PICs the RAM.

However, my assembler sucks in a lot of other ways, so I'm not giving it
out.  But maybe others could incorporate similar functionality into
commercially available assemblers.

Cheers,
Eric

1996\07\26@143226 by John Payson

flavicon
face
> > What I'd like to see would be the following:
> >
> > [1] Since labels are probably going to be handled by the assembler as 16-bit
> >     values even though the PIC only uses at most the bottom 9 (and I don't
> >     think any 16Cxx's use anything more than the bottom 8), what I'd like
> >     to see would be something like this:
> >
> >     00- 7F : Page 0 addresses
> >     80- FF : Page 1 addresses
> >    100-17F : Shared addresses [same in both pages]
>
> This would work, but I'd much rather see this added inside the assembler
> as an attribute: that way the value of the symbol can be the actual
> address in all cases, and as a bonus it wouldn't have to be changed no
> matter how many registers, in banks of whatever size, some remote
> descendent of the current PICs might have.

Okay, that's certainly fair enough.  But I think it's essential that the
attributes be set-able for each register so that some registers may be
marked as bank-independent and others marked as bank-dependent.  This would
be especially useful if Microchip came up with a CPU (other than the PIC
16C57/16C58) in which there were SOME user f-registers that were bank-
independent and others that were bank dependent. [HINT HINT Microchip, are
you listening? :-)]

{Quote hidden}

Well, I think there needs to be an easy way for the user to indicate that
certain things are happening to it, and also to allow for "bank-status
unknown"; my preference would be for the compiler to recognize all the
common ways of modifying the RP0 bit, and acknowlege its value as "unknown"
anywhere something suspicious, but not confirmable, happens to it (if user
code does, e.g., a 'movwf status', the assembler should allow the user to
put in an 'assume 0' if the user knows RP0 will be clear at that point).

> For portability... well, a simple method would be to have a pseudo-op
> that flags a block of code as "nasty old style", which would make the
> assembler treat it as being "unknown" (that is, page select status on
> return from a call into any address in the range would make the
> assumption after the call "unknown page": this is a place you might use a
> hint to tell the assembler what it can't deduce).

What I'd like to see would be for the assembler to require users to mark
the code areas that will be targets of indirect jumps.  This would produce
the following advantages:

<1> The assembler could move segments around to ensure no 'indirect-jump'
   segments cross pages.

<2> The assembler could disallow code-expansion (e.g. artificially-induced
   BSF RP0 instructions) within such areas, since they'd throw off the
   addresses of anything following.

<3> The assembler could better track flag states in areas which were known
   NOT to have such jumps targeted at them, and could produce more meaning-
   ful timing analyses (the PIC's instruction set makes it easy to figure
   timings; I've yet to see a diagnostic tool that could handle even simple
   subroutine calls in its timing analysis, though).

> > [3] The ability to specify what should be dome with the RP flag if it's
> >     "wrong" [error, change/do instruction/change back, or change/do
> >     instruction/keep changed until an instruction that needs it back, or
> >     until a "goto", "call", or label is encountered].
>
> I'll settle for a nice assemble-time error: that's a huge improvement
> over any runtime fault!

True enough.  Personally, that'd be the mode I'd most likely use.  But for
some applications having it handled automatically would be nice, too.

> > PS--On the 16C620/16C621, how should one save registers in an ISR since
> >     there's no address available in both banks for storing them?
>
> <blink> That's cute.  I guess you'd have to do all page1 operations either
> with interrupts masked, or else through INDF, or only access page1 when
> interrupts can't occur (this might be viable if you use interrupts in a
> restricted manner) if you're going to use interrupts!

Actually, I don't think anything that desperate is needed.  If nothing else,
you could start your ISR with something like:

ISR:
       btfss   RP0
        goto   ISR0
       bcf     RP0
ISR1:
       <<copy of ISR code here>>
       bsf     RP0
       retfie
ISR0:
       <<copy of ISR code here>>
       retfie

Ugly, yes.  Waste of time, yes.  Any better techniques (the INDF one is a
good one, btw)?  I dunno...

1996\07\27@005502 by Martin J. Maney

flavicon
face
On Fri, 26 Jul 1996, Eric Smith wrote:

> I added to my own assembler an "assume" directive (inspired by the disgusting

>       bsf     status,rp0
>       assume  1
> ; muck about in bank 1, assembler will generate errors for any attempt to
> ; directly access registers in bank 0

> Actually I usually use a macro that does both the rp0 twiddling and the

This is very like the macro hack I've found so useful, but because it's
built into the assembler you don't need to use reg(someRegisterName) in
instructions.  (After I had this working someone, perhaps Andrew,
mentioned a completely different approach that would fix this, but code
assembles so slowly with this relatively low-overhead hack that I'm not
real excited about making every instruction a macro).

> assume.  I didn't make the assembler automatically track the bsf and bcf
> instructions because that leads to sloppy thinking and problems like:
>
> subr1:        bsf     status,rp0
>       ...
>       call    subr2
>       ...

Well, there's no problem if the assembler recognizes that a subroutine
call can change the page select.  This was where I got in trouble before,
since a really helpful assembler could determine both the entry and exit
conditions for a subroutine and use them to good effect, but this can
easily turn into a far more complex process.  If I were to set out to
implement something like this starting tomorrow, I think I would make the
pre and post conditions something you'd have to declare before either
calling or defining the body of a subroutine - this eliminates a lot of
need for the compiler to deduce this stuff.  But then I thought that
protoypes were one of the best things added by Standard C, and mandantory
use and checking of them one of the biggest improvements in C++.  :-)

> subr2:        movwf   porta
>       ...
>       return
>
> If the assembler tried to do simple automatic bank tracking based on the bcf
> and bsf instructions, it would incorrectly think that subr2 was executed in
> bank 0.  Also, moves to the status register would confuse it.

And that could be if_else2: rather than a subroutine entry and it woud
ahve much the same problem.  That's the other reason I stopped working on
the macro hack well short of much more than what it sounds like you've
implemented.  I did think the subroutine case was important enough that I
have a macro used to make the call and then fiddle the page state
variable and one used to define subroutine entries.  They're crude in
their current form and always make worsy case assumptions, leaving the
page state set to "unknown".  So far the overhead for unnecessary page
bit twiddling hasn't been a problem.  <knock wood>

> I also had to add a directive that tells the assembler which locations are
> identical in both banks.  For example, PCL, RTCC, and in some PICs the RAM.

That's one advantage - probably the only one! - of the reg() macro.  For
normal RAM registers I write, as I have become accustomed to

 bsf reg(someFlagSet), SFS_ERROR_BIT

but for the special registers I can just omit the macro

 btfsc STATUS, CARRY

It's not perfect, but it works well enough.  And it was real easy to
implement.  :-)

1996\07\27@012701 by Martin J. Maney

flavicon
face
On Fri, 26 Jul 1996, John Payson wrote:

[lots of stuff that we basically agree on, I think, snipped]

{Quote hidden}

<smacks forehead>  Of course, the old use-the-PC-as-a-state-variable
trick!  I think I first saw this described as such in a letter from
Dijkstra to Knuth, quoted briefly in "Structured Programming With goto
Statements" if I recall correctly.

I wonder if Microchip saw this problem and this hack back before they
froze the design of the 620/21?

{Quote hidden}

Well, sure: instead of duplicating the whole ISR (unless it's very small),
save the STATUS in a register and then adjust the saved page bit; then the
two paths come back together again.  That was what I thought you were
proposing at first when I saw the btfss/goto stuff.  That would be the
only-store-the-state-in-the-PC-briefly approach.  :-)

1996\07\28@052301 by eyalo

flavicon
face
John Payson wrote:

> you could start your ISR with something like:
>
> ISR:
>         btfss   RP0
>          goto   ISR0
>         bcf     RP0
> ISR1:
>         <<copy of ISR code here>>
>         bsf     RP0
>         retfie
> ISR0:
>         <<copy of ISR code here>>
>         retfie
>
> Ugly, yes.  Waste of time, yes.  Any better techniques (the INDF one is a
> good one, btw)?  I dunno...

My own method is using the FSR as follows:
1. The default page is always data page 0.
2. All global data is in the start of data page 0.
3. The rest of the RAM used as stack.
4. Interupts are disabled when accessing the hardware registers in
  page 1.
This way the interrupt routine (if I have one) uses page 0 registers.
The rest of the RAM is used as a stack.
I use the folowing code to access the 'data stack':

PushW   movwf   0h                      ; save in the stack
       movlw   00h                     ; clear w
       btfss   FSR,MSB                 ; if MSB of FSR is high
       movlw   20h                     ; mov 20h to W
       incf    FSR,f                   ; increment FSR
       btfsc   FSR,MSB                 ; if MSB of FSR is high
       addwf   FSR,f                   ; add W to FSR
       return

PopW    movlw   0h                      ; clear w
       btfsc   FSR,MSB                 ; if MSB of FSR is high
       movlw   20h                     ; mov 20h to W
       decf    FSR,f                   ; decrement FSR
       subwf   FSR,f                   ; substract W from FSR
       btfsc   FSR,MSB                 ; if MSB of FSR is high
       addwf   FSR,f                   ; restor FSR value
       movf    0h,w                    ; restor W.
       return

If I use the stack in the interrupt function I disable the interrups
when using the stack from the rest of the code.

P.S. The code is for PIC16C62/63/73 but I used similar code for other
devices.

Eyal Oppenheimer
E-mail: @spam@eyaloKILLspamspamaks.com
R&D
Aladdin Knowledge Systems Ltd.
Tel:    +972-3-636-2222
Fax:    +972-3-537-5796
WWW Home Page:  http://www.aks.com

More... (looser matching)
- Last day of these posts
- In 1996 , 1997 only
- Today
- New search...