2013年12月29日 星期日

Risc mcu pic16f1825 long call assembly

 ////////////////
//file bank 0 address 0x000~0x7ff
////////////////
static volatile uint8_t s_addr_low;
static volatile uint8_t s_addr_high;

void bank00_EntryPoint00()
{
    s_addr_low  = 0;
    s_addr_high = 0;
    asm("return");
}

uint16_t goto_bank01()
{
    volatile uint16_t backvalue = (uint16_t)(&bank00_EntryPoint00);
    s_addr_low    = (uint8_t)(backvalue & 0x00ff);
    s_addr_high   = (uint8_t)(backvalue >> 8);
    
    asm("bsf PCLATH,3");
    asm("bcf PCLATH,4");
    asm("bcf PCLATH,5");
    asm("bcf PCLATH,6");

    __asm__ volatile(
                     "movf _s_addr_low,W    \n"
                     "movwf FSR0L           \n"
                     "movf _s_addr_high,W   \n"
                     "movwf FSR0H           \n"
                     "call  0x3a0           \n"
                    );
    
    __asm__ volatile(
                     "movf  FSR0L,W         \n"
                     "movwf _s_addr_low     \n"
                     "movf  FSR0H,W         \n"
                     "movwf _s_addr_high    \n"
                    );
    
    backvalue = s_addr_high;
    backvalue = (backvalue << 8) | s_addr_low;
    
    return backvalue;
}

int16_t zeroJob()
{
    int16_t ret = 0;
    return ret;
}

//keep code bank00_EntryPoint00, bank00_EntryPoint01
void bank00_InitFunction(int16_t value)
{
    switch(value)
    {
        case -1:
            bank00_EntryPoint00();
            bank00_EntryPoint01();
            break;
        default:
            break;
    }
}

int main(void)
{
    bank00_InitFunction(zeroJob()); //must use it to keep symbol address
    SYSTEM_Initialize();

    goto_bank01();

    while(1)
    {
        __delay_us(1000);
    }
    return 0;
}    
    
////////////////    
//file bank 1 link address 0x800~0xfff
////////////////
static volatile uint8_t s_addr_low;
static volatile uint8_t s_addr_high;

void bank01_Jump(uint16_t addrfunc)
{
    s_addr_low    = (uint8_t)(addrfunc & 0x00ff);
    s_addr_high   = (uint8_t)(addrfunc >> 8);
    
    __asm__ volatile("movf _s_addr_high,W   \n"
                     "movwf PCLATH          \n"
                     "movf _s_addr_low,W    \n"
                     "movwf PCL             \n");
}

void bank01_Call(uint16_t addrfunc)
{
    s_addr_low    = (uint8_t)(addrfunc & 0x00ff);
    s_addr_high   = (uint8_t)(addrfunc >> 8);

    __asm__ volatile("movlw 0xED                                \n"
                     "movwf FSR0L                               \n"
                     "movlw 0x0F                                \n"
                     "movwf FSR0H                               \n"
                     "movf  INDF0,W                             \n"
                     "incf  WREG, F                             \n"
                     "movwf INDF0                               \n"

                     "movlw 0xEE                                \n"
                     "movwf FSR0L                               \n"
                     "movlw 0x0F                                \n"
                     "movwf FSR0H                               \n"
                     "movlw (bank01_back_label & 0x00ff)        \n"
                     "movwf INDF0                               \n"
                     
                     "movlw 0xEF                                \n"
                     "movwf FSR0L                               \n"
                     "movlw 0x0F                                \n"
                     "movwf FSR0H                               \n"
                     "movlw ((bank01_back_label >> 8) & 0x00ff) \n"
                     "movwf INDF0                               \n"

                     "movf _s_addr_high,W                       \n"
                     "movwf PCLATH                              \n"
                     "movf _s_addr_low,W                        \n"
                     "movwf PCL                                 \n"
                     "bank01_back_label:                        \n");
}

void bank01_EntryPoint01() __at(0x0ba0) //offset 0x3a0
{
    volatile uint16_t backvalue;
    
    __asm__ volatile("movf  FSR0L,W         \n"
                     "movwf _s_addr_low     \n"
                     "movf  FSR0H,W         \n"
                     "movwf _s_addr_high    \n");
    
    backvalue = s_addr_high;
    backvalue = (backvalue << 8) | s_addr_low;
        
    bank01_Call(backvalue); //test
    
    asm("bcf PCLATH,3");
    asm("bcf PCLATH,4");
    asm("bcf PCLATH,5");
    asm("bcf PCLATH,6");

    s_addr_low   = backvalue & 0xFF;       // Low byte of the parameter
    s_addr_high  = (backvalue >> 8) & 0xFF; // High byte of the parameter
    s_addr_low++; //test
    __asm__ volatile("movf _s_addr_low,W    \n"
                     "movwf FSR0L           \n"
                     "movf _s_addr_high,W   \n"
                     "movwf FSR0H           \n");

    asm("return");
}

int16_t zeroJob()
{
    int16_t ret = 0;
    return ret;
}

void bank01_InitFunction(int16_t value)
{
    switch(value)
    {
        case -1:
            bank01_EntryPoint00();
            bank01_EntryPoint01(0);
            break;
        default:
            break;
    }
}

int main(void)
{
    bank01_InitFunction(zeroJob()); //must use it to load symbol address
    return 0;
}

explain:
1. select page, one page 2k size
asm("bcf PCLATH,3");
asm("bcf PCLATH,4");
asm("bcf PCLATH,5");
asm("bcf PCLATH,6");

2. assembly of bank01_Call
must use indirect reg INDF0 copy value
add STKPRT content +1
low bank01_back_label address move to TOL
high bank01_back_label address move to TOH
PCLATH select page
PCL jump to address

3. assembly of bank00_EntryPoint00
asm("return");
will return to bank01_back_label

4.
volatile uint16_t backvalue;
    
__asm__ volatile("movf  FSR0L,W         \n"
                 "movwf _s_addr_low     \n"
                 "movf  FSR0H,W         \n"
                 "movwf _s_addr_high    \n");
    
backvalue = s_addr_high;
backvalue = (backvalue << 8) | s_addr_low;

pass backaddr to bank01_Call

沒有留言:

張貼留言