Jump to content

RAM Bank handling code


Duggle
 Share

Recommended Posts

Hi,

I've just realised the significance of BSR register for making sure RAM is accessable.

My understanding is as follows:

;;use macro

SET_BSR my_var

;;can now access vars on same ram page as my_var

;;so long as BANKED flag is used with instructions.

movf my_var,W,BANKED

So my question is (to try to complete my knowledge): When don't one use the BANKED flag?

Are there tricks or techniques to reduce the use of SET_BSR when working with algorithms that use variables from different RAM pages.

thanks for any comments

Link to comment
Share on other sites

A really good question, because this is a point which has not been documented very well yet.

so: FAQMARKER

  • the PIC18F offers two different addressing modes: ACCESS and BANKED
  • ACCESS is the default mode, so you don't have to specify it explicitely on every instruction. It's independent from the BSR and allows you to access addresses between 0x00-0x7f and 0xf80-0xfff (SFR range) directly without initializing the BSR
  • for BANKED accesses you have to ensure that the BSR is set correctly. So, if you are doing a lot of BANKED operations to addresses between 0x80 and 0x37f (other addresses are reserved for MIOS), you should initialize the BSR before.
  • so long as the BANKED addresses are in between a page of 128 bytes (0x80), you don't have to reinitialize the BSR before every access. This influences the "coding style": addresses which belong together should be located in between a 128 bytes range in order to reduce code (the need to change the BSR)
  • it's alway possible to copy a register value to another register by using the "movff" instruction independent from the source/target address without initializing the BSR. So, the easiest way to copy any register to the working register is: "movff ANY_REGISTER, WREG" --- but note that the "movff" instruction allocates 4 bytes, a common instruction (also SET_BSR) is only 2 bytes long, so this method should only be used if just only one register has to be copied. As soon as you plan to access more than 2 register of the same 0x80 page, it makes sense to change the BSR or:
  • it sometimes makes sense to address the register indirectly by using FSR0 (main program) or FSR2 (interrupt service routine). The FSR has to be initialized with "lfsr FSRx, ANY_REGISTER", thereafter you can access it via "INDF0", "POSTINC0", "POSTDEC0", "PLUSW0", etc...
  • note that most MIOS function are changing the BSR and FSR1 and don't restore it to the old value (to save execution time). This means: if a change of BSR is notified in the MIOS function description, and if you are using BANKED accesses, you have to restore BSR after every MIOS call. So, if you have a lot of interaction between MIOS and your main program, the use of indirect addressing (FSR0/FSR2) or the use of "movff" should be prefered in order to save code space
  • Hint: registers which have to be accessed very often should just be located below 0x80 so that you don't have to take care for the page pointer. For example, MIOS_PARAMETER[123], TMP[12345] and IRQ_TMP[12345] are located between 0x00-0x0f which makes the use of this most frequently used addresses very easy


    Best Regards, Thorsten.

Link to comment
Share on other sites

Does FSR2 get saved and restored in the ISRs?

(if not then it can't be used in user routines without disabling interrupts)?

MIOS routines use FSR1 so if I use FSR1 completely in-between MIOS calls it should be ok? (MIOS may destroy FSR1's content)

Are there any dangers of using FSR0? (It gets used by main, are there any user hooks that should restore its content  for use by main?

thanks

Link to comment
Share on other sites

FSR2 is not restored when an interrupt has been invoked, only FSR0, FSR1, TBLPTR[LH], TABLAT and MIOS_PARAMETER[123] --- the reason for this is, that you normaly never need a third pointer, only on very special cases, so I decided to left it out to ensure best performance.

Yes, by temporary disable interrupts with IRQ_DISABLE it's possible to use all three pointers in your main program. After the use of FSR2 you can enable interrupts again with IRQ_ENABLE. FSR2 don't has to be saved/restored. Such a routine should never run longer than ca. 300 uS to ensure the realtime capability (especially: receiving MIDI events).

Yes, you can use FSR1 in between MIOS calles in your main program and in interrupt service routines w/o problems. The reason why I suggest FSR0 is not to confuse newbies too much...

There is no MIOS task which uses FSR0, so it can be used without any danger.

Best Regards, Thorsten.

Link to comment
Share on other sites

  • 1 month later...

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
 Share

×
×
  • Create New...