Searching \ for '[PIC] How do deal with RAM bank warnings?' in subject line. ()
Make payments with PayPal - it's fast, free and secure! Help us get a faster server
FAQ page: www.piclist.com/techref/microchip/memory.htm?key=bank
Search entire site for: 'How do deal with RAM bank warnings?'.

Exact match. Not showing close matches.
PICList Thread
'[PIC] How do deal with RAM bank warnings?'
2012\04\24@204638 by Dwayne Reid

flavicon
face
Good day to all.

This is an incredibly newbie-type question, but I'm stumped.

I've been writing code in assembler for 'conventional' 12-bit-core and 14-bit-core PIC chips for a LONG time now.  I've got a bunch of code-writing techniques that make the whole process fairly painless.

These early PICs have only 4 RAM banks: zero through three.  I have macros that deal with the MSB of the 7-bit address so that I get Message 302 warnings only when I haven't properly set up the bank bits.  These macros save me an awful lot of time when my fingers go faster than my mind.

In part, these macros are:

    #define BB1(reg,bit) (reg^0x80),(bit)   ;bit in bank 1
    #define RB1(reg) (reg^0x80)             ;reg in bank 1
;usage is:  bcf     BB1(_SOMEBIT)
;usage is:  movwf   RB1(SOMEREG)

What happens is that MPASMWIN spits out a message 302 warning if I don't use the BB1 or RB1 macro on a register that is in RAM bank 1 or 3.  Conversely, the assembler spits out a warning if use either macro when I shouldn't be using the macro with a register that is in RAM bank 0 or 2.

Like I mentioned above, these simple macros save me loads of time in tracking down stupid banking errors.  Plus - I get completely empty ..ERR files - this helps reassure me that I've probably caught all the RAM bank switching that is needed.

Now I'm starting a project with my very first enhanced PIC16 architecture PIC - the 12F1840.  This little sucker has 32 RAM banks - and an easy way to actually set the bank bits (banksel and movlb).

But: now I get all these darned message 302 warnings about checking to see if I actually did set the bank bits.

I *really* don't want to disable those warnings - they are a useful troubleshooting tool.  What I'm wondering if anyone has techniques to 'mask' the message on a case-by-case basis.

In other words, I want to be able to do something like:

    movlw    b'00110011'
    banksel  SOMERAM
    movwf    SOMERAM

but do *SOMETHING* that persuades MPASMWIN that the RAM location is really in RAM bank 0, so that I don't get the warning message.  Or: do something that hides the warning, again, on a case-by-case basis.

I know that there are a LOT of people using these newer chips and I was hoping that someone has a technique that hides the warning if the bank bits have actually been diddled.

My first thought was to write a macro that invokes banksel, turns off the warning, writes the RAM location, then turns the warning back on.  Something along the lines of:

BS_movwf  macro arg
    banksel  arg
    errorlevel -302
    movwf  arg
    errorlevel 302
    endm

Usage would be:
    movlw    b'00110011'
    BS_movwf (SOMERAM)

Of course, I'll have to do this for all possible operations, which seems tedious.

Any thoughts?

Many thanks!

dwayne

-- Dwayne Reid   <spam_OUTdwaynerTakeThisOuTspamplanet.eon.net>
Trinity Electronics Systems Ltd    Edmonton, AB, CANADA
(780) 489-3199 voice          (780) 487-6397 fax
http://www.trinity-electronics.com
Custom Electronics Design and Manufacturing

2012\04\24@225124 by Byron Jeff

flavicon
face
On Tue, Apr 24, 2012 at 06:46:35PM -0600, Dwayne Reid wrote:
{Quote hidden}

Interesting idea. I usually just disable the warnings.
{Quote hidden}

Not only a thought, I think I have a solution. I use a version of gpasm
that Joseph Julichar of Microchip augmented to support the enhanced
architecture. But it doesn't support a BANKSEL directive that properly sets
the BSR register. So I ended up writing my own macro:

SETBSR  macro   target
       movlb   (target >> 7)           ; gpasm assember's BANKSEL doesn't work for exhanced 16F parts.
       endm

Works fine, but I had simply disabled the 302 directives. Poking around the
manual I found the SET directive, which facilitates assembler variables
that can be changed. I figured that we can keep track of the current bank
in the macro. Since we only need the bank, I decided the shift the target
down, then shift it back up:

SETBSR  macro   target
       movlb   (target >> 7)           ; gpasm assember's BANKSEL doesn't work for exhanced 16F parts.
