@@ -48,6 +48,7 @@ struct i2c_struct_t {
48
48
uint16_t queueCount ;
49
49
uint16_t queuePos ;
50
50
uint16_t byteCnt ;
51
+ uint32_t exitCode ;
51
52
52
53
};
53
54
@@ -95,7 +96,7 @@ static i2c_err_t i2cAddQueue(i2c_t * i2c,uint8_t mode, uint16_t i2cDeviceAddr, u
95
96
dqx .queueEvent = event ;
96
97
97
98
if (event ){// an eventGroup exist, so, initialize it
98
- xEventGroupClearBits (event , 0x3F ); // all of them
99
+ xEventGroupClearBits (event , EVENT_MASK ); // all of them
99
100
}
100
101
101
102
if (i2c -> dq != NULL ){ // expand
@@ -1209,20 +1210,25 @@ static void IRAM_ATTR emptyRxFifo(i2c_t * i2c){
1209
1210
I2C_DATA_QUEUE_t * tdq = & i2c -> dq [i2c -> queuePos ];
1210
1211
1211
1212
moveCnt = i2c -> dev -> status_reg .rx_fifo_cnt ;//no need to check the reg until this many are read
1213
+ if (moveCnt > (tdq -> length - tdq -> position )){ //makesure they go in this dq
1214
+ // part of these reads go into the next dq
1215
+ moveCnt = (tdq -> length - tdq -> position );
1216
+ }
1212
1217
1213
1218
if (tdq -> ctrl .mode == 1 ) { // read
1214
1219
while (moveCnt > 0 ){
1215
1220
while (moveCnt > 0 ){
1216
1221
d = i2c -> dev -> fifo_data .val ;
1217
1222
moveCnt -- ;
1218
1223
cnt ++ ;
1219
- if (tdq -> position < tdq -> length ) tdq -> data [tdq -> position ++ ] = (d & 0xFF );
1220
- else { // discard? what Happened to get more than requested?
1221
- log_e ("discard 0x%x" ,d );
1222
- }
1224
+ tdq -> data [tdq -> position ++ ] = (d & 0xFF );
1223
1225
}
1224
1226
// see if any more chars showed up while empting Fifo.
1225
1227
moveCnt = i2c -> dev -> status_reg .rx_fifo_cnt ;
1228
+ if (moveCnt > (tdq -> length - tdq -> position )){ //makesure they go in this dq
1229
+ // part of these reads go into the next dq
1230
+ moveCnt = (tdq -> length - tdq -> position );
1231
+ }
1226
1232
}
1227
1233
cnt += (intBuff [intPos ][1 ])&& 0xffFF ;
1228
1234
intBuff [intPos ][1 ] = (intBuff [intPos ][1 ]& 0xFFFF0000 )|cnt ;
@@ -1235,6 +1241,7 @@ else {
1235
1241
}
1236
1242
1237
1243
static void i2cIsrExit (i2c_t * i2c ,const uint32_t eventCode ,bool Fatal ){
1244
+
1238
1245
switch (eventCode ){
1239
1246
case EVENT_DONE :
1240
1247
i2c -> error = I2C_OK ;
@@ -1256,24 +1263,25 @@ switch(eventCode){
1256
1263
}
1257
1264
uint32_t exitCode = EVENT_DONE | eventCode |(Fatal ?EVENT_ERROR :0 );
1258
1265
1266
+ if (i2c -> dq [i2c -> queuePos ].ctrl .mode == 1 ) emptyRxFifo (i2c ); // grab last few characters
1267
+
1259
1268
i2c -> dev -> int_ena .val = 0 ; // shutdown interrupts
1260
1269
i2c -> dev -> int_clr .val = 0x1FFFF ;
1261
1270
i2c -> stage = I2C_DONE ;
1271
+ i2c -> exitCode = exitCode ; //true eventcode
1262
1272
1263
- portBASE_TYPE HPTaskAwoken = pdFALSE ;
1264
-
1265
- if (i2c -> dq [i2c -> queuePos ].queueEvent ){ // this data element has an event, use it.
1266
- HPTaskAwoken = pdFALSE ;
1267
- xEventGroupClearBitsFromISR (i2c -> dq [i2c -> queuePos ].queueEvent , EVENT_RUNNING );
1268
- xEventGroupSetBitsFromISR (i2c -> dq [i2c -> queuePos ].queueEvent , exitCode ,& HPTaskAwoken );
1269
- if (HPTaskAwoken == pdTRUE ) portYIELD_FROM_ISR ();
1270
- }
1271
- xEventGroupClearBitsFromISR (i2c -> i2c_event , EVENT_RUNNING );
1273
+ portBASE_TYPE HPTaskAwoken = pdFALSE ,xResult ;
1274
+ // try to notify Dispatch we are done,
1275
+ // else the 50ms timeout will recover the APP, just alittle slower
1272
1276
HPTaskAwoken = pdFALSE ;
1273
- xEventGroupSetBitsFromISR (i2c -> i2c_event , exitCode , & HPTaskAwoken );
1274
- if (HPTaskAwoken == pdTRUE ) {//higher pri task has awoken, jump to it
1275
- portYIELD_FROM_ISR ();
1277
+ xResult = xEventGroupSetBitsFromISR (i2c -> i2c_event , exitCode , & HPTaskAwoken );
1278
+ if (xResult == pdPASS ){
1279
+ if (HPTaskAwoken == pdTRUE ) {
1280
+ portYIELD_FROM_ISR ();
1281
+ // log_e("Yield to Higher");
1282
+ }
1276
1283
}
1284
+
1277
1285
}
1278
1286
1279
1287
static void IRAM_ATTR i2c_isr_handler_default (void * arg ){
@@ -1283,25 +1291,14 @@ uint32_t activeInt = p_i2c->dev->int_status.val&0x1FFF;
1283
1291
//log_e("int=%x",activeInt);
1284
1292
//dumpI2c(p_i2c);
1285
1293
1286
- portBASE_TYPE HPTaskAwoken = pdFALSE ;
1287
- /* don't need this Event_in_irq
1288
- // be polite if someone more important wakes up.
1289
- //log_e("setbits(%p)=%p",p_i2c->i2c_event);
1290
-
1291
- xEventGroupSetBitsFromISR(p_i2c->i2c_event, EVENT_IN_IRQ, &HPTaskAwoken);
1292
- if (HPTaskAwoken == pdTRUE) {//higher pri task has awoken, jump to it
1293
- portYIELD_FROM_ISR();
1294
- }
1295
- //log_e("stage");
1296
- */
1294
+ portBASE_TYPE HPTaskAwoken = pdFALSE ,xResult ;
1297
1295
1298
1296
if (p_i2c -> stage == I2C_DONE ){ //get Out
1299
1297
log_e ("eject int=%p, ena=%p" ,activeInt ,p_i2c -> dev -> int_ena .val );
1300
1298
p_i2c -> dev -> int_ena .val = 0 ;
1301
1299
p_i2c -> dev -> int_clr .val = activeInt ; //0x1FFF;
1302
1300
dumpI2c (p_i2c );
1303
1301
i2cDumpInts ();
1304
- // xEventGroupClearBitsFromISR(p_i2c->i2c_event, EVENT_IN_IRQ);
1305
1302
return ;
1306
1303
}
1307
1304
while (activeInt != 0 ) { // Ordering of 'if(activeInt)' statements is important, don't change
@@ -1321,19 +1318,8 @@ while (activeInt != 0) { // Ordering of 'if(activeInt)' statements is important,
1321
1318
// p_i2c->byteCnt=0;
1322
1319
if (p_i2c -> stage == I2C_STARTUP ){
1323
1320
p_i2c -> stage = I2C_RUNNING ;
1324
- xEventGroupClearBitsFromISR (p_i2c -> i2c_event , EVENT_DONE ); //why?
1325
- if (p_i2c -> dq [p_i2c -> queuePos ].queueEvent ){ // this data element has an event, use it.
1326
- HPTaskAwoken = pdFALSE ;
1327
- xEventGroupSetBitsFromISR (p_i2c -> dq [p_i2c -> queuePos ].queueEvent , EVENT_RUNNING ,
1328
- & HPTaskAwoken );
1329
- if (HPTaskAwoken == pdTRUE ) portYIELD_FROM_ISR ();
1330
- }
1331
- HPTaskAwoken = pdFALSE ;
1332
- xEventGroupSetBitsFromISR (p_i2c -> i2c_event , EVENT_RUNNING , & HPTaskAwoken );
1333
- if (HPTaskAwoken == pdTRUE ) {//higher pri task has awoken, jump to it
1334
- portYIELD_FROM_ISR ();
1335
- }
1336
1321
}
1322
+
1337
1323
activeInt &=~I2C_TRANS_START_INT_ST_M ;
1338
1324
p_i2c -> dev -> int_ena .trans_start = 1 ; // already enabled? why Again?
1339
1325
p_i2c -> dev -> int_clr .trans_start = 1 ; // so that will trigger after next 'END'
@@ -1367,23 +1353,8 @@ while (activeInt != 0) { // Ordering of 'if(activeInt)' statements is important,
1367
1353
p_i2c -> dev -> int_ena .rx_fifo_full = 1 ;
1368
1354
}
1369
1355
1370
- if (p_i2c -> dq [p_i2c -> queuePos ].queueEvent ){ // this data element has an event, use it.
1371
- HPTaskAwoken = pdFALSE ;
1372
- xEventGroupClearBitsFromISR (p_i2c -> dq [p_i2c -> queuePos ].queueEvent , EVENT_RUNNING );
1373
- xEventGroupSetBitsFromISR (p_i2c -> dq [p_i2c -> queuePos ].queueEvent , EVENT_DONE ,
1374
- & HPTaskAwoken );
1375
- if (HPTaskAwoken == pdTRUE ) portYIELD_FROM_ISR ();
1376
- }
1377
-
1378
1356
p_i2c -> queuePos ++ ; //inc to next dq
1379
1357
1380
- if (p_i2c -> dq [p_i2c -> queuePos ].queueEvent ){ // this data element has an event, use it.
1381
- HPTaskAwoken = pdFALSE ;
1382
- xEventGroupSetBitsFromISR (p_i2c -> dq [p_i2c -> queuePos ].queueEvent , EVENT_RUNNING ,
1383
- & HPTaskAwoken );
1384
- if (HPTaskAwoken == pdTRUE ) portYIELD_FROM_ISR ();
1385
- }
1386
-
1387
1358
if (p_i2c -> queuePos < p_i2c -> queueCount ) // load next dq address field + data
1388
1359
p_i2c -> dev -> int_ena .tx_fifo_empty = 1 ;
1389
1360
@@ -1408,7 +1379,6 @@ while (activeInt != 0) { // Ordering of 'if(activeInt)' statements is important,
1408
1379
}
1409
1380
1410
1381
if (activeInt & I2C_TRANS_COMPLETE_INT_ST_M ) {
1411
- if (p_i2c -> dq [p_i2c -> queuePos ].ctrl .mode == 1 ) emptyRxFifo (p_i2c ); // grab last few characters
1412
1382
i2cIsrExit (p_i2c ,EVENT_DONE ,false);
1413
1383
return ; // no more work to do
1414
1384
/*
@@ -1430,39 +1400,29 @@ while (activeInt != 0) { // Ordering of 'if(activeInt)' statements is important,
1430
1400
}
1431
1401
1432
1402
if (activeInt & I2C_END_DETECT_INT_ST_M ) {
1433
- HPTaskAwoken = pdFALSE ;
1434
- xEventGroupSetBitsFromISR (p_i2c -> i2c_event , EVENT_IN_END , & HPTaskAwoken );
1435
- if (HPTaskAwoken == pdTRUE ) {//higher pri task has awoken, jump to it
1436
- portYIELD_FROM_ISR ();
1437
- }
1438
1403
p_i2c -> dev -> int_ena .end_detect = 0 ;
1439
1404
p_i2c -> dev -> int_clr .end_detect = 1 ;
1440
1405
p_i2c -> dev -> ctr .trans_start = 0 ;
1441
1406
fillCmdQueue (p_i2c ,0 ,true);
1442
1407
p_i2c -> dev -> ctr .trans_start = 1 ; // go for it
1443
1408
activeInt &=~I2C_END_DETECT_INT_ST_M ;
1444
1409
// What about Tx, RX fifo fill?
1445
- xEventGroupClearBitsFromISR (p_i2c -> i2c_event , EVENT_IN_END );
1446
1410
}
1447
1411
1448
1412
if (activeInt & I2C_RXFIFO_OVF_INT_ST_M ) { //should never happen, I always use Fifo
1449
1413
p_i2c -> dev -> int_clr .rx_fifo_ovf = 1 ;
1414
+ p_i2c -> dev -> int_ena .rx_fifo_ovf = 0 ; // disable it
1450
1415
}
1451
1416
1452
1417
if (activeInt ){ // clear unhandled if possible? What about Disabling interrupt?
1453
1418
p_i2c -> dev -> int_clr .val = activeInt ;
1454
1419
log_e ("unknown int=%x" ,activeInt );
1420
+ // disable unhandled IRQ,
1421
+ p_i2c -> dev -> int_ena .val = p_i2c -> dev -> int_ena .val & (~activeInt );
1455
1422
}
1456
1423
1457
1424
activeInt = p_i2c -> dev -> int_status .val ; // start all over if another interrupt happened
1458
- /* if((activeInt&oldInt)==oldInt){
1459
- log_e("dup int old=%p, new=%p dup=%p",oldInt,activeInt,(oldInt&activeInt));
1460
- }
1461
- */
1462
1425
}
1463
-
1464
- //xEventGroupClearBitsFromISR(p_i2c->i2c_event, EVENT_IN_IRQ);
1465
- // and we're out!
1466
1426
}
1467
1427
1468
1428
void i2cDumpInts (){
@@ -1506,10 +1466,12 @@ if(!i2c->i2c_event){
1506
1466
}
1507
1467
if (i2c -> i2c_event ) {
1508
1468
uint32_t ret = xEventGroupClearBits (i2c -> i2c_event , 0xFF );
1469
+
1509
1470
// log_e("after clearBits(%p)=%p",i2c->i2c_event,ret);
1510
1471
}
1511
1472
else {// failed to create EventGroup
1512
1473
log_e ("eventCreate failed=%p" ,i2c -> i2c_event );
1474
+ I2C_MUTEX_UNLOCK ();
1513
1475
return I2C_ERROR_MEMORY ;
1514
1476
}
1515
1477
@@ -1561,6 +1523,7 @@ i2c->queuePos=0;
1561
1523
fillCmdQueue (i2c ,0 ,false); // start adding command[], END irq will keep it full
1562
1524
//Data Fifo will be filled after trans_start is issued
1563
1525
1526
+ i2c -> exitCode = 0 ;
1564
1527
i2c -> stage = I2C_STARTUP ; // everything configured, now start the I2C StateMachine, and
1565
1528
// As soon as interrupts are enabled, the ISR will start handling them.
1566
1529
// it should receive a TXFIFO_EMPTY immediately, even before it
@@ -1584,6 +1547,7 @@ if(!i2c->intr_handle){ // create ISR I2C_0 only,
1584
1547
uint32_t ret = esp_intr_alloc (ETS_I2C_EXT0_INTR_SOURCE , 0 , & i2c_isr_handler_default , i2c , & i2c -> intr_handle );
1585
1548
if (ret != ESP_OK ){
1586
1549
log_e ("install interrupt handler Failed=%d" ,ret );
1550
+ I2C_MUTEX_UNLOCK ();
1587
1551
return I2C_ERROR_MEMORY ;
1588
1552
}
1589
1553
}
@@ -1593,6 +1557,8 @@ if(!i2c->intr_handle){ // create ISR I2C_0 only,
1593
1557
// how many ticks should it take to transfer totalBytes thru the I2C hardware,
1594
1558
// add 50ms just for kicks
1595
1559
1560
+
1561
+
1596
1562
portTickType ticksTimeOut = ((totalBytes /(i2cGetFrequency (i2c )/(10 * 1000 )))+ 50 )/portTICK_PERIOD_MS ;
1597
1563
portTickType tBefore = xTaskGetTickCount ();
1598
1564
@@ -1607,6 +1573,14 @@ uint32_t eBits = xEventGroupWaitBits(i2c->i2c_event,EVENT_DONE,pdFALSE,pdTRUE,ti
1607
1573
portTickType tAfter = xTaskGetTickCount ();
1608
1574
1609
1575
uint32_t b ;
1576
+ // if xEventGroupSetBitsFromISR() failed, the ISR could have succeeded but never been
1577
+ // able to mark the success
1578
+
1579
+ if (i2c -> exitCode != eBits ){ // try to recover from O/S failure
1580
+ // log_e("EventGroup Failed:%p!=%p",eBits,i2c->exitCode);
1581
+ eBits = i2c -> exitCode ;
1582
+ }
1583
+
1610
1584
if (!(eBits == EVENT_DONE )&& (eBits & ~(EVENT_ERROR_NAK |EVENT_ERROR |EVENT_DONE ))){ // not only Done, therefore error, exclude ADDR NAK
1611
1585
dumpI2c (i2c );
1612
1586
i2cDumpInts ();
@@ -1647,15 +1621,28 @@ else { // GROSS timeout, shutdown ISR , report Timeout
1647
1621
i2cDumpInts ();
1648
1622
}
1649
1623
1624
+ // offloading all EventGroups to dispatch, EventGroups in ISR is not always successful
1625
+ // 11/20/2017
1650
1626
// if error, need to trigger all succeeding dataQueue events with the EVENT_ERROR_PREV
1651
- if (eBits & EVENT_ERROR ){// every dq past the error point needs it's EventGroup Released
1652
- b = i2c -> queuePos + 1 ;
1653
- while (b < i2c -> queueCount ){
1627
+
1628
+ b = 0 ;
1629
+ while (b < i2c -> queueCount ){
1630
+ if (b < i2c -> queuePos ){ // before any error
1631
+ if (i2c -> dq [b ].queueEvent ){ // this data queue element has an EventGroup
1632
+ xEventGroupSetBits (i2c -> dq [b ].queueEvent ,EVENT_DONE );
1633
+ }
1634
+ }
1635
+ else if (b == i2c -> queuePos ){ // last processed queue
1636
+ if (i2c -> dq [b ].queueEvent ){ // this data queue element has an EventGroup
1637
+ xEventGroupSetBits (i2c -> dq [b ].queueEvent ,eBits );
1638
+ }
1639
+ }
1640
+ else { // never processed queues
1654
1641
if (i2c -> dq [b ].queueEvent ){ // this data queue element has an EventGroup
1655
1642
xEventGroupSetBits (i2c -> dq [b ].queueEvent ,eBits |EVENT_ERROR_PREV );
1656
1643
}
1657
- b ++ ;
1658
1644
}
1645
+ b ++ ;
1659
1646
}
1660
1647
1661
1648
I2C_MUTEX_UNLOCK ();
0 commit comments