• AVR Freaks

Hot!Problem with Microchip 16-bit Self-Test Library and PIC24EP

Author
aekalman
Senior Member
  • Total Posts : 129
  • Reward points : 0
  • Joined: 2003/11/07 12:38:10
  • Status: offline
2017/04/23 16:30:57 (permalink)
5 (1)

Problem with Microchip 16-bit Self-Test Library and PIC24EP

Looking for some insight -- this one has me really stumped.
 
Tools / Conditions: XC16 v1.25, MPLAB X IDE v3.15, Microchip 16-bit CPU Self-test Library (the last release was in 2015), PIC24EP256MC206, Production environment. Note that the self-test library cores are in Assembly language, so the compiler version probably has very little impact on this. And yes, I extended v1.25 of the compiler's support files and the peripheral library source files to work properly with the PIC24EP256MC206 ... So far, so good.
 
I ported the Self-test libraries to the PIC24EP family (only minor mods required), and was able to get them running in the following build environment: PIC24EP256MC206, 70% program space used, 66% data memory used, large code and data models, 0x4482 bytes dynamic memory used, multiple interrupts (UART and I2C), all declared as void __attribute__ ((interrupt,no_auto_psv)) and generally very "clean", like this:
void __attribute__ ((interrupt,no_auto_psv)) _U1RXInterrupt(void) {
(two short function calls -- forum software won't let me post their contents (!), I get an ACCESS DENIED if they are included)
}

As long as I stuck to my four UART and one I2C interrupts, all was well. But when I add an ADC code and ADC interrupt like this:
void task_gpsrm_adc(void) {
uart1_msg_hhmmsstt(STR_TASK_GPSRM_ADC STR_STARTING);
ANSELCbits.ANSC0 = 1; // Setup to read RC0, RC1, RC2, RC11
ANSELCbits.ANSC1 = 1; // ""
ANSELCbits.ANSC2 = 1; // ""
ANSELCbits.ANSC11 = 1; // ""
AD1CON1 = 0x00E0; // Internal counter triggers conversion
//AD1CHS = 0x0000; // Not used ('cause we're channel scanning)
AD1CSSL = 0x09C0; // Scan channels AN6, AN7, AN8, AN11
AD1CON3 = 0x0F00; // Sample time = 15Tad, Tad = Tcy
AD1CON2 = 0x000C; // Set AD1IF after every fourth sample
// 'cause we're scanning four channels
AD1CON2bits.CSCNA = 1; // Scan inputs AN[0..X] via MUX A
AD1CON1bits.ADON = 1; // Turn ADC ON
IFS0bits.AD1IF = 0; // Clear ADC interrupt flag
AD1CON1bits.ASAM = 1; // Auto start sampling for 31Tad
IEC0bits.AD1IE = 1; // Enable interrupts
// Compute averaged analog inputs at 100Hz
while(1){
v_u16_ANALOG6 = AverageADCSamples(AN6results);
v_u16_ANALOG7 = AverageADCSamples(AN7results);
v_u16_ANALOG8 = AverageADCSamples(AN8results);
v_u16_ANALOG11 = AverageADCSamples(AN11results);
OS_Delay(10);
} /* while() */
} /* task_adc() */
 
 
 
 
 
 
 

void __attribute__ ((interrupt,no_auto_psv)) _AD1Interrupt(void) {
static uint16_t index = 0;
// Clear interrupt flag
IFS0bits.AD1IF = 0;
// These lines must happen faster than one sample-and-conversion time to
// avoid read problems.
AN6results[index] = ADC1BUF0;
AN7results[index] = ADC1BUF1;
AN8results[index] = ADC1BUF2;
AN11results[index] = ADC1BUF3;
// Increment results index, modulo
index = (index+1)%NUM_SAMPLES;
} /* _AD1Interrupt() */

then test #6 fails regularly, like this:
0)00:00:03:10.97 task_supmcu_self_test: Self-test #4: Pass=26 Fail=2
0)00:00:03:11.44 supmcu_self_test: Self-test #5: 311 clock cycles.
Self-test #5: 0x1BD2 (pass).
0)00:00:03:11.45 task_supmcu_self_test: Self-test #5: Pass=27 Fail=2
0)00:00:03:11.92 supmcu_self_test: Self-test #6: 325 clock cycles.
Self-test #6: 0xAE3F (fail).
0)00:00:03:11.93 task_supmcu_self_test: Self-test #6: Pass=27 Fail=3
0)00:00:03:12.40 supmcu_self_test: Self-test #1: 291 clock cycles.
Self-test #1: 0x694D (pass).
0)00:00:03:12.41 task_supmcu_self_test: Self-test #1: Pass=28 Fail=3
0)00:00:03:12.88 supmcu_self_test: Self-test #2: 315 clock cycles.
Self-test #2: 0x7B77 (pass).
0)00:00:03:12.89 task_supmcu_self_test: Self-test #2: Pass=29 Fail=3
s0)00:00:03:13.36 supmcu_self_test: Self-test #3: 416 clock cycles.
Self-test #3: 0xC2AB (pass).
0)00:00:03:13.37 task_supmcu_self_test: Self-test #3: Pass=30 Fail=3
up0)00:00:03:13.84 supmcu_self_test: Self-test #4: 294 clock cycles.
Self-test #4: 0x00F8 (pass).
0)00:00:03:13.85 task_supmcu_self_test: Self-test #4: Pass=31 Fail=3
:0)00:00:03:14.32 supmcu_self_test: Self-test #5: 311 clock cycles.
Self-test #5: 0x1BD2 (pass).
0)00:00:03:14.33 task_supmcu_self_test: Self-test #5: Pass=32 Fail=3
se0)00:00:03:14.80 supmcu_self_test: Self-test #6: 325 clock cycles.
Self-test #6: 0xAEFF (fail).
0)00:00:03:14.81 task_supmcu_self_test: Self-test #6: Pass=32 Fail=4