CURBANK set     ((target >> 7) << 7)
       endm

Note you can use BANKSEL instead of the movlb if you like, which will only
generate the movlb if the bank changes.
Once you have the assembler variable, you can use it the same way you did
with the older chips:

#define BB(reg,bit) (reg^CURBANK),(bit)   ;verify reg is in CURBANK
#define RB(reg) (reg^CURBANK)             ;verify reg is in CURBANK

I did a quick test, and it looks like a winner. Try it.

Now that I see this method, it looks like I could do conditional assembly
of my movlb (add an OLDBANK variable, compare it to CURBANK, and only generate
the movlb if they differ) to optimize SETBSR.

Hope this helps,

BAJ



{Quote hidden}

> -

2012\04\25@051608 by Jan-Erik Soderholm

face picon face
Byron Jeff wrote 2012-04-25 04:51:

> Note you can use BANKSEL instead of the movlb if you like,
> which will only generate the movlb if the bank changes.

Are you saying that BANKSEL in some way tracks the current
state of the bank-bits? Are you sure? I think BANKSEL
always will create the apropriate MOVLB command.

Jan-Erik.


Byron Jeff wrote 2012-04-25 04:51:
{Quote hidden}

>> -

2012\04\25@063017 by Byron Jeff

flavicon
face
On Wed, Apr 25, 2012 at 11:16:06AM +0200, Jan-Erik Soderholm wrote:
> Byron Jeff wrote 2012-04-25 04:51:
>
>  > Note you can use BANKSEL instead of the movlb if you like,
>  > which will only generate the movlb if the bank changes.
>
> Are you saying that BANKSEL in some way tracks the current
> state of the bank-bits? Are you sure? I think BANKSEL
> always will create the apropriate MOVLB command.

Really? Not an MPASM user, so I'm unsure. Just in case, I updated my macro
to do exactly that. Of course it only works properly on straight line code.
So there probably needs to be a complementary one that forces a MOVLB when
coming in/out of a subroutine. And of course interrupts should be good and
save/restore the BSR register. Here's my first crack at it:

SETBSR  macro   target
       if      (target >> 7) != (CURBANK >> 7)
       movlb   (target >> 7)                          ; gpasm assember's BANKSEL doesn't work for exhanced 16F parts.
CURBANK set     (((target >> 7) & 0x1f) << 7)                ; Force bank from 0-31
       endif
       endm

It seems to work. What actually fails are the types of defines that Dwayne
has below. Unsure as to why gpasm chokes on it. No a hugh problem as
virtually every Unix box which will run gpasm has an actual C preprocessor
that can handle it. BTW I prime CURBANK in the beginning with a bank 33,
which is out of range and forces generation of MOVLB and a reset of
CURBANK.

BAJ

{Quote hidden}

2012\04\25@064446 by Jan-Erik Soderholm

face picon face


Byron Jeff wrote 2012-04-25 12:30:
> On Wed, Apr 25, 2012 at 11:16:06AM +0200, Jan-Erik Soderholm wrote:
>> Byron Jeff wrote 2012-04-25 04:51:
>>
>>   >  Note you can use BANKSEL instead of the movlb if you like,
>>   >  which will only generate the movlb if the bank changes.
>>
>> Are you saying that BANKSEL in some way tracks the current
>> state of the bank-bits? Are you sure? I think BANKSEL
>> always will create the apropriate MOVLB command.
>
> Really? Not an MPASM user, so I'm unsure.

Yes, it is possible when writing *own* macros, of course.

Olin Lathrops tool-set has been like that "always".
With some complementary macros to "invalidate" the
saved setting after returning from a CALL and so on.

But the question is/was about BANKSEL i MPASM, not ?

Jan-Erik.



{Quote hidden}

2012\04\25@072515 by Byron Jeff

flavicon
face
On Wed, Apr 25, 2012 at 12:44:45PM +0200, Jan-Erik Soderholm wrote:
{Quote hidden}

Not exactly. Dwayne wanted to keep the 302 warnings on, but use some form
of macros and defines to check the current bank, whether or not it was
generated with BANKSEL or MOVLB. It's not clear if his set of macros
guaranteed that the bank bits RP0/RP1 were set correctly or not. What I've
generated will generate both the MOVLB and will track what BSR is set to.
So as long as the code is straight line it'll only generate 302 warnings
when the register is not in sync with current value of BSR.

BAJ

{Quote hidden}

>

2012\04\25@075252 by Jan-Erik Soderholm
face picon face


