Searching \ for '[PIC]: Anyone have a solid strategy for code that' 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/devices.htm?key=pic
Search entire site for: 'Anyone have a solid strategy for code that'.

Exact match. Not showing close matches.
PICList Thread
'[PIC]: Anyone have a solid strategy for code that '
2001\01\09@071114 by ranma

flavicon
face
Hi guys,

The code for my project has been growing beyond the first 2k page of my
16F877 for some time now. I have moved as much code and subroutines as
possible into Page 1. I have all the right macros for doing cross-page calls
and gotos, but *@#% it, it is never quite that simple, is it?.

There is always something that has a problem with running in a certain page
or being accessed from another page. To save me from
death-through-debugging, I wanted to ask the group what strategies people
had for managing large code the spans pages on these chips.

It is a bit more complex than saying "Put the less-used subs in Page 1" as
nothing in my code is much less used than anything else.

A typical problem is as follows: You have a large number of calls to a
subroutine from various spots, all residing in page 0. You decide to move
the subroutine to page 1, because you're desperate for space in page 0. You
then have to change all calls to the subroutine to xcalls/longcalls/whatever
to make it all work. You recompile and discover that while moving the
subroutine gave you say, 100 bytes free space in page 0, you lost 60 bytes
of those because of the 30 times you now call it with your macro!. If the
subroutine is small, you can actually be worse off than you were.

As my code tries to be as size efficient as possible (in a linear addressing
world) there are a lot of subroutines and a great many calls to them. Moving
any to another page is perilous or pointless because of the code that the
macros generate. I of course try to minimise this code by using the single
page call macros, you know...

pcall   MACRO   LABEL           ;Page call - only for jumps to page 1 from page 0
       bsf     PCLATH,3
       CALL    LABEL
       bcf     PCLATH,3        ;Needed for sanity
       ENDM

I am interested to hear if anyone has been down this path before and thought
out a really good way to have a large piece of code with LOTS of subroutines
run happily across multiple pages with minimal page swapping macros.

Anyone?.

Dave. (Totally paged out... >:-o)

--
http://www.piclist.com hint: The PICList is archived three different
ways.  See http://www.piclist.com/#archives for details.


2001\01\09@093351 by Don Hyde

flavicon
face
I move, not a single subroutine, but rather a piece of functionality.

Most problems involve a set of functions that interact intimately with one
another, but have more limited interaction with the rest of the system.
When you move a group of subroutines that work together to implement some
sort of subsystem, you will also tend to move a lot of calls between them as
well.  This can also apply to data structures and temporary variables as
well, so that, for instance, your code in page 1 may also mostly be
referring to data in bank 1, so you may be able to reduce bank switching as
well.

Good functional design in the first place calls for cutting up the big
problem into a set of subproblems that you can draw circles around.  For
each of these you define an interface to the rest of the little world inside
your processor.  A system conceived in such terms tends to be much easier to
subdivide into neat partitions that lend themselves to being segregated into
a page or bank.  For embedded programmers, I can highly recommend a year or
two of struggling to master the "object-oriented design" philosophy behind
languages like C++.  That tough mental excercise will alter the way you
think about problems and drive you to find their natural divisions.

After the fact, with an existing design, it can be really hard to see its
natural divisions, or to tease the code apart along those natural fault
lines.  This I know from hard experience.  But you can learn to look forward
to each new design as an opportunity to see its structure more clearly.

One might philosophically appreciate banking and paging as in impetus toward
better-structured design, but it never ceases to be a major pain in the @ss.
There are many things to appreciate about the PIC line of microcontrollers,
but their designers' descent into the hell of banking and paging has left
them permanently disfigured.  The two most productivity-demolishing and
bug-enhancing disasters a hardware architect can inflict on programmers are
bank switching and paging, and PIC's have both.

> {Original Message removed}

2001\01\09@095331 by Olin Lathrop

face picon face
> There is always something that has a problem with running in a certain
page
> or being accessed from another page. To save me from
> death-through-debugging, I wanted to ask the group what strategies people
> had for managing large code the spans pages on these chips.

I make each code page a separate linker section.  This guarantees that each
module is entirely on one page.  I also make it a convention that PCLATH is
set for the page the code is on.  If you do these two things, then you can
always do local GOTOs and CALLs without having to worry about paging.  You
only have to set PCLATH when jumping or calling to an external routine.  You
also have to reset PCLATH to the current page after a return from an
external subroutine.

