PICC18 9.51pl2. Очередная ошибка. Неправильно вычисляет разницу чисел со знаком при одновременном выполнении оператора сравнения. Обход ошибки -- присвоения результата вычисления разности временной переменной. Пример:
static int_fast8_t i2c_wait(void)
{
ftime_t t;
t=timer();
do {
if (BCL1IF) {
/* collision */
i2c_fail=I2C_COLLIDE;
return -1;
}
if ((SSP1CON2 & 0x1f)==0 && RW1==0)
/* finished ok */
return 0;
} while (timer() - t < (ftime_t)(10L*FTIME_PER_SEC/1000));
asm("nop");
i2c_fail=I2C_TIMEOUT;
return -1;
}
При попадании в строку где i2c_fail=I2C_TIMEOUT имеем: t=25, последний вызов timer() вернул 26, WREG=24, (unsigned)btemp = 0x1000.
Сгенерированный код:
199 005DA2 _i2c_wait:
272 005DA2 ECE1 F00F call _timer ;wreg free
273 005DA6 C000 F0E3 movff btemp,?a_i2c_wait
274 005DAA C001 F0E4 movff btemp+1,?a_i2c_wait+1
275 005DAE l8:
276 ;i2c_hal.c: 22: do {
277 ;i2c_hal.c: 23: if (BCL1IF) {
278 005DAE A6A1 btfss 4001,3,c ;volatile
279 005DB0 D004 goto l9
280 ;i2c_hal.c: 25: i2c_fail=I2C_COLLIDE;
281 005DB2 0E01 movlw 1
282 005DB4 CFE8 F4BB movff wreg,_i2c_fail
283 ;i2c_hal.c: 26: return -1;
284 005DB8 0CFF retlw 255
285 005DBA l9:
286 ;i2c_hal.c: 27: }
287 005DBA 50C5 movf 4037,w,c ;volatile
288 005DBC 0B1F andlw 31
289 005DBE B4D8 btfsc status,2,c
290 005DC0 B4C7 btfsc 4039,2,c ;volatile
291 005DC2 D001 goto l10
292 ;i2c_hal.c: 31: return 0;
293 005DC4 0C00 retlw 0
294 005DC6 l10:
295 ;i2c_hal.c: 33: } while (timer() - t < (ftime_t)
+ (10L*(((10000000UL*4)/4+128)/256/16)/1000));
296 005DC6 ECE1 F00F call _timer ;wreg free
297 005DCA 0100 movlb __Lparam shr (0+8)
298 005DCC 51E3 movf ?a_i2c_wait^(__Lparam& (0+65280)),w
299 005DCE 5E00 subwf btemp,f,c
300 005DD0 51E4 movf (?a_i2c_wait+1)^(__Lparam& (0+65280)),w
301 005DD2 5A01 subwfb btemp+1,f,c
302 005DD4 5001 movf btemp+1,w,c
303 005DD6 0A80 xorlw 128
304 005DD8 0F80 addlw -128
305 005DDA 0E18 movlw 24
306 005DDC B4D8 btfsc status,2,c
307 005DDE 5C00 subwf btemp,w,c
308 005DE0 E3E6 bnc l8
309 ;i2c_hal.c: 36: asm("NOP");
310 005DE2 F000 nop ;#
311 ;i2c_hal.c: 37: i2c_fail=I2C_TIMEOUT;
312 005DE4 0E02 movlw 2
313 005DE6 CFE8 F4BB movff wreg,_i2c_fail
314 ;i2c_hal.c: 38: return -1;
315 005DEA 0CFF retlw 255
316 ;i2c_hal.c: 39: }
317 005DEC __end_of_i2c_wait:
Разбираться уже ни сил, ни желания. Пусть PIC-профессионалы разбираются.