This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

EXTS instruction sometimes doesn't work in CLASS B trap handler

Hi,
I've got exactly the problem as in this thread:
http://www.keil.com/forum/docs/thread171.asp

That was 6.5 years ago! Have you heard of a fix of some kind for this problem. The workaround is very complex and I'd rather not use it.
In my program, the EXTS instruction sometimes works and some other times is ignored and I can't find out why.

  • I've got exactly the problem as in this thread:

    Not to be disrespectful but are you really sure?

    It would be best to post a snippet of code that shows behavior that you are experiencing. I can show you an example which works fine from a trap routine using the EXTS instruction sequence. It is also important not to get hung up on the disassembler syntax for the instruction.

    So here is my code snippet as an example.

    void main(void) {
      /* cause a class B trap */
      volatile int i = *(unsigned int *)(0x8001);
    
      for(;;);
    }
    
    void Class_B_trap (void) interrupt 0x0A  {
      trapRegister = TFR;
      *((volatile unsigned int huge *)0xf1236ul) = 10;
    
      /* add your code here */
      while (1);                 /* end-less loop */
    }
    

    Note that you will write "10" to absolute address 0xF1236. But when looking at the disassembly you think it is using DPP0. Is not, this is just the way the the instruction is decoded (by the disassembler not by the real device or simulator)!

    00000158 0DFF      JMPR     CC_UC,SOFTBRK_trap(0x158)
        88: void Class_B_trap (void) interrupt 0x0A  {
        89:
    0000015A C6030300  SCXT     DPP3,#0x0003
    0000015E ECF4      PUSH     R4
        90:   trapRegister = TFR;
        91:
    00000160 F6D60082  MOV      DPP2:0x0200,TFR
        92:         *((volatile unsigned int huge *)0xf1236ul) = 10;
        93:
        94:   /* add your code here */
    00000164 E0A4      MOV      R4,#0x0A
    00000166 D7000F00  EXTS     #0x000F,#1
    0000016A F6F43612  MOV      DPP0:0x1236,R4
        95:   while (1);                 /* end-less loop */
    0000016E 0DFF      JMPR     CC_UC,0x00016E
    

    To show another example, I will change the absolute address to 0xFD234. Now have a look you will see that the disassembler decoded DPP3 but again it is not using this as you have the EXTS instruction right before telling it to treat the next instruction as an extended segment sequence. EXTS #0x000F,#1

    00000160 F6D60082  MOV      DPP2:0x0200,TFR
        92:         *((volatile unsigned int huge *)0xfD236ul) = 10;
        93:
        94:   /* add your code here */
    00000164 E0A4      MOV      R4,#0x0A
    00000166 D7000F00  EXTS     #0x000F,#1
    0000016A F6F436D2  MOV      DPP3:0x1236,R4
    

    Hope this helps.

  • Thanks for your answer.
    Yes I am sure the EXTS instruction is not working bacause I am using a monitor to read the values of the registers. The problem is it is working in a project and not in an other project.
    I am aware of what DPPx mean in an EXTS instruction, it is the first thing I's checked in the manual.

    Here is my code:

        61:  if(StructTrap.CrashDetectorActive)
        62:  {
    00016886 D7000C00  EXTS     #0x000C,#1
    0001688A F3F89C82  MOVB     RL4,DPP2:0x029C
    0001688E EA201C6A  JMPA     CC_Z,0x016A1C
        63:   if (ILLBUS == 1)
        64:   {
    00016892 9AD60C00  JNB      0xD6.0,0x0168AE
        65:         EEPROM_value =  0x80;
    00016896 E6FE8000  MOV      R14,#0x0080
        66:     ILLBUS = 0;
    0001689A 0ED6      BCLR     0xD6.0
        67:           StructTrap.NbOftraps[ILLBUS_]++;
    0001689C D7000C00  EXTS     #0x000C,#1
    000168A0 F3F89E82  MOVB     RL4,DPP2:0x029E
    000168A4 0981      ADDB     RL4,#1
    000168A6 D7000C00  EXTS     #0x000C,#1
    000168AA F7F89E82  MOVB     DPP2:0x029E,RL4
        68:   }
    

    I'm running the code in debug mode with a monitor so I can see exactly what is in the RAM and the registers. The first EXTS instruction is not working and the value of RL4 is set to what is at address 0x829C and not what is at address 0xC829C. That mean the if executed even if the variable CrashDetectorActive is set to zero! Then the 2 other EXTS instructions are working fine and the variable at 0xC829E is incremented as expected. If I copy the same code in other project, its working fine. Note: it doesn't change anything if the global variable is part of a structure or stand alone. Nate2: the JUMPA instruction is not part of the EXTended segment and so it not the branch problem.

  • Given that the opcodes are in the actual code but the device does not execute them correctly I would suggest that you contact the micro vendor directly for further investigation. Perhaps you have discovered an errata with the device.

  • After one week working on this problem, I finaly found the cause and one solution.
    The instruction EXTS is designed so that the EXTended sequence is terminated if a class B trap occurs. Here is the warning text in the instruction set manual:
    "CAUTION: When a Class B trap interupts an ATOMIC or EXTended sequence, this sequence is terminated, the interrupt lock is removed and the standard condition is restored, before the trap routine is executed! The remaining instructions of the terminated sequence that are executed after returning from the trap routine will run under standard conditions!"

    For this mater, in the description of this instruction, there is:

    DO WHILE ((count) != 0 AND Class_B_trap_condition != TRUE)
    

    So what happens when this instruction is used in a class B trap function? Aparently, nothing is specified in that case. And according to this code, it is just ignored! And that is what I got, most of the time. I have no idea what Class_B_trap_condition means but acording to the tests I've done, it seems to mean "all the class b request flags in TFR are 0." Therefore, once the bits have been cleared, the instruction EXTS is working fine. My solution was then to make a copy of the TFR register, to clear it, and then to work on the copy.

  • I've just checked on the latest version of the instruction set manual and this has been clarified by the following text:
    "Within a ClassA or ClassB trap service routine EXTend instructions do not work (i.e. override the DPP mechanism) as long as any of the ClassB trap flags is set."
    However, I've seen one example where it did work and that confused me. That just means "do not work" should be understand "should not be used".

    So my conclusion is: allways check that you have the latest version of the manual!