Email: Password: Remember Me | Create Account (Free)

Back to Subject List

Old thread has been locked -- no new posts accepted in this thread
???
02/19/09 15:04
Read: times


 
#162569 - Function "Program Double Clock" never returns in IAP mode
Hi everyone,

it seems to me that function "Program Security Bit, Double Clock" (see [1] on page 27) of P89V51RD2's bootloader v7 contains a bug: it never returns when called via IAP interface. Other functions, such as "Read ID" and "Set ISP Entry Mode" (see [2]) works fine for me.

Has anyone else experienced the same problem? The values I use for the interface registers are:

  • R1 = 0x05

  • DPH = 0x00

  • DPL = 0x05

  • ACC = 0x00



More precisely, my code looks like:

//--- implemented IAP functions -----------------------------------------------
// common functions             R1   DPH  DPL  ACC
#define IAP_GET_DEVICE_ID_1     0x00,0x00,0x01,0x00 ///< request device id #1
#define IAP_GET_MANUFACTURER_ID 0x00,0x00,0x00,0x00 ///< request manufacturer id

// for device 89C51 only        R1   DPH  DPL  ACC
[...]

// for device 89V51 only        R1   DPH  DPL  ACC
#define IAP_V51_GET_BOOT_CODE_VERSION 
                                0x00,0x00,0x02,0x00 ///< read id - boot code ver
#define IAP_V51_SET_DOUBLE_CLOCK 
                                0x05,0x00,0x05,0x00 ///< program double clock
#define IAP_V51_SET_ISP_ENTRY_MODE_ALWAYS 
                                0x04,0x00,0x03,0x00 ///< run ISP after reset
#define IAP_V51_SET_ISP_ENTRY_MODE_PIN_LOW(pinl) 
                                0x04,pinl,0x01,0x00 ///< user code if pin high

void init_iap (void)
{
        BSEL = 1; // select bank 0 for reading (89V51 only)
        SWR  = 0; // make bank 1 (boot code) accessible (89V51 only)
        switch (call_iap(IAP_GET_MANUFACTURER_ID)) {

        case 0x15:                                              // Philips
                [...]
                break;

        case 0xBF:                                              // NXP (?)
                switch (call_iap(IAP_GET_DEVICE_ID_1)) {
                case 0x91:                                      // P89V51Rx2xx
                        iap.device = IAP_DEVICE_89V51;
                        if (call_iap(IAP_V51_GET_BOOT_CODE_VERSION) == 0x07)
                                return;
                        upgrade_p89v51_iap();
                        call_iap(IAP_V51_SET_DOUBLE_CLOCK);
                        call_iap(IAP_V51_SET_ISP_ENTRY_MODE_PIN_LOW(0x90 + 0));
                                                        // port P1 + pin 0
                        iap_reboot();
                }
        } // switch

        fatal_error(E_IAP_UNKNOWN_DEVICE_TYPE);
}

/// call IAP routine
/**
 * This function is a wrapper around real IAP routine placed in
 * bootcode area.
 *
 * @warning
 * The function code relies on the fact that current compiler passes
 * function parameters via registers @c R1, @c R2, @c R3, and @c R4,
 * in this order.
 *
 * @return IAP function exit code or value
 */
#pragma location="IAP_SAFE_CODE" // code segment start >= 0x2000
#pragma optimize=no_inline
static char call_iap (const char R1,    ///< 1st parameter passed via R1
                      const char R2,    ///< 2nd parameter passed via R2
                      const char R3,    ///< 3rd parameter passed via R3
                      const char R4)    ///< 4th parameter passed via R4
{
        asm("PUSH 0xA8/*IEN0*/       ");
        asm("CLR  0xA8.7/*EA*/       ");// disable interrupts
        asm("ANL  0xB1/*FCF*/,#~0x01 ");// enable 89V51's bootcode bank
        asm("ANL  ?DPS,#~0x01        ");// select DPTR 0
        asm("MOV  DPH,R2             ");
        asm("MOV  DPL,R3             ");
        asm("MOV  A,R4               ");
        asm("CALL iap_routine        ");// call 89V51's IAP routine (0x1FF0)
        asm("ORL  0xB1/*FCF*/,#0x01  ");// disable 89V51's bootcode bank
        asm("POP  0xA8/*IEN0*/       ");

        return ACC;
}
 


By inspecting the bootloader's disassembled code, I noticed (see line in bold below) that there is a loop which waits for serial transmit interrupt flag (SCON.1). Because I am in IAP mode, not ISP mode, and I have no transmission pending, the loop never ends.

04BFh   MOV  A,FST
04C1h   JB   ACC.3,0502h
04C4h   JNB  SCON.1,04C4h
04C7h   ORL  FCF,#40h
04CAh   MOV  B4h,#55h
04CDh   MOV  B5h,#AAh
04D0h   MOV  B2h,#08h
        [...]
0502h   CLR  A
0503h   RET
 


I think I have only two choices:

  1. implementing the routine myself

  2. force SCON.1=1 before calling the function (I tried, it works)


I would go for option 1. What would you guys do?


[1] - P89V51RB2/RC2/RD2 - 8-bit 80C51 5V low power 16/32/64 kB Flash microcontroller with 1 kB RAM (rev. 03 - 02 December 2004)
[2] - 89V/LV51Rx2 Bootcode Enanchements (part of ZIP archive available at P89V51Rx2 Bootloader Update)

List of 9 messages in thread
TopicAuthorDate
Function "Program Double Clock" never returns in IAP mode            01/01/70 00:00      
   You should check carefully            01/01/70 00:00      
      I feel safe            01/01/70 00:00      
   bootloader v6 is affected, too            01/01/70 00:00      
      it's the same in v4 and v5, too            01/01/70 00:00      
         TI=1 workaround            01/01/70 00:00      
            3-rd party programming and thebootloader            01/01/70 00:00      
               bootloader self-upgraded to v7            01/01/70 00:00      
   IAP ?            01/01/70 00:00      

Back to Subject List