I use a bunch of macros to make this easy.  See http://www.embedinc.com/pic.
Take a look at the macros GCALL (global call), MCALL (module call), and
GJUMP (global jump) in STD.INS.ASPIC.  These rely on page switching macros
like SETPAGE and MYPAGE.  Note that SETPAGE works around the PAGESEL bug.
(Didn't know there was a PAGESEL bug, did ya?)

> It is a bit more complex than saying "Put the less-used subs in Page 1" as
> nothing in my code is much less used than anything else.

Right.  If you do what I suggested above then you just let the linker plunk
each module wherever it wants.  The only things you need to put at specific
addresses are the startup vector and the interrupt routine.  (In theory you
could put the interrupt routine anywhere as long as the vector is at the
right location, but I always start the interrupt routine right at the vector
address.  This saves a few instructions on every interrupt, and it also
allows for optimizations in the interrupt routine if you know it is always
in page 0.  For example, you can to a CLRF PCLATH instead of loading it with
the some non-zero value).

> A typical problem is as follows: You have a large number of calls to a
> subroutine from various spots, all residing in page 0. You decide to move
> the subroutine to page 1, because you're desperate for space in page 0.

There's your problem.  You shouldn't be messing with page allocations
manually.  Doing it yourself is error prone and makes the code difficult to
maintain.

> I am interested to hear if anyone has been down this path before and
thought
> out a really good way to have a large piece of code with LOTS of
subroutines
> run happily across multiple pages with minimal page swapping macros.

Yup, I've done multi-page projects many times without having to deal with
this stuff.  Just don't worry about the small number of extra instructions
it takes to call accross page boundaries.  The vast majority of times, two
or three extra cycles isn't an issue when you are calling an external
subroutine.  If it is, then maybe you should put the code in a macro in an
include file and insert it in line when speed is important.  Since 2
instructions make a difference, the "subroutine" code is presumably small.


*****************************************************************
Olin Lathrop, embedded systems consultant in Devens Massachusetts
(978) 772-3129, spam_OUTolinTakeThisOuTspamembedinc.com, http://www.embedinc.com

--
http://www.piclist.com hint: The PICList is archived three different
ways.  See http://www.piclist.com/#archives for details.


2001\01\09@103201 by David VanHorn

flavicon
face
>
>I am interested to hear if anyone has been down this path before and thought
>out a really good way to have a large piece of code with LOTS of subroutines
>run happily across multiple pages with minimal page swapping macros.
>
>Anyone?.
>
>Dave. (Totally paged out... >:-o)


Three letters.. A V R.
No pages. Ever.
:)

--
Where's dave? http://www.findu.com/cgi-bin/find.cgi?kc6ete-9

--
http://www.piclist.com hint: The PICList is archived three different
ways.  See http://www.piclist.com/#archives for details.


2001\01\09@103826 by Andrew Kunz

flavicon
face
>Three letters.. A V R.


HA!  I beat you - one letter!

C

Andy

--
http://www.piclist.com hint: The PICList is archived three different
ways.  See http://www.piclist.com/#archives for details.


2001\01\09@110126 by JP.BROWN

flavicon
face
I think the answer to this (especially if time is money) is to use a
compiler many compilers are very efficient at using available space and
resources and the nitty gritty paging stuff is taken care of for you.
Pic assembly language is deceptively simple, you can soon learn
to write simple programs but to produce large complex programs requires a
lot of skill and time (and debugging). I have written a lot of assembly
programs for the 68000 and this was easy compared to the Pic, sometimes
one 68000 instruction will do what takes half a page of difficult to
understand Pic code.

--- John


> > There is always something that has a problem with running in a certain
> page
> > or being accessed from another page. To save me from
> > death-through-debugging, I wanted to ask the group what strategies people
> > had for managing large code the spans pages on these chips.
>


         -----  John P. Brown      .....J.P.BrownKILLspamspam@spam@bradford.ac.uk ----
          \            --- Witty remark goes here ---         /
           --------------------------------------------------

--
http://www.piclist.com hint: The PICList is archived three different
ways.  See http://www.piclist.com/#archives for details.


2001\01\09@111402 by mike

flavicon
face
On Tue, 9 Jan 2001 22:44:06 +1100, you wrote:

{Quote hidden}

Been there.... This particular problem, of subroutines  called from
lots of places, is easily solved efficiently - for each page-1 routine
have a page-select and goto to it in page zero. adds a minor time
penalty but space is usually more important.
After the first call of a subroutine, this adds no page-swap code
overhead for subsequent calls, so is 'profitable' for any routines
called more then once.