From the above you can see that test # 6 is regularly failing, but the other five tests are OK.
I thought that perhaps the compiler was generating PSVPAG-related code in _AD1Interrupt(), but that was not the case. Even when I reduced _AD1Interrupt() to the bare minimum of:
void __attribute__ ((interrupt,no_auto_psv)) _AD1Interrupt(void) {
// Clear interrupt flag
IFS0bits.AD1IF = 0;
}

the problem perists -- test #6 fails.
 
If I change the interrupt declaration to
void __attribute__ ((interrupt,auto_psv)) _AD1Interrupt(void) {
// Clear interrupt flag
IFS0bits.AD1IF = 0;
}

the problem is even worse -- now tests 6 & 5 fail regularly.
 
The ADC interrupt itself is quite simple:
53800 1A44E BE9F80 MOV.D W0, [W15++]
53801 1A450 781F82 MOV W2, [W15++]
53802 1A452 FA0000 LNK #0x0
53803 1A454 A9A801 BCLR 0x801, #5
53804 1A456 81D3C0 MOV 0x3A78, W0
53805 1A458 801801 MOV ADC1BUF0, W1
53806 1A45A 400100 ADD W0, W0, W2
53807 1A45C 23A300 MOV #0x3A30, W0
53808 1A45E 410000 ADD W2, W0, W0
53809 1A460 780801 MOV W1, [W0]
53810 1A462 81D3C0 MOV 0x3A78, W0
53811 1A464 801811 MOV ADC1BUF1, W1
53812 1A466 400100 ADD W0, W0, W2
53813 1A468 23A400 MOV #0x3A40, W0
53814 1A46A 410000 ADD W2, W0, W0
53815 1A46C 780801 MOV W1, [W0]
53816 1A46E 81D3C0 MOV 0x3A78, W0
53817 1A470 801821 MOV ADC1BUF2, W1
53818 1A472 400100 ADD W0, W0, W2
53819 1A474 23A500 MOV #0x3A50, W0
53820 1A476 410000 ADD W2, W0, W0
53821 1A478 780801 MOV W1, [W0]
53822 1A47A 81D3C0 MOV 0x3A78, W0
53823 1A47C 801831 MOV ADC1BUF3, W1
53824 1A47E 400100 ADD W0, W0, W2
53825 1A480 23A600 MOV #0x3A60, W0
53826 1A482 410000 ADD W2, W0, W0
53827 1A484 780801 MOV W1, [W0]
53828 1A486 81D3C0 MOV 0x3A78, W0
53829 1A488 E80000 INC W0, W0
53830 1A48A 600067 AND W0, #0x7, W0
53831 1A48C 89D3C0 MOV W0, 0x3A78
53832 1A48E FA8000 ULNK
53833 1A490 78014F MOV [--W15], W2
53834 1A492 BE004F MOV.D [--W15], W0
53835 1A494 064000 RETFIE

This doesn't look to me like anything out of the ordinary, anything that would cause PSVPAG- or other related issues.
 
