No exact or substring matches. trying for part
PICList
Thread
'[PIC]: Anyone have a solid strategy for code that '
2001\01\09@071114
by
ranma
|
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
|
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
> 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_OUTolinTakeThisOuT
embedinc.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
>
>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
2001\01\09@110126
by
JP.BROWN
|
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.BrownKILLspam
@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
|
On Tue, 9 Jan 2001 22:44:06 +1100, you wrote:
{Quote hidden}>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.
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
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
2001\01\09@185018
by
Matt Bennett
|
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
|
>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
xandinho
KILLspaminterlink.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
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
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 .....listservKILLspam
.....mitvma.mit.edu with SET PICList DIGEST in the body
2001\01\10@150439
by
Olin Lathrop
> 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_OUT
TakeThisOuTembedinc.com, http://www.embedinc.com
--
http://www.piclist.com#nomail Going offline? Don't AutoReply us!
email listserv
spam_OUTmitvma.mit.edu with SET PICList DIGEST in the body
2001\01\11@034748
by
Snail Instruments
|
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@snailKILLspam
iol.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-requestKILLspam
mitvma.mit.edu
2001\01\11@090535
by
Olin Lathrop
> 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, RemoveMEolinTakeThisOuT
embedinc.com, http://www.embedinc.com
--
http://www.piclist.com hint: To leave the PICList
spamBeGonepiclist-unsubscribe-requestspamBeGone
mitvma.mit.edu
2001\01\11@094426
by
Bob Ammerman
>
> > 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-requestEraseME
spam_OUTmitvma.mit.edu
More... (looser matching)
- Last day of these posts
- In 2001
, 2002 only
- Today
- New search...