I'm reading resources related to PIC optimizations and I've found document called MPLAB® C18 OPTIMIZATION TIPS. One of the things it mentions is Access RAM. I know that it is the part of RAM which can be used without the need to use the bank access register and that it allows for faster access to variables stored in it, but it's still not very clear to me how exactly should I use it manually and when I should expect the compiler to populate it with variables.

  • 1
    \$\begingroup\$ At first I didn't understand why this was difficult to grasp, but after looking at that guide I agree - I have no idea what they're trying to show, which variable is in access ram, or even how the C code relates to the ASM. \$\endgroup\$
    – AngryEE
    Commented Apr 26, 2012 at 19:07

2 Answers 2


RAM addresses on a PIC 18 are 12 bits wide. That is too much to include in single-word instructions, which are only 16 bits wide. To use less address bits in instructions than the memory actually has, the PIC 18 uses a segmented architecture. This means RAM is divided into segments which the PIC documentation calls banks. Each bank holds 256 bytes. A full memory holds 4096 bytes, so there are 16 banks. The 8 bit address offset within a bank is specified in instructions and the 4 bit bank number is specified with state that can be set at run time, which is called the BSR register.

To allow for more efficient access to a selected portion of this 4096-byte or 16-bank memory, instructions actually contain one more address bit. This bank selects between one of two banks, the bank identified by BSR and the access bank, which is a fixed set of 256 bytes defined for that PIC. The 256 bytes of the access bank is split between some of the special function registers at the end of bank 15 and some general RAM at the start of bank 0. Where this split is, meaning how many bytes of the access bank are in bank 0 and how many in bank 15 varies between models in the PIC 18 family.

The purpose of the access bank in general is for fast access to any of the selected 256 locations independent of the current BSR setting. Certain core registers are always in the access bank part in bank 15, like STATUS, PRODH, PRODL, etc. The advantages of this should be obvious, in that code is not needed to set BSR, and that accessing these registers can preserve BSR.

The advantage in general RAM is similar. Application code can access variables in that part of the access bank without the overhead of having to set the current bank, which again therefore also doesn't corrupt the current bank setting. Since the amount of access memory available for registers is limited, you have to consider carefully what you want to place there and what is better placed in banked memory so that something else can benefit from the fast access of the access bank. For example, the access bank is generally inappropriate for large buffers. A single buffer could easily be larger than the general RAM part of the access bank, and it is likely addressed indirectly thru the FSR registers anyway. These contain the full 12 bit address so banking doesn't apply to indirect references.

In general, keep the often-used individual and genarally global variables in the access bank. There is a lot of room if you're using it only one byte at a time. In my system, by default, I use the first 16 bytes as general registers that are used frequently as local scratch and for passing parameters into and out of subroutine. These get banged around a lot, so they benefit from the easy access. After that, I usually put individual global variables in the access bank and the private local state of each module wholly in one bank when this is possible and reasonable. That means code in any one module only needs to access data in one bank and the few global variables in the access bank.

Of course those are just general guidlines. Every project is different and you have to think about what makes sense.

To allocate memory in the access bank in assembler, you use the UDATA_ACS directive instead of just UDATA for banked memory. I think the compiler has a similar sounding mechanism. See the compiler manual for details.

  • \$\begingroup\$ Hi, will the use of access bank addresses interfere with the values of SFR registers? In PIC18, addresses from 0xFD8 to 0xFFF are being used as SFR. \$\endgroup\$
    – dnth
    Commented Jun 15, 2016 at 11:43

Depending upon which PIC and instruction set you're using, there may be anywhere from 0 to 128 bytes of "access RAM". Variables placed within access RAM can be accessed more quickly, and with less code, than variables elsewhere, but unless a program is pretty simple it won't be possible to put all variables in access RAM. Compilers may theoretically be able to judge how much code would be saved by placing particular variables or combinations thereof in access RAM, but I've never seen one do a good job of it. Further, compilers generally can't tell what speedups are apt to be important or unimportant. Consequently, it is sometimes helpful for programmers to designate certain variables for placement in Access RAM. Placing as many variables as possible in Access RAM generally won't hurt, provided that there's room in Access RAM for all the variables so designated. Attempting to place more variables in Access RAM than will fit will generally cause a linker error.

  • \$\begingroup\$ 1: I don't believe there is any PIC 18, nor will there ever be, with 0 bytes in the general RAM part of the access bank. 2: overflowing the access bank causes a linker error, not a compiler error. \$\endgroup\$ Commented Apr 26, 2012 at 20:10
  • \$\begingroup\$ @OlinLathrop: The data sheet for the PIC18F8722 specifies that access bank addresses 0x60-0xFF represent SFR's, and specifies that when XINST is enabled, access bank addresses 0x00-0x5F represent indirect accesses off FSR2. What range of access-bank addresses would map to RAM? \$\endgroup\$
    – supercat
    Commented Apr 26, 2012 at 21:26
  • \$\begingroup\$ @OlinLathrop: I would think it silly for a PIC to have XINST mode turn ALL of Access RAM into indirect addressing space off FSR2 (actually, I think gobbling up more than 32 bytes for FSR2 is just plain wasteful; optimal usage would probably be to use 15 bytes for addressing off FSR2 and 7 each for FSR0 and FSR1). Nonetheless, by my reading of the data sheet, the aforementioned PIC does precisely that. \$\endgroup\$
    – supercat
    Commented Apr 26, 2012 at 21:54
  • \$\begingroup\$ I wasn't thinking about the extended instruction set. I don't know how that effects the access bank off the top of my head. I do remember looking at the extended instruction set when it first came out and deciding that it had more drawbacks than benefits to me, especially considering how my PIC development environment already uses the PIC 18. \$\endgroup\$ Commented Apr 26, 2012 at 23:25
  • \$\begingroup\$ @OlinLathrop: Hence my comment, "depending upon which PIC and instruction set". The only disadvantage of the extended instruction set is that it gobbles up access RAM. If one could give up 15 bytes of access RAM for indirect addressing off FSR2 (with offsets of 1-15 bytes), and 3 or 7 bytes each off FSR0 and FSR1, that would probably worth the amount of that much access RAM in many applications. Unfortunately, for whatever reason, Microchip requires applications that use extended instruction set at all to give up 96 bytes of access RAM for FSR2 addressing. \$\endgroup\$
    – supercat
    Commented Apr 27, 2012 at 14:46

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.