Byron Jeff wrote 2012-04-25 13:25:
{Quote hidden}

OK, I think I see now. :-)

Your reference to BANKSEL (that I quoted above) was "when used
inside your own macro", not to BANKSEL i general, right ?

Of course, if the BANKSEL is never run at all, it will not
generate any code either... :-)

Jan-Erik.




{Quote hidden}

>>

2012\04\25@081644 by Byron Jeff

flavicon
face
On Wed, Apr 25, 2012 at 01:52:51PM +0200, Jan-Erik Soderholm wrote:
{Quote hidden}

Actually I was asking about BANKSEL in general. But it's clear now that it
doesn't track.

>
> Of course, if the BANKSEL is never run at all, it will not
> generate any code either... :-)

Correct. So it can be used in my macro. In fact it may be a good idea.
Using BANKSEL would backport my macro back to the older family of chips too
because BANKSEL will properly twiddle the appropriate bits, whereas mine
specifically does a MOVLB, which is an enhanced 16F only instruction.
Personally I'm not pressed because I'm never planning on moving back to the
older chips ever. With enhanced chips in every package size, I cannot see a
good reason to every move back.

BAJ

{Quote hidden}

> >>

2012\04\25@082946 by Jan-Erik Soderholm

face picon face
Byron Jeff wrote 2012-04-25 14:16:
{Quote hidden}

Ah, OK. :-)

Case closed. It's always good to clear out the details, it's
where the devil lives after all, not ? :-)

Jan-Erik.

2012\04\25@090501 by alan.b.pearce

face picon face
> Correct. So it can be used in my macro. In fact it may be a good idea.
> Using BANKSEL would backport my macro back to the older family of chips
> too because BANKSEL will properly twiddle the appropriate bits, whereas
> mine specifically does a MOVLB, which is an enhanced 16F only
> instruction.
> Personally I'm not pressed because I'm never planning on moving back to
> the older chips ever. With enhanced chips in every package size, I
> cannot see a good reason to every move back.

The other thing to note about Olins macros is that they only generate instructions for the bits in the bank selection register that require changing, where BANKSEL always generates instructions to change all the bits. Olins macros will even generate no code if no bits require changing, so splashing the macro around before every instruction that could access a register in a bank doesn't mean you fill up the code space.
-- Scanned by iCritical.

2012\04\25@095350 by Jan-Erik Soderholm

face picon face


RemoveMEalan.b.pearceTakeThisOuTspamstfc.ac.uk wrote 2012-04-25 14:54:
>> Correct. So it can be used in my macro. In fact it may be a good
>> idea. Using BANKSEL would backport my macro back to the older family
>> of chips too because BANKSEL will properly twiddle the appropriate
>> bits, whereas mine specifically does a MOVLB, which is an enhanced 16F
>> only instruction. Personally I'm not pressed because I'm never
>> planning on moving back to the older chips ever. With enhanced chips
>> in every package size, I cannot see a good reason to every move back.
>
> The other thing to note about Olins macros is that they only generate
> instructions for the bits in the bank selection register that require
> changing, where BANKSEL always generates instructions to change all the
> bits. Olins macros will even generate no code if no bits require
> changing, so splashing the macro around before every instruction that
> could access a register in a bank doesn't mean you fill up the code
> space.
'
And then, it is also worth noting that on the Enhanced Midrange PICs
(with 32 banks) *one* MOVLB instruction sets all bankbits at once.
This is one of the things that makes them perform better using
the same source code as on the old Midrange PICs. Each bank-switch
takes half the time/cycles (compared to a 4-bank PIC).

And BANKSEL of course "knows" this. :-)

Jan-Erik.

2012\04\25@130339 by Dwayne Reid

flavicon
face
Many thanks, Byron.  Its been a while since I last did any serious / difficult macro writing and you've given me much to think about.  I think that I can automate the whole process even more than my previous stuff - I had to manually set / clear the rp0 & rp1 bits with my previous (current) setup.

However, I'm confused by something:

At 08:51 PM 4/24/2012, Byron Jeff wrote:

{Quote hidden}

I'm assuming that you are shifting the target down, then back up so as to strip off the low-order address bits?  A simple 'AND' would have worked just as well - correct?  Or is there a good reason to do it your way instead of using a simple 'AND' to mask off the low-order address bits?

dwayne