Here is the source (from Microchip) for test #6; note that PIC24EP does not have an alternate interrupt vector table.
_TestSubset_6: ; Start of TestSubset_6
;..............................................................................
;1. Saving of SFR's INTCON1, INTCON2, RCOUNT, CORCON on to the stack.
;..............................................................................
push INTCON1
.ifdef __dsPIC33F
push INTCON2
.endif
.ifdef __PIC24H
push INTCON2
.endif
push RCOUNT
push CORCON
;..............................................................................
;1. Alternate vector table(ALTIVT) bit is set in INTCON2 (dsPIC33F/PIC24H only)
;2. Move 0xF042 to w0 and store the value 0xF042 into the data memory
; at the location 0x1AAA.
;3. mov the address 0xAAA to w3 and 0x8001 to w4.
;4. Multiply the contents w4 with the contents of [w3] and store the result
; to w6:w7. Both source operands and the result are interpreted as two's
; complement signed numbers. Register indirect addressing is used for second
; operand.
;5. Unsigned integer divide is performed. The result of previous mul.ss
; instruction is used as i/p values for this division. The 16-bit quotient
; of the divide operation is stored in W0, and the 16-bit remainder is
; stored in W1 by default. The result of this division will be used as i/p of
; other multiplication or division. This cycle continues so that the
; end result will validate all the features tested.
;6. Multiply the contents of w0 with the contents of w1, and store the 32-bit
; result w6:w7.
;..............................................................................
.ifdef __dsPIC33F
bset INTCON2, #15 ; Use alternate vector table
.endif
.ifdef __PIC24H
bset INTCON2, #15 ; Use alternate vector table
.endif
bset INTCON1, #NSTDIS ; prevent interrupt nesting (AEK)
mov #CpuTest6Data1, w0; 0xF042 is moved to w0
mov w0, CpuTestRam1 ; 0xF042 is stored at 0x0AAA
mov #CpuTestRam1, w3 ; 0x0AAA is moved to w3
mov #CpuTest6Data2, w4; 0x8001 is moved to w4
mul.ss w4, [w3], w6 ; Integer 16x16-bit Signed Multiply
repeat #17 ; Unsigned 16/16-bit integer divide
div.u w6, w7
mul.su w0, w1, w6 ; Integer 16x16-bit Signed-Unsigned Multiply
;..............................................................................
;1. Generate the divide by zero math error trap using div.s instruction
; with the operands as w6 and w7.
;2. Before going to math trap ISR the PC is captured to check for the context
; save on to the stack.
;3. In order to get result independent of PCL and PCH, PCH and PCL are
; subtracted first and later added to w5 during the testing of context save
; on to the stack.
;4. Tested interrupt call and return operations.
;5. In the math error trap ISR the RCOUNT is cleared so that effectively next
; instruction after the div.s instruction will be executed.
;6. The w1:w0 are of no use after the divide by zero error.
;..............................................................................
mov PCH, w5
sub w4, w5, w5
mov PCL, w2
sub w5, w2, w5
; refer special issue
repeat #17 ; divide by zero arithmetic error trap
div.s w6, w7 ; generation
;..............................................................................
;1. Multiply the contents of w4 with unsigned short literal 0x07 and store the
; result to w2:w3.
;2. Signed 16/16-bit integer divide is performed once again to check whether
; division operation can recovered after the math error trap or not.
;3. Multiply the contents of w0 with w1 and store the result to w6:w7.
;4. Signed 32/16-bit integer divide is performed. The 16-bit quotient of the
; divide operation is stored in W0, and the 16-bit remainder is stored
; in W1 by default.
;5. Multiply the contents of w0 with the contents of w1 and store the result
; to w6:w7.
;6. Multiply the contents of w6 with the 5-bit literal 0x1F and store the
; result to w2:w3.
;7. w2, w3 validates above operations. w5 validates operations in math trap ISR
;8. w2, w3, w5 and w7 are added and stored to produce the final result in w0.
;..............................................................................
; Integer 16x16-bit Signed-
; Unsigned Short Literal Multiply
mul.su w4, #CpuTest6Data3, w2
repeat #17 ; Signed 16/16-bit integer divide
div.s w2, w3
mul.us w0, w1, w6 ; Integer 16x16-bit Unsigned-Signed Multiply
; mov #17(0x11) to w4
mov #CpuTest6Data6, w4
repeat w4 ; Signed 32/16-bit integer divide
div.sd w6, w3
mul.uu w0, w1, w6 ; Integer 16x16-bit Unsigned Multiply
; Integer 16x16-bit Unsigned-
; Short Literal Multiply
mul.uu w6, #CpuTest6Data4, w2
add w2, w3, w2
add w5, w7, w5
add w2, w5, w0
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
bclr INTCON1, #NSTDIS ; restore interrupt nesting (AEK)
; Retrieving of SFR's INTCON1, INTCON2, RCOUNT, CORCON from the stack.
;..............................................................................
pop CORCON
pop RCOUNT
.ifdef __dsPIC33F
pop INTCON2
.endif
.ifdef __PIC24H
pop INTCON2
.endif
pop INTCON1
return ; End of TestSubset_6
;..............................................................................
; ISR for Math Error trap: for TestSubsets 6 & 7
;..............................................................................
.ifdef __dsPIC33F
__AltMathError:
.endif
.ifdef __PIC24H
__AltMathError:
.endif
.ifdef __dsPIC33E
__MathError:
.endif
.ifdef __PIC24E
__MathError:
.endif
btsc INTCON1, #DIV0ERR ; Check the trap is caused by divide by zero
; If DIV0ERR=1 then branch to
; TestSubset_6MathISR to execute TestSubset_6
; specific code else execute TestSubset_7
; specific code
bra TestSubset_6MathISR
TestSubset_7MathISR: ; The following code is for TestSubset_7:
add #1,w0
bclr INTCON1, #MATHERR
retfie
; The following code is for TestSubset_6:
;..............................................................................
;1. Tested SR flags IPL<2:0>, RA and CORCON flag IPL3.
;2. The known SR<7:4> bits are moved to w0.
;3. Multiply the default working register WREG with the register RCOUNT and
; store the result to w2. An 8-bit multiply operation is performed here.
;4. This multiplication will validate the RCOUNT register value.
;5. In order to test the context save on to the stack during interrupt,
; the address pointer is moved to w3.
;6. With the help of w3, read the PCL, PCH, SR<7:0> and IPL3 bits, save
; them on the stack and add to w5.
;7. As this is a math error trap, the IPL3 bit will be set. This bit is tested
; with the BTSC instruction. If it is cleared then it will effect w5 which,
; in turn, effects the final result.
;8. The Math Error Trap status flag in the INTCON1 is cleared.
;9. The RCOUNT register is cleared to stop the division instruction which
; caused divide-by-zero error.
;..............................................................................
TestSubset_6MathISR:
mov #CpuTest6Data5, w0
and SR, WREG ; IPL<2:0> and RA bits are catured to w0
; Integer Unsigned Multiply f and WREG
mul.b RCOUNT ; validating RCOUNT and mul.b by f
mov w15, w3 ; mov stack address pointer to w3
; SR<7:0>, IPL3 and PCH are read from stack
add w5, [--w3], w5 ; and added to w5
add w5, [--w3], w5 ; PCL is read from stack and added to w5
btsc CORCON, #IPL3
add w5, w2, w5 ; executed as IPL3=1
bclr INTCON1, #MATHERR ; clear the matherror flag
clr RCOUNT ; clear the RCOUNT register
retfie

