PIC18F24k22 MPASM Code Generation Issue

Discussion in 'Embedded Systems and Microcontrollers' started by Sensacell, Jun 30, 2012.

  1. Sensacell

    Thread Starter Well-Known Member

    Jun 19, 2012
    1,132
    267
    Hello,

    I am writing assembly code for the PIC18F24K22 part under MPLAB / MPASM.

    I have discovered that MPASM sets the 'a' bit in an instruction automatically in a complex and somewhat disturbing manner, consider the following list file snippet: (intended only to illustrate the assembler behavior- not real code)

    LOC OBJECT CODE LINE SOURCE TEXT
    VALUE


    000138 0101 00706 movlb 1 ;point to bank 1
    00013A 0EEA 00707 movlw 0xEA ;load W with value
    00013C 6E5F 00708 movwf 0x5F ;A bit =0, BSR ignored!
    00013E 6F60 00709 movwf 0x60 ;A bit =1, BSR included!
    000140 6F5F 00710 movwf CCPR3H ;A bit =1, BSR included!
    000142 6E60 00711 movwf SLRCON ;A bit =0, BSR ignored!

    Note how MPASM decides to set the 'a' bit in the instruction differently for
    the SAME ADDRESS, depending on if it's specified by a mnemonic
    or literal address! Passing the boundary 0x5F-0x60 reverses everything!

    I understand that this boundary is where GPR and SFR meet in the access bank in this part, which is a big clue.

    How are you supposed to write code that works with sneaky little things like this going on under your nose?

    Is there some documentation that explains this?
     
  2. takao21203

    Distinguished Member

    Apr 28, 2012
    3,577
    463
    18F + assembler is complex and disturbing as such.

    You can specify
    Code ( (Unknown Language)):
    1. ,ACCESS
    , however.
     
  3. nickelflipper

    Active Member

    Jun 2, 2010
    280
    35
    Microchip has extended the SFR register number to beyond its 256 byte limitation. In these newer 18f chips, with all the multiplexing that is going on, so you may have to use bankselect, depending on the register map. This happen to me when trying to access CCP3CON. I am no assembly guy, so no doubt there are some extra bankselect's in the below code, but it did work.

    Code ( (Unknown Language)):
    1. ;******** CCP3 *****************
    2.     movlw   12      ;std PWM mode
    3.     banksel CCP3CON
    4.     movwf   CCP3CON
    5.     movlw   128     ;set CCP3 PWM timer as TMR6
    6.     banksel CCPTMRS0
    7.     iorwf   CCPTMRS0
    8.     movlw   100     ;100 instr cycles * 16 prescale * 1/16000000 = 100 us or freq. of 10kHz
    9.     banksel PR6
    10.     movwf   PR6
    11.     movlw   50      ;50% D.C. with PR4=100: 50 (instr cycles) * 16 (prescale) * 1/16000000 = 50 us
    12.     banksel CCPR3L
    13.     movwf   CCPR3L
    14.     movlw   7       ;Prescale is 16, TMR6ON=1
    15.     banksel T6CON
    16.     movwf   T6CON
     
  4. takao21203

    Distinguished Member

    Apr 28, 2012
    3,577
    463
    I wrote one larger program for 13k50 (18f) using assembler.

    I could post the source for reference, to see how messy it is to use assembler for 18F. But that's a bit off the thread topic?

    It's also written in the datasheet, how the access bank is correlating to the actual address used.

    Otherwise you have to use banksel all the time or you have to track the actual banks very carefully. So it's true assembler takes 15x the time, and can be somehow easy to write intially, but is very hard to modify for larger programs.
     
  5. JohnInTX

    Moderator

    Jun 26, 2012
    2,347
    1,029
    The assembler knows where ACCESS RAM begins and ends and, if the label specifies the full 12-bit address of the RAM, will correctly generate the ,0 ,1 suffixes by default to address RAM. The same goes for the SFRs. In most 18Fs, all SFRs are in upper ACCESS RAM and can be addressed without banking but in THIS case, SOME SFRs are indeed in banked RAM and you must 1)set BSR to point to the bank for direct access or 2) use an FSR to get to it indirectly (without changing BSR) as you would any other non-ACCESS RAM.

    You can help yourself along by specifying ,ACCESS or ,BANKED in your label references and MPASM will issue warnings if you confuse the two spaces. It can't however ensure that you are in the correct bank at run-time, that's up to you, the programmer.

    I've done a TON of MPASM/18F (and 10x/12x/16x/17x for almost 20yrs now - geeze) and find that MPASM does a great job. Still, ANY banked target architecture ultimately requires time to understand all of the quirks and some programming experience/technique to cope with them.
     
    Sensacell likes this.
  6. Sensacell

    Thread Starter Well-Known Member

    Jun 19, 2012
    1,132
    267
    Thank you for that clear explanation, I appreciate it.

    Specifying ACCESS or BANKED will save me from ruin.

    I have been programming PICs almost exclusively in assembly for a long time using MPLAB, most of the time bank switching is not a big deal, but the devil is in the details.
     
  7. takao21203

    Distinguished Member

    Apr 28, 2012
    3,577
    463
    It is still possible to write code in assembler. If you consider 24F, or PIC32, this becomes too much a learning curve. Even if you master it, you then will experience massive portability problems, as banking is all different!

    C code can in most cases become ported accross almost all PICs- from 10F to PIC32. Configuration is easier as well, in MPLABX you get a small framework already for new projects.

    I have used assembler (on PIC) for more than 5 years. I have even written some small assembler programs which run under Windows. What's the gain? In the end you only find yourself emulating things compilers do, using rather complex and complicate means, and still in no way portable.

    For instance this simple array access (on 8bit chip) results in about 30 lines assembler, nearly impossible to maintain if you code this directly in assembler. Very complex and disturbing!

    Code ( (Unknown Language)):
    1.  {palentry=palette[pixelbuffer[x]];
    2.       LCD_DataWrite((unsigned char)(palentry>>8),(unsigned char)palentry);
    3.      }
    If you take this code and move over to 16bit PIC, the assembler code will be completely different, much easier for the 24F MCU, and less lines. But, you won't have to change anything!

    And shift by 8 is replaced by special constructs, not shifted 8 times...
     
  8. takao21203

    Distinguished Member

    Apr 28, 2012
    3,577
    463
    What's really disturbing is the resulting assembler source if you need for whatever reason to use 16bit, or for instance arrays. You have to code it different for each different PIC because the RAM areas are different. Yes possible, but too much effort to read all the details. In C = simply don't care, if it is not fast enough, maybe optimize a little.

    If you are good at assembler then you can use C almost like assembler. For instance you can shift by one, and then test
    Code ( (Unknown Language)):
    1. CARRY
    , and things like that. By no means documentated, but there are many such details to improve code efficiency. The resulting assembler will be nearly 1:1, just one shift instruction, and one BTFSC for the carry flag.
     
Loading...