-- Dwayne Reid   <spamBeGonedwaynerspamBeGonespamplanet.eon.net>
Trinity Electronics Systems Ltd    Edmonton, AB, CANADA
(780) 489-3199 voice          (780) 487-6397 fax
http://www.trinity-electronics.com
Custom Electronics Design and Manufacturing

2012\04\25@131234 by Dwayne Reid

flavicon
face
Another question / comment:

At 08:51 PM 4/24/2012, Byron Jeff wrote:

>Now that I see this method, it looks like I could do conditional assembly
>of my movlb (add an OLDBANK variable, compare it to CURBANK, and only generate
>the movlb if they differ) to optimize SETBSR.

I haven't tried to do anything like this for many years now because the early versions of MPASM and MPASMWIN couldn't handle situations where a macro changes the number of lines of code in the file between assembler passes.  The assembler would simply bail with a weird error code that was eventually explained to me by someone in Microchip's tech support department as being a 'phasing error'.  What that meant is that the assembler just couldn't deal with macro code that added or removed lines of code during assembly.

I'm certainly happy to try it but I fully expect problems with this.

dwayne

-- Dwayne Reid   <TakeThisOuTdwaynerEraseMEspamspam_OUTplanet.eon.net>
Trinity Electronics Systems Ltd    Edmonton, AB, CANADA
(780) 489-3199 voice          (780) 487-6397 fax
http://www.trinity-electronics.com
Custom Electronics Design and Manufacturing

2012\04\25@135217 by Byron Jeff

flavicon
face
On Wed, Apr 25, 2012 at 11:03:33AM -0600, Dwayne Reid wrote:
{Quote hidden}

Correct.

>  Or is there a good reason to do
> it your way instead of using a simple 'AND' to mask off the low-order
> address bits?

I already had the shift in place and was just testing quickly. At first I
simply copied the movlb line from the original macro that already had the
shift. I then realized that I needed the bank bits back in their original
location. At the time it was just faster to do the shift back instead of
trying to figure out the mask to AND.

BAJ

>
> dwayne
>
> --
> Dwayne Reid   <RemoveMEdwaynerspamTakeThisOuTplanet.eon.net>
> Trinity Electronics Systems Ltd    Edmonton, AB, CANADA
> (780) 489-3199 voice          (780) 487-6397 fax
> http://www.trinity-electronics.com
> Custom Electronics Design and Manufacturing
>
> -

2012\04\25@141209 by Dwayne Reid

flavicon
face
Hi there, Byron.

I just tried your technique and it works well.  I did have to create a separate macro for setting BSR for manipulating a bit in isolation (I have NO idea of which registers some of the newer bits belong) as shown below:

setbsr          MACRO   target          ;register
    movlb       (target >>7)            ;get bank bits
CURRBANK        set ((target >>7) <<7)  ;
    endm

setbsrbit       MACRO   target, bnum    ;bit
    movlb       (target >>7)            ;get bank bits
CURRBANK        set ((target >>7) <<7)  ;
    endm

    #define BB(reg,bit) (reg^CURRBANK),(bit)   ;bit in bank 1
    #define RB(reg) (reg^CURRBANK)             ;reg in bank 1
;usage is:  bcf     BB(_SOMEBIT)
;usage is:  movwf   RB(SOMEREG)

I'll try to get some time later today to try out the conditional assembly thing that we were talking about.

Many thanks!

dwayne

-- Dwayne Reid   <dwaynerEraseMEspam.....planet.eon.net>
Trinity Electronics Systems Ltd    Edmonton, AB, CANADA
(780) 489-3199 voice          (780) 487-6397 fax
http://www.trinity-electronics.com
Custom Electronics Design and Manufacturing

2012\04\25@145007 by Jan-Erik Soderholm

face picon face


Dwayne Reid wrote 2012-04-25 20:12:
> Hi there, Byron.
>
> I just tried your technique and it works well.  I did have to create
> a separate macro for setting BSR for manipulating a bit in isolation
> (I have NO idea of which registers some of the newer bits belong) as
> shown below:
>
> setbsr          MACRO   target          ;register
>       movlb       (target>>7)            ;get bank bits
> CURRBANK        set ((target>>7)<<7)  ;
>       endm
>
> setbsrbit       MACRO   target, bnum    ;bit
>       movlb       (target>>7)            ;get bank bits
> CURRBANK        set ((target>>7)<<7)  ;
>       endm
>

OK. I'm lost... :-)

What does the bnum parameter do ?

Jan-Erik.



{Quote hidden}

2012\04\25@154630 by Byron Jeff