It can also be useful for all page 1 subroutines to exit via a common
point that clears the page 1 bit first. This avoids the page 0 call
having to worry about whether the routine is in page 0 or 1 - things
tend to move about as code grows & changes...!

e.g. page 0 : ..
call p0sub1
...
call p0sub1
....


p0sub1   bsf pclath,page1bit
errorlevel -306 ; supress warning, you know what you're doing...
goto p1sub1
errorlevel +306 ; re-enable warning to catch real errors.

page 1 :

p1sub1
....
goto p1exit



p1exit
bcf pclath,page1bit
return


Having a consistent naming convention is important to avoid major
debug headaches.

Obviously it helps a lot to group subroutines by page to reduce the
number of page-bit swaps, e.g. all subs called by p1sub1 above live in
page 1.

For routines called only once, returning via the 'clear page bit' exit
point is still useful as the calling code doesn't need to clear it.

--
http://www.piclist.com hint: The PICList is archived three different
ways.  See http://www.piclist.com/#archives for details.


2001\01\09@121417 by mike

flavicon
face
On Tue, 9 Jan 2001 10:29:28 -0500, you wrote:

>>
>>I am interested to hear if anyone has been down this path before and thought
>>out a really good way to have a large piece of code with LOTS of subroutines
>>run happily across multiple pages with minimal page swapping macros.
>>
>>Anyone?.
>>
>>Dave. (Totally paged out... >:-o)
>
>
>Three letters.. A V R.
>No pages. Ever.
>:)
no chips either...

Limited branch range is a pain though!

--
http://www.piclist.com hint: The PICList is archived three different
ways.  See http://www.piclist.com/#archives for details.


2001\01\09@142356 by David VanHorn

flavicon
face
>
>Limited branch range is a pain though!

I've only hit that once..

As to stocking, I've got all I neeed.
Digikey has stock too.

--
Where's dave? http://www.findu.com/cgi-bin/find.cgi?kc6ete-9

--
http://www.piclist.com hint: The PICList is archived three different
ways.  See http://www.piclist.com/#archives for details.


2001\01\09@185018 by Matt Bennett

flavicon
face
David VanHorn wrote:
>
> >
> >Limited branch range is a pain though!
>
> I've only hit that once..
>
> As to stocking, I've got all I neeed.
> Digikey has stock too.

This is a very real problem- and strongly affects many decisions.  About
8 months ago, I was working on a project that was based around an AVR-
an 8515- we were getting *26* week lead times for quantities in the 10K
reigon, and even then nobody would guarantee us parts.  That put us way
outside of our manufacturing window.  The company that I was working for
at the time was a *big* company, that used lots of parts, so Atmel
really wanted our buisness, but they just couldn't deliver.  Atmel was
devoting their foundry capability to making large flash memories, and
ignoring their uC demand because it has a lower margin.  They have shown
that their primary concern is not microcontrollers.  Microchip at least
appears to be committed to microcontrollers.

Even Digi-Key has supply problems for Atmel parts: for the
AT90S8515A-8JC (an 8MHz, Commercial temperature range (I think) PLCC)
they have this message: "Due to extended lead-time we are unable to
backorder, no delivery date available."  Yes, they do have some smaller
quantities available of other parts, but nowhere near the quantities (or
prices) that you need for large scale manufacturing.

The company I used to work for is going to think very, very hard before
they design another Atmel part into a product. Lets face it, *most* of
us here are not huge manufacturing concerns.  Our lifetime use of these
parts would hardly make a blip on Microchip's or Atmel's forecasts.  We
have some good parts and good tools because they forsee selling a large
quantity of these parts.  But if they can't deliver, the big boys will
stop buying, and we won't have them to play with. I really liked a lot
of things about the AVR, but there is one great advantage about the PIC-
I can get them.

Matt

--
http://www.piclist.com hint: The PICList is archived three different
ways.  See http://www.piclist.com/#archives for details.


2001\01\09@193721 by dre Domingos F. Souza

