|
|
 |
Ответов
|
Dec 17 2016, 16:47
|
Знающий
   
Группа: Участник
Сообщений: 643
Регистрация: 29-05-09
Из: Германия
Пользователь №: 49 725

|
Цитата(Сергей Борщ @ Dec 16 2016, 08:48)  Присоединяюсь к вопросу. Я сразу начал и с прерываниями и с ПДП и под ОС. Все работет. Что я сделал неправильно? Вы, в итоге, наверняка сделали все правильно. Речь о том, что именно у F1xx I2C очень кривой. Об этом было много тем здесь, еще до появления других Fxxx, просто многие подзабыли. Достаточно напомнить, что при работе с I2C по прерываниям необходимо заботится о том, чтобы это прерывание не было прервано (самый высокий приоритет для I2C, либо вообще запреты прерываний на определенных этапах обработки I2C). Более того, на малых скоростях тактирования ядра (например, с целью энергосбережения) наблюдались комбинации флагов прерывания, которые никак не упоминались в документации, и для которых не было даже определений в STL. Это вводило в ступор обработчик. Поскольку большинство заводит камни сразу на максимуме, на такой косяк натыкались не многие, похоже. Мне понадобилась пара недель, с последующими доработками при работе с различной I2C периферией, чтобы запустить F103 стабильно. Когда появились F0xx, где I2C переработан, мне хватило и пары часов, чтобы запустить I2C так, что работает до сих пор.
Сообщение отредактировал KnightIgor - Dec 17 2016, 16:50
|
|
|
|
|
Dec 20 2016, 06:52
|
Участник

Группа: Участник
Сообщений: 40
Регистрация: 10-09-16
Пользователь №: 93 282

|
Цитата(KnightIgor @ Dec 17 2016, 16:47)  Вы, в итоге, наверняка сделали все правильно. Речь о том, что именно у F1xx I2C очень кривой. Об этом было много тем здесь, еще до появления других Fxxx, просто многие подзабыли. Достаточно напомнить, что при работе с I2C по прерываниям необходимо заботится о том, чтобы это прерывание не было прервано (самый высокий приоритет для I2C, либо вообще запреты прерываний на определенных этапах обработки I2C). Более того, на малых скоростях тактирования ядра (например, с целью энергосбережения) наблюдались комбинации флагов прерывания, которые никак не упоминались в документации, и для которых не было даже определений в STL. Это вводило в ступор обработчик. Поскольку большинство заводит камни сразу на максимуме, на такой косяк натыкались не многие, похоже. Мне понадобилась пара недель, с последующими доработками при работе с различной I2C периферией, чтобы запустить F103 стабильно. Когда появились F0xx, где I2C переработан, мне хватило и пары часов, чтобы запустить I2C так, что работает до сих пор. А можно кусок кода или пример по обработке (что б не пройти по тем же граблям). ОГРОМНОЕ СПАСИБО
|
|
|
|
|
Dec 20 2016, 20:52
|
Знающий
   
Группа: Участник
Сообщений: 643
Регистрация: 29-05-09
Из: Германия
Пользователь №: 49 725