flavicon
face
On Wed, Apr 25, 2012 at 08:50:06PM +0200, Jan-Erik Soderholm wrote:
{Quote hidden}

I wasn't going to ask. I'm glad thaat you did. ;-)

BAJ

{Quote hidden}

> -

2012\04\25@181129 by Dwayne Reid

flavicon
face
At 12:50 PM 4/25/2012, Jan-Erik Soderholm wrote:
> >
> > setbsrbit       MACRO   target, bnum    ;bit
> >       movlb       (target>>7)            ;get bank bits
> > CURRBANK        set ((target>>7)<<7)  ;
> >       endm
> >
>
>OK. I'm lost... :-)
>
>What does the bnum parameter do ?

Its a throw-away parameter.

My include files are all in the form of:

; INTCON Register Bits          rb 0
    #define _IOCIF  INTCON,0    ; InterruptOnChange flag            rst in sw
    #define _INTF   INTCON,1    ; RB0 INT interrupt flag            rst in sw
    #define _T0IF   INTCON,2    ; TMR0 overflow int flag            rst in sw
    #define _IOCIE  INTCON,3    ; InterruptOnChange Enable          active hi
    #define _INTE   INTCON,4    ; INTF interrupt enable             active hi
    #define _T0IE   INTCON,5    ; TMR0 interrupt enable             active hi
    #define _PEIE   INTCON,6    ; Peripheral Interrupt Enable       active hi
    #define _GIE    INTCON,7    ; global interrupt enable           active hi

INT_INIT        EQU b'11000000' ;GIE, PEI enabled
INT_SLEEP       EQU b'00011000' ;wake up from i/p & pin change (no GIE)

This allows me to manipulate bits without ever knowing or caring in which register the bit belongs to.

For example:
    bsf    _GIE
;next line of code


Another example, this time using the above macro:

;EECON1                         rb 3
    #define _RD     EECON1,0    ; Read: 1= initiate read
    #define _WR     EECON1,1    ; Write: 1= initiate write
    #define _WREN   EECON1,2    ; Erase/Write enable: 1=enable
    #define _WRER   EECON1,3    ; Erase/Write error: 1=error
    #define _FREE   EECON1,4    ; Erase/Write select: 1=Erase, 0=Write
    #define _LWLO   EECON1,5    ; Ld Wr Latches Only =1; 0= Write all data
    #define _CFGS   EECON1,6    ; Config Select =1; 0= access Program memory
    #define _EEPGD  EECON1,7    ;

    movlw  MAGIC_VALUE_ADDRESS
    setbsr  EEADRL
    movwf   RB(EEADRL)
    clrf    RB(EEADRH)

;somewhere later in the code, now I want to read that value.  I have no idea of what value BSR contains, so I need to set up the BSR register.  Because I'm lazy, I don't want to go and find out what register the "_RD" bit belongs to.  So I use the macro:

    setbsrbit  (_RD)
    bsf    BB(_RD)

Note how "_RD" expands to EECON1,0  - this means that the macro has two parameters passed to it.  Since all I want is the bank in which the register belongs to, I simply throw away the second parameter.  But the macro has to be written to accept that second parameter, else the assembler gets mad at you and throws a fatal error.

[RANT ON]

Why doesn't everyone write code using #define statements like I've shown above.  It seems, to me, to be completely ridiculous that people have to string register names and bit names together to do a simple bit manipulation.  This is the new millennium, for gosh sakes!

One of the smartest people I've ever had the pleasure to learn from (Andrew Warren) showed me the above technique and I've been using it ever since.  That's back to the late '80s, early '90s.

[RANT OFF]

dwayne

-- Dwayne Reid   <EraseMEdwaynerspamplanet.eon.net>
Trinity Electronics Systems Ltd    Edmonton, AB, CANADA
(780) 489-3199 voice          (780) 487-6397 fax
http://www.trinity-electronics.com
Custom Electronics Design and Manufacturing

2012\04\26@021604 by Jan-Erik Soderholm

face picon face
OK, that make sense, with those defines. :-)

And yes, since the bits-names are unique, the
tools (MPASM) could/should be able to find out
what register they are in. Or the builtin INC
files could include those reg/bit combined defines.

Otoh, in most programs/applications there isn't
*that* much handling of the FSR. Most are setup
in the init routine, and the  some of them
(timer regs, USART tx/rx regs and so on) are used.

But yes, your defines seems to be a good thing.

Jan-Erik.

Dwayne Reid wrote 2012-04-26 00:11:
{Quote hidden}

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