flavicon
face
>The company I used to work for is going to think very, very hard before
>they design another Atmel part into a product. Lets face it, *most* of
>us here are not huge manufacturing concerns.  Our lifetime use of these
>parts would hardly make a blip on Microchip's or Atmel's forecasts.  We
>have some good parts and good tools because they forsee selling a large
>quantity of these parts.  But if they can't deliver, the big boys will
>stop buying, and we won't have them to play with. I really liked a lot
>of things about the AVR, but there is one great advantage about the PIC-
>I can get them.

       An interesting subject: Why do you do embeeded programming? Is it for your own fun? Or is it for profit??? If it's for your fun, anything you code will suit - Even a BASIC program in a 8052 (another good question: In english, when you use the "a" before a number as it were a consonant, or "an" as if it were a vowel?) will work ok to you. But if you are doing that for profit, the first thing a smart company will ask you to do is "redesign it using the xxx processor". And better you know how to do it, because if else, your project won't be approved. That's where the support - in engineering and sale - fits, what if you make a revolutionary device using the Atmel MCU, if you can't buy it to make 1k???


--------------8<-------Corte aqui-------8<--------------

       All the best!!!
       Alexandre Souza
       xandinhospamKILLspaminterlink.com.br
       Linux User #85093

--------------8<-------Corte aqui-------8<--------------

--
http://www.piclist.com hint: The PICList is archived three different
ways.  See http://www.piclist.com/#archives for details.


2001\01\10@054825 by ranma

flavicon
face
Hi again guys,

Thanks to everyone that replied so far. I have received many very helpful
responses and also a few from the AVR crowd... :-)

Thanks especially to Olin Lathrop. If you guys have not had a chance to look
at his page (linked below) then you are missing out on something. I have
seen many different people's macro pages, but NOTHING is like this. It even
has a software stack with PUSH and PULL macros!.

I am going to sit on a mountaintop now and meditate over these sage answers
and think how best to rearrange my code. Next project, I'll use Olin's
macros for sure.

Kind regards,

David

{Original Message removed}

2001\01\10@132703 by Javi2

flavicon
face
I use this macro to forget cross-pages calls.
Runs ok with Microchip's boot loader in order
to re-use serial routines located in page 4.

;----- START CODE ------
; save_w is a RAM location to save W register.

Call_page MACRO adress_new, save_w
 local a = high $
 local b = high adress_new
 if a == b
  call  adress_new
 else
  movwf  save_w
  pagesel adress_new
  movf  save_w,w
  call  adress_new
  movwf  save_w
  pagesel $
  movf  save_w,w
 endif
 endm

;----- END CODE ------


Regards, Javier Martmnez.

--
http://www.piclist.com#nomail Going offline? Don't AutoReply us!
email .....listservKILLspamspam.....mitvma.mit.edu with SET PICList DIGEST in the body


2001\01\10@150439 by Olin Lathrop

face picon face
> Call_page MACRO adress_new, save_w
>   local a = high $
>   local b = high adress_new
>   if a == b
>    call  adress_new
>   else
>    movwf  save_w
>    pagesel adress_new
>    movf  save_w,w
>    call  adress_new
>    movwf  save_w
>    pagesel $
>    movf  save_w,w
>   endif
>   endm

Note that this only works if ADDRESS_NEW is known at assembly time.


*****************************************************************
Olin Lathrop, embedded systems consultant in Devens Massachusetts
(978) 772-3129, EraseMEolinspam_OUTspamTakeThisOuTembedinc.com, http://www.embedinc.com

--
http://www.piclist.com#nomail Going offline? Don't AutoReply us!
email listservspamspam_OUTmitvma.mit.edu with SET PICList DIGEST in the body


2001\01\11@034748 by Snail Instruments

flavicon
face
Hi David,

I remember the hard time I had when my projects hit 2K boundary for the
first time. I have developed some techniques to deal with pages, maybe you
can adopt some of them. I always maintain PCLATH set to the current page
for reasons mentioned in earlier post.

Josef

1. Short routines can be copied in both (all) pages. A #define will take
care about choosing the right one. You call them by short calls only.

#define TXCHAR  TXCHAR_#V($>>11)

This routine can be copied (without changes) at every page (if needed).
; ------------------------------
; TRANSMIT CHARACTER IN W
; ------------------------------
TXCHAR: BTFSS   _TXIF
       GOTO    TXCHAR
       MOVWF   TXREG
       RETURN

2. Longer routines that make no (or very few) calls to the rest of the
program can jump to another page. The routine can be called from page0
only, but takes up just two words of page0.

page0:

LONGSUB:BSF     PCLATH,3
       GOTO    LONGSUB_CONT

page1:

LONGSUB_CONT:
       ....lot of code
       ....as few as possible calls to page0
       BCF     PCLATH,3
       RETURN

3. Simplified access to routines in another page. Uses extra stack level.
Call Anysub0 from page0, call Anysub1 from page1.