|
Цитата(dimon_rub @ Dec 20 2016, 08:52)  А можно кусок кода или пример по обработке (что б не пройти по тем же граблям). ОГРОМНОЕ СПАСИБО Я приведу кусок - обработчик прерывания. Сразу скажу, что он работает в моей, назовем это так, - экосистеме. Это макросы, различные процедуры, не приведенные здесь. Обработчик - один для нескольких I2C периферий. Поэтому используются управляющие структуры данных. Смотрите не столько на инструкции, сколько на комментарии. CODE // ----------------------------------------------------------------------------- // EVENT INTERRUPT HANDLER // ----------------------------------------------------------------------------- static void I2Cx_EV_IRQHandler(uint8_t port) { I2C_Control_Type *ctrl = &control[port]; I2C_TypeDef *i2c = ctrl->i2c;
switch (ctrl->evnt = I2C_Event(i2c, ctrl->readsr2)) {
// - - I2C Started - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
case I2C_EVENT_MASTER_MODE_SELECT_NO_SB: // MASTER, START sent: BUSY, MSL but SB are set
break; // ignore, wait for SB set
case I2C_EVENT_MASTER_MODE_SELECT: // MASTER, (RE)START sent: BUSY, MSL and SB are set
if (ctrl->wcnt > 0) { // PREPARE WRITING: send the slave Address // with R/W bit ==0 I2C_SEND_ADDR(i2c, ctrl->ptr[0] & ~I2C_Direction_Receiver);
} else { // PREPARE READING:
// For N == 2 set POS bit to move // NACK to the second byte.
if (ctrl->icnt == 2) { I2C_POS(i2c); // ACK is already set } else { #if (USE_I2C_RX_DMA1)
// if RX DMA enabled, allow below only for N == 1...
if (ctrl->icnt < 2) #endif // For pure interrupt mode RX and // cases (N != 2) enable RxNE interrupt: I2C_BUFIE_SET(i2c); } // Prevent reading of SR2 to avoid resetting of ADDR bit, // if two or less bytes to read (cases N == 1 or N == 2). // See RM0008.PDF, Doc ID 13902 Rev 14, Page 735.
if (ctrl->icnt <= 2) ctrl->readsr2 = 0; // Send I2C ID (slave Address to receive). // Writing DR here preceeded by SR1 reading above clears SB // with R/W bit ==1 I2C_SEND_ADDR(i2c, ctrl->ptr[0] | I2C_Direction_Receiver); } break;
// - - I2C Transmitting - - - - - - - - - - - - - - - - - - - - - - - - - - -
case I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED: // ADDR sent with /W bit
#if (USE_I2C_TX_DMA1)
// Transmit bytes via DMA
I2C_START_DMA_TX(ctrl); #else // WRITE the FIRST data byte:
I2C_WRITE_NEXT(ctrl, ctrl->ptr[ctrl->indx++]); // .icnt-- and .wnt-- inside... #endif
break; // // ATTENTION! - since 03.11.11. does not work without the simple // case I2C_EVENT_MASTER_BYTE_TRANSMITTING below as if // I2C_EVENT_MASTER_BYTE_TRANSMITTING occures sometimes // before I2C_EVENT_MASTER_BYTE_TRANSMITTED. // Possible reasons (due to the following changes): // 1). Interrupt priority of I2C has been changed to the highest one; // 2). The I2C speed has been reduced down to 100kHz from 400kHz, // the driver was tested before. // case I2C_EVENT_MASTER_BYTE_TRANSMITTING: // Data being SENT; TRA, BSY, MSL and { // TxE but BTF are set. uint8_t ex = 0; uint32_t tp = i2c_SBTimeoutInit(port, 10 * BITS_ONE_BYTE); // Time of two I2C bytes to wait while (!I2C_BTF(i2c) && !(ex = i2c_SBTimeoutExpired(&tp))); // Wait for BTF! It MUST arrive else // it were a severe hardware error... if (ex) // BTF still off: expired! { I2C_ERROR_HANDLER(port, ctrl->code = ctrl->evnt); break; } // else CONTINUE: } case I2C_EVENT_MASTER_BYTE_TRANSMITTED: // Data byte's been SENT; TRA, BSY, MSL and // both TxE and BTF are set. if (ctrl->icnt) { if (ctrl->wcnt == 0)
// RESTART after the last byte from [WRITE] transaction. // See RM0008.PDF, Doc ID 13902 Rev 12, Page 733, // Note to START and Page 734 to "Closing the // communication"
I2C_START(i2c);
else // just write the next byte I2C_WRITE_NEXT(ctrl, ctrl->ptr[ctrl->indx++]); // .icnt-- and .wnt-- inside...
} else { // The last byte is completely pushed out, ACK from slave got. // Bus is stretched (BTF is set), issue STOP. I2C_ISSUE_STOP(i2c); I2C_SUCCESS_HANDLER(ctrl); } break;
// TRAP: where is TRA bit?! case I2C_EVENT_MASTER_BYTE_TRANSMITTED_BUT_TRA:
I2C_ERROR_HANDLER(port, ctrl->code = ctrl->evnt); break;
// - - I2C Receiving - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// +++ case N == 1 (single byte) and N == 2 begin +++
// .icnt is == 1 here if READ ONLY operation started, // or == 1 + wcnt if RESTART-AFTER-WRITE preceeded.
// +++ case N == 1 (single byte) and N == 2; I2C_readSR2 == 0 // See RM0008.PDF, Doc ID 13902 Rev 14, Page 735.
case I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED_SR1: // ADDR sent, bit still set (I2C_readSR2 == 0) { I2C_PREPARE_CRITICAL_SECTION(sv);
// To avoid multiply data receiption... I2C_BEGIN_CRITICAL_SECTION(sv);
// Clear ADDR bit by reading SR2 out (SR1's been read at "switch"). // This starts the receiption immediately. ctrl->evnt |= I2C_GET_SR2(i2c) << 16;
// Prepare NACK (clear ACK); if POS is set it goes to the second (==last) byte. // Don't worry about too late NACK setting: all IRQs are disabled! I2C_NACK_IT(i2c); if (ctrl->icnt == 1) // Prepare/issue STOP after the SINGLE byte I2C_ISSUE_STOP(i2c);
I2C_END_CRITICAL_SECTION(sv);
// Allow SR2 readout at "switch" again to get into RxNE interrupt. // CONTINUE... } // This fucking case is neccessary for reading two bytes @48MHz CPU // while I2C_readSR2 == 0 after the address has been sent. // Occured when trying to read MCP4661 (2x Reostat) out. // // It seems that the interrupt is generated by ADDR = 1 while the bit // has not appeared in SR1 yet! At the same time the SB bit is still // seen in SR1. Madness! // case I2C_EVENT_MASTER_MODE_SELECT_SR1: ctrl->readsr2 = 1; // Allow SR2 readout at "switch" again break; // --- case N == 1 (single byte) and N == 2 end --- // +++ case N > 2:
case I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED: // ADDR sent, bit cleared
// 1. ADDR has already been cleared at "switch", thus // 2. the receiption of the first byte must be in // progress now; #if (USE_I2C_RX_DMA1)
// Receive bytes via DMA I2C_START_DMA_RX(ctrl); #else // 3. RxNE buffer interrupt is enabled. // So do nothing here. #endif
break;
// BTF is set: case I2C_EVENT_MASTER_BYTE_RECEIVED_BTF:
switch (ctrl->icnt) {
case 2: // N == 2 (two bytes only)
// Here both DR and SHIFT are full with expected // two bytes because RxNE interrupt has not been // enabled yet. NACK has been issued to the last // byte because NACK along with POS were prepared // before. // I2C bus is stretched (BTF set). Issue STOP. // Read data TWICE (both from DR and SHIFT)! // See Errata about disable IRQ for // [STOP-read DATA(N-1)-read DATA(N)]
I2C_STOPN_2(ctrl); // surrounded by disabled IRQs... ctrl->icnt = 0; // All data got. I2C_SUCCESS_HANDLER(ctrl); break;
case 3: // N == 3 bytes left to receive
// Here Data(N-2) in DR and Data(N-1) in SHIFT; // The bus is stretched/pending (BTF is set). // Prepare NACK for Data(N) and... I2C_NACK_IT(i2c);
// ...read Data(N-2) out: // this starts the receiption of the last byte // with NACK at its end. I2C_STORE(ctrl, ctrl->ptr[ctrl->indx++]);
// Prepare STOP and read Data(N-1) out: // See Errata about disable IRQ for [STOP-read DATA(N-1)] I2C_STOPN_1(ctrl); // surrounded by disabled IRQs ctrl->icnt = 1; // One byte left to read as soon as RxNE set // Enable RxNE interrupt again to read it out. I2C_BUFIE_SET(i2c); break;
default: // RxNE _AND_ BTF are set: store and check if complete. // This occures also at enabled RxNE interrupt if // there were no possibility to process RxNE below // because of too long interrupts of higher priority. // Store, check if complete: I2C_STORE_NEXT(ctrl, ctrl->ptr[ctrl->indx++]); } break;
case I2C_EVENT_MASTER_BYTE_RECEIVED: // RxNE is set
if (ctrl->icnt == 3) // 3 bytes left to receive: // Here Data(N-2) in DR and the receiption of Data(N-1) // must/can be in progress.
// See RM0008.PDF, Doc ID 13902 Rev 12, Page 737: // DON'T READ the data byte, just disable RxNE interrupt and // let be interrupted by BTF above (both DR and SHIFT are full)
I2C_BUFIE_CLEAR(i2c);
else // Store, check if complete: I2C_STORE_NEXT(ctrl, ctrl->ptr[ctrl->indx++]);
break; // --- case N > 2 end ---
default: // // 19.03.2014: At 24MHz an interrupt can occure while no status bits set yet! // This case is not to consider as an error: exit the interrupt // and let it shoot again with all bits set. // It seems to occure when prepared to read only 2 bytes (when // ctrl->readsr2 is 0). // if (ctrl->readsr2 && ctrl->evnt) I2C_ERROR_HANDLER(port, ctrl->code = ctrl->evnt); } ctrl->guard = 1; }
Сообщение отредактировал KnightIgor - Dec 20 2016, 21:17
|
|
|
|
Сообщений в этой теме
dimon_rub Вопрос по I2C Dec 15 2016, 12:21 haker_fox QUOTE (dimon_rub @ Dec 15 2016, 20:21) Зд... Dec 15 2016, 13:01 Obam По бубну Dec 15 2016, 13:11 pitt Цитата(dimon_rub @ Dec 15 2016, 07:21) Зд... Dec 15 2016, 13:25 dimon_rub Спасибо. Хотелось услышать людей непосредственно р... Dec 15 2016, 14:04 KnightIgor Цитата(dimon_rub @ Dec 15 2016, 16:04) Сп... Dec 15 2016, 20:11  dimon_rub Цитата(KnightIgor @ Dec 15 2016, 20:11) М... Dec 16 2016, 07:36   Pridnya Цитата(KnightIgor @ Dec 15 2016, 23:11) М... Dec 16 2016, 09:35    Сергей Борщ QUOTE (Pridnya @ Dec 16 2016, 11:35) А во... Dec 16 2016, 11:15     Kabdim Цитата(Сергей Борщ @ Dec 16 2016, 14:15) ... Dec 16 2016, 12:05      Сергей Борщ QUOTE (Kabdim @ Dec 16 2016, 14:05) Если ... Dec 16 2016, 12:11    zltigo Цитата(Pridnya @ Dec 16 2016, 11:35) Но в... Dec 16 2016, 11:18     Pridnya Цитата(Сергей Борщ @ Dec 16 2016, 14:15) ... Dec 16 2016, 12:05    jcxz Цитата(Pridnya @ Dec 16 2016, 12:35) Но в... Dec 17 2016, 11:42     zltigo Цитата(jcxz @ Dec 17 2016, 13:42) Бывают ... Dec 17 2016, 11:49   alexf Бывают ситуации когда CPU нечего делать пока идет ... Dec 17 2016, 20:48    zltigo Цитата(alexf @ Dec 17 2016, 22:48) Бывают... Dec 18 2016, 08:09     dimon_rub Цитата(KnightIgor @ Dec 20 2016, 20:52) Я... Dec 21 2016, 08:26 Aleksandr Baranov Я бы еще вспомнил процедуру "I2C bus recovery... Dec 20 2016, 22:22 alexf Если я раз в секунду читаю пару датчиков за 1 мсек... Dec 21 2016, 00:37 KnightIgor Цитата(Aleksandr Baranov @ Dec 21 2016, 00... Dec 22 2016, 12:14  jcxz Просто "безудержное дёргание" и не должн... Dec 22 2016, 12:53   KnightIgor Цитата(jcxz @ Dec 22 2016, 14:53) Просто ... Dec 22 2016, 12:59    jcxz Цитата(KnightIgor @ Dec 22 2016, 15:59) Э... Dec 22 2016, 13:05  zltigo Цитата(KnightIgor @ Dec 22 2016, 14:14) О... Dec 22 2016, 14:51 Aleksandr Baranov В "AN10216-01 I2C Manual" не сказано: ... Dec 22 2016, 15:37 KnightIgor Цитата(Aleksandr Baranov @ Dec 22 2016, 17... Dec 22 2016, 16:32  zltigo Цитата(KnightIgor @ Dec 22 2016, 18:32) Е... Dec 22 2016, 17:22   jcxz Цитата(zltigo @ Dec 22 2016, 20:22) Такое... Dec 22 2016, 22:44    zltigo Цитата(jcxz @ Dec 23 2016, 00:44) Да, дол... Dec 23 2016, 06:35     jcxz Цитата(zltigo @ Dec 23 2016, 09:35) Я пис... Dec 23 2016, 16:20      zltigo Цитата(jcxz @ Dec 23 2016, 18:20) Это у В... Dec 24 2016, 07:09 AVR Мои 5: когда я работал с I2C на AVR то на коротком... Dec 23 2016, 07:07
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|