Any ideas or suggestions on where to look? For this particular build a result of 0xAE40 is the correct result for test #6, but it only occurs maybe 30-40% of the time ...
post edited by aekalman - 2017/04/23 16:49:03

Andrew E. Kalman, Ph.D.
President
Pumpkin, Inc.
#1

5 Replies Related Threads

    I.AbuHamam
    New Member
    • Total Posts : 3
    • Reward points : 0
    • Joined: 2018/08/29 06:01:15
    • Location: 0
    • Status: offline
    Re: Problem with Microchip 16-bit Self-Test Library and PIC24EP 2020/06/29 07:09:15 (permalink)
    0
    Hi,
    I am having a similar issue with the exact same subset (#6), i was searching and stumbled upon your post.
    did you happen to find a solution to this issue? or at least the reason this is happening?
    thanks in advance for your help
    #2
    aekalman
    Senior Member
    • Total Posts : 129
    • Reward points : 0
    • Joined: 2003/11/07 12:38:10
    • Status: offline
    Re: Problem with Microchip 16-bit Self-Test Library and PIC24EP 2020/06/29 09:53:23 (permalink)
    0
    Unfortunately we have not. We have fielded the self tests on around 12 different products, that have a relatively strong mix of peripherals in use (all use the same Salvo RTOS core as the application foundation).
     
    To date, we cannot predict (nor explain) why self-tests fail on some of these products/builds, and not on others. Generally speaking, either the self-tests all work without error forever, or the higher-number tests (typically #5 and #6) will fail with regularity, either pretty often (say once per 100 tests) or more rarely (say, once per 1000 tests). We run the tests at 2Hz as a moderate-priority task. Typical products have a limited number of interrupt sources (5-9).
    #3
    aekalman
    Senior Member
    • Total Posts : 129
    • Reward points : 0
    • Joined: 2003/11/07 12:38:10
    • Status: offline
    Re: Problem with Microchip 16-bit Self-Test Library and PIC24EP 2020/06/30 00:41:59 (permalink)
    0
    Here's an example of four of our modules, all running the exact same self-test code. Three of them do this:
    0)00:00:09:21.56 task_supmcu_selftest: 1094 passed(#2, 0x7B77 in 173 cycles), 0 failed(#0, 0x0000).
    0)00:00:09:22.05 task_supmcu_selftest: 1095 passed(#3, 0xC2AB in 215 cycles), 0 failed(#0, 0x0000).
    0)00:00:09:22.54 task_supmcu_selftest: 1096 passed(#4, 0x00F8 in 147 cycles), 0 failed(#0, 0x0000).
    But one of them does this:
    0)00:00:10:48.09 task_supmcu_selftest:       143 failed(#2, 0x7B76 in 268 cycles), expected 0x7B77).
    0)00:00:10:48.59 task_supmcu_selftest:      1006 passed(#3, 0xC2AB in 313 cycles), 143 failed(#2, 0x7B76).
    0)00:00:10:49.07 task_supmcu_selftest:      1007 passed(#4, 0x00F8 in 247 cycles), 143 failed(#2, 0x7B76).
    0)00:00:10:49.55 task_supmcu_selftest:      1008 passed(#5, 0x1BD2 in 267 cycles), 143 failed(#2, 0x7B76).
    0)00:00:10:50.02 task_supmcu_selftest:       144 failed(#6, 0xAEFF in 284 cycles), expected 0xAE3F).
    0)00:00:10:50.52 task_supmcu_selftest:      1009 passed(#1, 0x694D in 244 cycles), 144 failed(#6, 0xAEFF).
    0)00:00:10:51.00 task_supmcu_selftest:      1010 passed(#2, 0x7B77 in 269 cycles), 144 failed(#6, 0xAEFF).
    0)00:00:10:51.48 task_supmcu_selftest:      1011 passed(#3, 0xC2AB in 313 cycles), 144 failed(#6, 0xAEFF).
    0)00:00:10:51.96 task_supmcu_selftest:      1012 passed(#4, 0x00F8 in 247 cycles), 144 failed(#6, 0xAEFF).
    0)00:00:10:52.44 task_supmcu_selftest:      1013 passed(#5, 0x1BD2 in 267 cycles), 144 failed(#6, 0xAEFF).
    0)00:00:10:52.92 task_supmcu_selftest:      1014 passed(#6, 0xAE3F in 287 cycles), 144 failed(#6, 0xAEFF).
    0)00:00:10:53.40 task_supmcu_selftest:      1015 passed(#1, 0x694D in 247 cycles), 144 failed(#6, 0xAEFF).

     
    #4
    RISC
    Super Member
    • Total Posts : 5776
    • Reward points : 0
    • Status: offline
    Re: Problem with Microchip 16-bit Self-Test Library and PIC24EP 2020/07/11 02:17:43 (permalink)
    0
    Hi,
    You may want to check the classB / functional libraries : 
    https://www.microchip.com/design-centers/16-bit/functional-safety
    Regards
     

    For support make sure to check first here : http://microchipdeveloper.com
    There are hundreds of PIC, AVR, SAM...which one do YOU use ?
    #5
    I.AbuHamam
    New Member
    • Total Posts : 3
    • Reward points : 0
    • Joined: 2018/08/29 06:01:15
    • Location: 0
    • Status: offline
    Re: Problem with Microchip 16-bit Self-Test Library and PIC24EP 2020/07/27 23:50:30 (permalink)
    0
    I colleague of mine may have found something, when we used the XC16 V1.3 compiler the tests work well (as long as the PWM interrupt is not enabled) but using any newer version of the XC16 results in failure of subset #6.
    they've check the errata and it seems that some lines of the assembly code were skipped. adding NOP at certain lines solved the issue for newer compilers, but it still happens when the system is fully functioning (especially if the PWM interrupt was enabled). 
    #6
    Jump to:
    © 2020 APG vNext Commercial Version 4.5