page0:

ANYSUB0:BSF     PCLATH,3
       CALL    ANYSUB1
       BCF     PCLHATH,3
       RETURN

page1:

ANYSUB1:....lot of code
       ....calls to page1
       ....lot of code
       RETURN

4. Some other useful macros, I have no idea how they work, but I'd assume
they are self-explanatory:

BSFPCLH MACRO   BIT
IFNDEF __PCLATH
__PCLATH SET    0
ENDIF
       BSF     PCLATH,BIT
__PCLATH SET    __PCLATH | (0x01<<BIT)
       ENDM

BCFPCLH MACRO   BIT
IFNDEF __PCLATH
__PCLATH SET    0
ENDIF
       BCF     PCLATH,BIT
__PCLATH SET    __PCLATH & (~(0x01<<BIT))
       ENDM

CLRFPCLH MACRO
       CLRF    PCLATH
__PCLATH SET    0
       ENDM

LDBPCLH MACRO   ADRHI
       MOVLW   ADRHI
       MOVWF   PCLATH
__PCLATH SET    ADRHI
       ENDM

LLCALL  MACRO   DEST    ;LONG CALL
IFNDEF __PCLATH
__PCLATH SET    0
ENDIF
IF ((__PCLATH ^ HIGH DEST) & 0xF8) == 0
       ERRORLEVEL -0306
ENDIF
       CALL    DEST
       ERRORLEVEL +0306
       ENDM

LLGOTO  MACRO   DEST    ;LONG GOTO
IFNDEF __PCLATH
__PCLATH SET    0
ENDIF
IF ((__PCLATH ^ HIGH DEST) & 0xF8) == 0
       ERRORLEVEL -0306
ENDIF
       GOTO    DEST
       ERRORLEVEL +0306
__PCLATH SET    HIGH $
       ENDM


=======================================================================
Electronical devices for chemical laboratory, custom electronics design
-----------------------------------------------------------------------
Snail Instruments                      Josef Hanzal, M. S.
Vojanova 615                           phone/fax: +420-311-624433
266 01 Beroun                          e-mail: @spam@snailKILLspamspamiol.cz
Czech Republic                         URL: http://www.vitrum.cz/snail/
GPS: 49deg58'28" North, 14deg 4'35" East
=======================================================================

--
http://www.piclist.com hint: To leave the PICList
KILLspampiclist-unsubscribe-requestKILLspamspammitvma.mit.edu


2001\01\11@090535 by Olin Lathrop

face picon face
> 2. Longer routines that make no (or very few) calls to the rest of the
> program can jump to another page. The routine can be called from page0
> only, but takes up just two words of page0.
>
> page0:
>
> LONGSUB:BSF     PCLATH,3
>         GOTO    LONGSUB_CONT

This only works on machines with 2 code pages.  More than two requires
setting additional PCLATH bits.

> 3. Simplified access to routines in another page. Uses extra stack level.
> Call Anysub0 from page0, call Anysub1 from page1.
>
> page0:
>
> ANYSUB0:BSF     PCLATH,3
>         CALL    ANYSUB1
>         BCF     PCLHATH,3
>         RETURN

There is no need to use an extra stack level.  Just GOTO the target routine
and let it return to the caller directly.


*****************************************************************
Olin Lathrop, embedded systems consultant in Devens Massachusetts
(978) 772-3129, RemoveMEolinTakeThisOuTspamembedinc.com, http://www.embedinc.com

--
http://www.piclist.com hint: To leave the PICList
spamBeGonepiclist-unsubscribe-requestspamBeGonespammitvma.mit.edu


2001\01\11@094426 by Bob Ammerman

picon face
>
> > 3. Simplified access to routines in another page. Uses extra stack
level.
> > Call Anysub0 from page0, call Anysub1 from page1.
> >
> > page0:
> >
> > ANYSUB0:BSF     PCLATH,3
> >         CALL    ANYSUB1
> >         BCF     PCLHATH,3
> >         RETURN
>
> There is no need to use an extra stack level.  Just GOTO the target
routine
> and let it return to the caller directly.

The CALL is there so that the PCLATH can be fixed up (BCF PCLATH,3) before
returning to the caller.

Bob Ammerman
RAm Systems
(contract development of high performance, high function, low-level
software)

--
http://www.piclist.com hint: To leave the PICList
TakeThisOuTpiclist-unsubscribe-requestEraseMEspamspam_OUTmitvma.mit.edu


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