Перейти к содержанию
    

Освоение MSP430 / первые шаги

Ещё варианты:

1. Добавить в конец программы какую-то команду, как в рабочем примере (в той программе после CS_HIGH есть ещё пара строк работы со светодиодом).

Например, после CS_HIGH добавить ещё 2-3 команды записи байта - пусть их будет не 6 а 9. Посмотреть что будет с задержкой после 6-й команды.

 

2. В рабочем примере, в конце текста есть ещё команда Return 0 и кавычка - а есть ли они в переработанном варианте?

Может это они влияют на завершение программы с такой задержкой.

 

3. Переключить в режим 3-pin SPI mode. Всё равно аппаратная нога SS не нужна в данном случае, но может здесь что-то изменится.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Однако, дизассемблер ничего лишнего не указывает.



Ну вы б хоть опубликовали дизассм всех вариантов, а то "чёрной магией" про совершенно внятный контроллер повеяло.

Изменено пользователем Obam

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Да, конечно. Вот я, для наглядности, оформил процедуру инициализации карточки в отдельную функцию:

unsigned char Init_SD (void)
{
    volatile unsigned char data;
    volatile unsigned char  i;
    // initialize SD-card in SPI-mode and reset
          CS_HIGH;
          for (i=0; i<10; i++)                      // for more than 74 cycles
          {
             UCB0TXBUF = 0xFF;                      // send clock pulses at CS high state
             while (!(UCB0IFG & UCTXIFG));
          }

          for(i=3; i>0; i--);                       // Delay

     // SD soft reset sequence (CMD0)
          data = UCB0RXBUF;                        // clear RX flag
          CS_LOW;
          UCB0TXBUF = 0x40;
          while (!(UCB0IFG & UCRXIFG));
          data = UCB0RXBUF;                        // clear RX flag
          UCB0TXBUF = 0;
          while (!(UCB0IFG & UCRXIFG));
          data = UCB0RXBUF;                        // clear RX flag
          UCB0TXBUF = 0;
          while (!(UCB0IFG & UCRXIFG));
          data = UCB0RXBUF;                        // clear RX flag
          UCB0TXBUF = 0;
          while (!(UCB0IFG & UCRXIFG));
          data = UCB0RXBUF;                        // clear RX flag
          UCB0TXBUF = 0;
          while (!(UCB0IFG & UCRXIFG));
          data = UCB0RXBUF;                        // clear RX flag
          UCB0TXBUF = 0x95;
          while (!(UCB0IFG & UCRXIFG));           // USCI_B0 RX buffer ready?
          UCB0TXBUF = 0xFF;
          data = UCB0RXBUF;
          while (!(UCB0IFG & UCRXIFG));
          data = UCB0RXBUF;
          UCB0TXBUF = 0xFF;
          while (!(UCB0IFG & UCRXIFG));
          data = UCB0RXBUF;
          CS_HIGH;

          return data;
}

Здесь переменная-счётчик i используется сначала для отсчёта 10-ти байтов 0xFF, посылаемых при высоком уровне CS, а затем для формирования задержки между этой стадией и следующей, где посылается команда сброса (CMD0) и принимается ответ от карточки.

Вызываю её, как и прежде, после настройки модуля eUSCI_B :

int main(void)
{
volatile unsigned int data1, data2;

      WDTCTL = WDTPW + WDTHOLD;                 // Stop watchdog timer
// Disable the GPIO power-on default high-impedance mode
// to activate previously configured port settings
      PM5CTL0 &= ~LOCKLPM5;
// eUSCI_B0 Initializing
      UCB0CTL1 |= UCSWRST;                      // Enable SW reset
      P1DIR |= BIT0;                            // Set P1.0 to output direction
      P1SEL0 |= BIT0 + BIT1 + BIT2 + BIT3;      // P1.0 - P1.3 USCI_B0 option select
      P3DIR |= BIT0;                            // P3.0 output direction (CS)
      UCB0CTLW0 |= UCMSB + UCMST + UCSYNC;      // 8-bit SPI mstr, MSB 1st, sync
      UCB0CTLW0 |= UCMODE1 + UCSSEL1 + UCSTEM;  // 4-pin mode, STE low, SMCLK
      UCB0BRW = 4;                              // division, clock eq. to BRCLK/4
      UCB0STATW = 0;                            // clear errors
      UCB0CTL1 &= ~UCSWRST;                     // Clear SW reset, resume operation

      data1 = 0xAA;

      data2 = Init_SD();

И, как видно по осциллограмме ниже, всё выполняется корректно. Здесь красный луч - MOSI, зелёный - MISO, синий - SCLK, жёлтый - CS.

20200602-0001.thumb.gif.2d3b47329cf9b9247bb95518f2a8eb99.gif

Но стоит мне переменную-счётчик i объявить обычной, не volatile, как начинаются чудеса. На следующей осциллограмме видно, что

а) пауза между стадиями сократилась,

б) пауз между передачей байтов во второй стадии нет совсем, то есть проверка на заполнение приёмного буфера как будто не выполняется,

в) сигнал CS возвращается в высокое состояние ещё до того, как закончилась передача, то есть, опять же, не взирая на флаг UCRXIFG.

20200602-0002.thumb.gif.2112d282353ffd2ab52b11086df4f42f.gif

Вот листинги дизассемблера обоих вариантов функции.  volatile unsigned char  i:

        Init_SD():
008000:   8321                DECD.W  SP
 83               CS_HIGH;
008002:   D3D2 0222           BIS.B   #1,&PB_PBOUT
 84               for (i=0; i<10; i++)                      // for more than 74 cycles
008006:   43C1 0001           CLR.B   0x0001(SP)
00800a:   90F1 000A 0001      CMP.B   #0x000a,0x0001(SP)
008010:   2C0C                JHS     ($C$L3)
 86                  UCB0TXBUF = 0xFF;                      // send clock pulses at CS high state
        $C$L1:
008012:   40B2 00FF 054E      MOV.W   #0x00ff,&eUSCI_B0_UCB0TXBUF
 87                  while (!(UCB0IFG & UCTXIFG));
        $C$L2:
008018:   B3A2 056C           BIT.W   #2,&eUSCI_B0_UCB0IFG
00801c:   27FD                JEQ     ($C$L2)
 84               for (i=0; i<10; i++)                      // for more than 74 cycles
00801e:   53D1 0001           INC.B   0x0001(SP)
008022:   90F1 000A 0001      CMP.B   #0x000a,0x0001(SP)
008028:   2BF4                JLO     ($C$L1)
 90               for(i=3; i>0; i--);                       // Delay
        $C$L3:
00802a:   40F1 0003 0001      MOV.B   #0x0003,0x0001(SP)
008030:   93C1 0001           TST.B   0x0001(SP)
008034:   2405                JEQ     ($C$L5)
        $C$L4:
008036:   83D1 0001           DEC.B   0x0001(SP)
00803a:   93C1 0001           TST.B   0x0001(SP)
00803e:   23FB                JNE     ($C$L4)
 93               data = UCB0RXBUF;                        // clear RX flag
        $C$L5:
008040:   421F 054C           MOV.W   &eUSCI_B0_UCB0RXBUF,R15
008044:   4FC1 0000           MOV.B   R15,0x0000(SP)
 94               CS_LOW;
008048:   C3D2 0222           BIC.B   #1,&PB_PBOUT
 95               UCB0TXBUF = 0x40;
00804c:   40B2 0040 054E      MOV.W   #0x0040,&eUSCI_B0_UCB0TXBUF
 96               while (!(UCB0IFG & UCRXIFG));
        $C$L6:
008052:   B392 056C           BIT.W   #1,&eUSCI_B0_UCB0IFG
008056:   27FD                JEQ     ($C$L6)
 97               data = UCB0RXBUF;                        // clear RX flag
008058:   421F 054C           MOV.W   &eUSCI_B0_UCB0RXBUF,R15
00805c:   4FC1 0000           MOV.B   R15,0x0000(SP)
 98               UCB0TXBUF = 0;
008060:   4382 054E           CLR.W   &eUSCI_B0_UCB0TXBUF
 99               while (!(UCB0IFG & UCRXIFG));
        $C$L7:
008064:   B392 056C           BIT.W   #1,&eUSCI_B0_UCB0IFG
008068:   27FD                JEQ     ($C$L7)
100               data = UCB0RXBUF;                        // clear RX flag
00806a:   421F 054C           MOV.W   &eUSCI_B0_UCB0RXBUF,R15
00806e:   4FC1 0000           MOV.B   R15,0x0000(SP)
101               UCB0TXBUF = 0;
008072:   4382 054E           CLR.W   &eUSCI_B0_UCB0TXBUF
102               while (!(UCB0IFG & UCRXIFG));
        $C$L8:
008076:   B392 056C           BIT.W   #1,&eUSCI_B0_UCB0IFG
00807a:   27FD                JEQ     ($C$L8)
103               data = UCB0RXBUF;                        // clear RX flag
00807c:   421F 054C           MOV.W   &eUSCI_B0_UCB0RXBUF,R15
008080:   4FC1 0000           MOV.B   R15,0x0000(SP)
104               UCB0TXBUF = 0;
008084:   4382 054E           CLR.W   &eUSCI_B0_UCB0TXBUF
105               while (!(UCB0IFG & UCRXIFG));
        $C$L9:
008088:   B392 056C           BIT.W   #1,&eUSCI_B0_UCB0IFG
00808c:   27FD                JEQ     ($C$L9)
106               data = UCB0RXBUF;                        // clear RX flag
00808e:   421F 054C           MOV.W   &eUSCI_B0_UCB0RXBUF,R15
008092:   4FC1 0000           MOV.B   R15,0x0000(SP)
107               UCB0TXBUF = 0;
008096:   4382 054E           CLR.W   &eUSCI_B0_UCB0TXBUF
108               while (!(UCB0IFG & UCRXIFG));
        $C$L10:
00809a:   B392 056C           BIT.W   #1,&eUSCI_B0_UCB0IFG
00809e:   27FD                JEQ     ($C$L10)
109               data = UCB0RXBUF;                        // clear RX flag
0080a0:   421F 054C           MOV.W   &eUSCI_B0_UCB0RXBUF,R15
0080a4:   4FC1 0000           MOV.B   R15,0x0000(SP)
110               UCB0TXBUF = 0x95;
0080a8:   40B2 0095 054E      MOV.W   #0x0095,&eUSCI_B0_UCB0TXBUF
111               while (!(UCB0IFG & UCRXIFG));           // USCI_B0 RX buffer ready?
        $C$L11:
0080ae:   B392 056C           BIT.W   #1,&eUSCI_B0_UCB0IFG
0080b2:   27FD                JEQ     ($C$L11)
112               UCB0TXBUF = 0xFF;
0080b4:   40B2 00FF 054E      MOV.W   #0x00ff,&eUSCI_B0_UCB0TXBUF
113               data = UCB0RXBUF;
0080ba:   421F 054C           MOV.W   &eUSCI_B0_UCB0RXBUF,R15
0080be:   4FC1 0000           MOV.B   R15,0x0000(SP)
114               while (!(UCB0IFG & UCRXIFG));
        $C$L12:
0080c2:   B392 056C           BIT.W   #1,&eUSCI_B0_UCB0IFG
0080c6:   27FD                JEQ     ($C$L12)
115               data = UCB0RXBUF;
0080c8:   421F 054C           MOV.W   &eUSCI_B0_UCB0RXBUF,R15
0080cc:   4FC1 0000           MOV.B   R15,0x0000(SP)
116               UCB0TXBUF = 0xFF;
0080d0:   40B2 00FF 054E      MOV.W   #0x00ff,&eUSCI_B0_UCB0TXBUF
117               while (!(UCB0IFG & UCRXIFG));
        $C$L13:
0080d6:   B392 056C           BIT.W   #1,&eUSCI_B0_UCB0IFG
0080da:   27FD                JEQ     ($C$L13)
118               data = UCB0RXBUF;
0080dc:   421F 054C           MOV.W   &eUSCI_B0_UCB0RXBUF,R15
0080e0:   4FC1 0000           MOV.B   R15,0x0000(SP)
119               CS_HIGH;
0080e4:   D3D2 0222           BIS.B   #1,&PB_PBOUT
121               return data;
0080e8:   416C                MOV.B   @SP,R12
122     }
0080ea:   5321                INCD.W  SP
0080ec:   0110                RETA    

unsigned char  i:

        Init_SD():
008000:   8321                DECD.W  SP
 83               CS_HIGH;
008002:   D3D2 0222           BIS.B   #1,&PB_PBOUT
 84               for (i=0; i<10; i++)                      // for more than 74 cycles
008006:   434F                CLR.B   R15
008008:   907F 000A           CMP.B   #0x000a,R15
00800c:   2C0A                JHS     ($C$L3)
 86                  UCB0TXBUF = 0xFF;                      // send clock pulses at CS high state
        $C$L1:
00800e:   40B2 00FF 054E      MOV.W   #0x00ff,&eUSCI_B0_UCB0TXBUF
 87                  while (!(UCB0IFG & UCTXIFG));
        $C$L2:
008014:   B3A2 056C           BIT.W   #2,&eUSCI_B0_UCB0IFG
008018:   27FD                JEQ     ($C$L2)
 84               for (i=0; i<10; i++)                      // for more than 74 cycles
00801a:   535F                INC.B   R15
00801c:   907F 000A           CMP.B   #0x000a,R15
008020:   2BF6                JLO     ($C$L1)
 90               for(i=3; i>0; i--);                       // Delay
        $C$L3:
008022:   407F 0003           MOV.B   #0x0003,R15
008026:   934F                TST.B   R15
008028:   2402                JEQ     ($C$L5)
        $C$L4:
00802a:   835F                DEC.B   R15
00802c:   23FE                JNE     ($C$L4)
 93               data = UCB0RXBUF;                        // clear RX flag
        $C$L5:
00802e:   421F 054C           MOV.W   &eUSCI_B0_UCB0RXBUF,R15
008032:   4FC1 0000           MOV.B   R15,0x0000(SP)
 94               CS_LOW;
008036:   C3D2 0222           BIC.B   #1,&PB_PBOUT
 95               UCB0TXBUF = 0x40;
00803a:   40B2 0040 054E      MOV.W   #0x0040,&eUSCI_B0_UCB0TXBUF
 96               while (!(UCB0IFG & UCRXIFG));
        $C$L6:
008040:   B392 056C           BIT.W   #1,&eUSCI_B0_UCB0IFG
008044:   27FD                JEQ     ($C$L6)
 97               data = UCB0RXBUF;                        // clear RX flag
008046:   421F 054C           MOV.W   &eUSCI_B0_UCB0RXBUF,R15
00804a:   4FC1 0000           MOV.B   R15,0x0000(SP)
 98               UCB0TXBUF = 0;
00804e:   4382 054E           CLR.W   &eUSCI_B0_UCB0TXBUF
 99               while (!(UCB0IFG & UCRXIFG));
        $C$L7:
008052:   B392 056C           BIT.W   #1,&eUSCI_B0_UCB0IFG
008056:   27FD                JEQ     ($C$L7)
100               data = UCB0RXBUF;                        // clear RX flag
008058:   421F 054C           MOV.W   &eUSCI_B0_UCB0RXBUF,R15
00805c:   4FC1 0000           MOV.B   R15,0x0000(SP)
101               UCB0TXBUF = 0;
008060:   4382 054E           CLR.W   &eUSCI_B0_UCB0TXBUF
102               while (!(UCB0IFG & UCRXIFG));
        $C$L8:
008064:   B392 056C           BIT.W   #1,&eUSCI_B0_UCB0IFG
008068:   27FD                JEQ     ($C$L8)
103               data = UCB0RXBUF;                        // clear RX flag
00806a:   421F 054C           MOV.W   &eUSCI_B0_UCB0RXBUF,R15
00806e:   4FC1 0000           MOV.B   R15,0x0000(SP)
104               UCB0TXBUF = 0;
008072:   4382 054E           CLR.W   &eUSCI_B0_UCB0TXBUF
105               while (!(UCB0IFG & UCRXIFG));
        $C$L9:
008076:   B392 056C           BIT.W   #1,&eUSCI_B0_UCB0IFG
00807a:   27FD                JEQ     ($C$L9)
106               data = UCB0RXBUF;                        // clear RX flag
00807c:   421F 054C           MOV.W   &eUSCI_B0_UCB0RXBUF,R15
008080:   4FC1 0000           MOV.B   R15,0x0000(SP)
107               UCB0TXBUF = 0;
008084:   4382 054E           CLR.W   &eUSCI_B0_UCB0TXBUF
108               while (!(UCB0IFG & UCRXIFG));
        $C$L10:
008088:   B392 056C           BIT.W   #1,&eUSCI_B0_UCB0IFG
00808c:   27FD                JEQ     ($C$L10)
109               data = UCB0RXBUF;                        // clear RX flag
00808e:   421F 054C           MOV.W   &eUSCI_B0_UCB0RXBUF,R15
008092:   4FC1 0000           MOV.B   R15,0x0000(SP)
110               UCB0TXBUF = 0x95;
008096:   40B2 0095 054E      MOV.W   #0x0095,&eUSCI_B0_UCB0TXBUF
111               while (!(UCB0IFG & UCRXIFG));           // USCI_B0 RX buffer ready?
        $C$L11:
00809c:   B392 056C           BIT.W   #1,&eUSCI_B0_UCB0IFG
0080a0:   27FD                JEQ     ($C$L11)
112               UCB0TXBUF = 0xFF;
0080a2:   40B2 00FF 054E      MOV.W   #0x00ff,&eUSCI_B0_UCB0TXBUF
113               data = UCB0RXBUF;
0080a8:   421F 054C           MOV.W   &eUSCI_B0_UCB0RXBUF,R15
0080ac:   4FC1 0000           MOV.B   R15,0x0000(SP)
114               while (!(UCB0IFG & UCRXIFG));
        $C$L12:
0080b0:   B392 056C           BIT.W   #1,&eUSCI_B0_UCB0IFG
0080b4:   27FD                JEQ     ($C$L12)
115               data = UCB0RXBUF;
0080b6:   421F 054C           MOV.W   &eUSCI_B0_UCB0RXBUF,R15
0080ba:   4FC1 0000           MOV.B   R15,0x0000(SP)
116               UCB0TXBUF = 0xFF;
0080be:   40B2 00FF 054E      MOV.W   #0x00ff,&eUSCI_B0_UCB0TXBUF
117               while (!(UCB0IFG & UCRXIFG));
        $C$L13:
0080c4:   B392 056C           BIT.W   #1,&eUSCI_B0_UCB0IFG
0080c8:   27FD                JEQ     ($C$L13)
118               data = UCB0RXBUF;
0080ca:   421F 054C           MOV.W   &eUSCI_B0_UCB0RXBUF,R15
0080ce:   4FC1 0000           MOV.B   R15,0x0000(SP)
119               CS_HIGH;
0080d2:   D3D2 0222           BIS.B   #1,&PB_PBOUT
121               return data;
0080d6:   416C                MOV.B   @SP,R12
122     }
0080d8:   5321                INCD.W  SP
0080da:   0110                RETA    

Как можно видеть, вся разница в одной-единственной строчке (не считая, конечно, замены ячейки памяти на регистр R15):

00803a:   93C1 0001           TST.B   0x0001(SP)

которой во втором варианте нет. Но какое отличие в поведении! Никогда бы не подумал, что такое возможно. Следует вообще все переменные объявлять volatile?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

еррату бы ещё глянуть, там, насколько помню, всегда было отнюдь не пусто по части usci.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Поскольку у вас проявления глюка меняется от смены порядка команд, попробуйте увеличить разницу между частотой ядра и частотой SPI.
Может быть разница в 4 раза мала для нормальной синхронной работы?
Хотя никаких намеков на это в документации я не нашел...
Или увеличьте частоту ядра или уменьшите скорость SPI.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Гипотеза, почему могут отличаться программы с переменными типа volatile и переменными обычными, статья.

Если смотреть на листинги, в той части где происходит отправка команды 0 на карту - так программы абсолютно одинаковые! Но, зная что программы одинаковые, и сравнивая осциллограммы - появляется мысль, что по программе с обычной переменной таки "прошёлся" оптимизатор.

Почему этого не видно на листингах? Возможно потому, что в листингах приведен дизассемблер исходной программы на С, а не итогового машинного кода, который заливается в контроллер. Это только гипотеза, но в контексте приведенной статьи, мне она кажется очень вероятной.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

14 часов назад, Herz сказал:

Но стоит мне переменную-счётчик i объявить обычной, не volatile, как начинаются чудеса.

Не чудеса это. МК всё сделал правильно, просто программа у Вас кривая. Посмотрите сами:

Сначала отправляете 10 слов, после каждого ожидая только освобождения буфера передатчика (каждый новый принятый байт при этом переписывает поверх предыдущий в буфере приёма).

Потом ставите CS=low не дожидаясь завершения передачи (т.е. - не дожидаясь флага RX от последнего слова). В варианте с volatile у Вас там есть задержка перед CS=low, поэтому последнее слово успевает прийти в rx-буфер (переписав предпоследнее) и Вы его удаляете нормально перед CS=low, а в варианте без volatile задержка меньше (а может вообще отсутствовать, так как компилятор вправе вообще удалить цикл for(i=3; i>0; i--)), и чтением rx-буфера перед CS=low удаляется не последнее слово, а предпоследнее из предыдущего цикла. И потом каждым чтением rx-буфера Вы читаете не то что ожидаете, а данные от предыдущей передачи (возможно, а может и текущей - как повезёт в зависимости от задержек, вызываемых всякими ISR).

Так что МК и компилятор тут всё сделали правильно, косяк в программе. Нужно везде использовать RX-флаг регистра статуса прерываний, а не TX-флаг. И всё будет ок. :yes3:

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Для чего же тогда TX-флаг придумали? :smile: Да, Вы всё правильно говорите, проблема была в опоздании на один байт очистки приёмного буфера, в невозможности определить, от какого принятого слова установлен флаг RX: от последнего или предыдущего. Потому флаг RX после сброса тут же устанавливался. Мне так и не пришло в голову, как это можно определить.

Собственно, для этой цели и была вставлена задержка между первой частью инициализации (с CS=high) и второй, чтобы в буфер приёмника переписалось последнее слово.

Увеличение этой задержки путём увеличения i до 5 решило эту проблему. Даже переменную data можно объявлять не- volatile. Хотя это кривое решение, конечно.

Идея была в том, чтобы сократить до минимума время инициализации. А если в первой части тоже проверять RX-флаг, то процедура растягивается примерно вдвое за счёт пауз между пересылками тех десяти байтов.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1 час назад, Herz сказал:

Для чего же тогда TX-флаг придумали? :smile:

Чтоб було, ведь у всех есть. :wink: 

Ну или для DMA.

1 час назад, Herz сказал:

Увеличение этой задержки путём увеличения i до 5 решило эту проблему. Даже переменную data можно объявлять не- volatile. Хотя это кривое решение, конечно.

Это называется "выстрелить себе в ногу". Ибо работать будет до следующей перекомпиляции, когда компилятор чуть поумнеет и решит что цикл можно вообще секвестировать.

1 час назад, Herz сказал:

Идея была в том, чтобы сократить до минимума время инициализации. А если в первой части тоже проверять RX-флаг, то процедура растягивается примерно вдвое за счёт пауз между пересылками тех десяти байтов.

А почему бы не использовать DMA для ускорения? Оно же есть в вашем МК?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

14 minutes ago, jcxz said:

Это называется "выстрелить себе в ногу". Ибо работать будет до следующей перекомпиляции, когда компилятор чуть поумнеет и решит что цикл можно вообще секвестировать.

А почему бы не использовать DMA для ускорения? Оно же есть в вашем МК?

На сейчас я заменил цикл на  __delay_cycles(15); и надеюсь, что компилятор с этим уже ничего делать не станет.

А с DMA я ещё работать не умею, не дорос. Намекните, как это изменит ситуацию? Приёмный буфер будет переписываться в память, минуя регистр R15? Так даже если я сбрасываю флаг RX прямо в регистре:

 UCB0IFG &= ~UCRXIFG;                      // clear RX flag

а не чтением приёмного буфера, занимает это ровно столько же времени.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

19 часов назад, Herz сказал:

А с DMA я ещё работать не умею, не дорос. Намекните, как это изменит ситуацию? Приёмный буфер будет переписываться в память, минуя регистр R15? Так даже если я сбрасываю флаг RX прямо в регистре:


 UCB0IFG &= ~UCRXIFG;                      // clear RX flag

а не чтением приёмного буфера, занимает это ровно столько же времени.

Медленность работы по RX-флагу не из-за выполнения команд процессором, а из-за задержек при передачи данных из сдвигового регистра в буферный и выставления флагов готовности внутри SPI-блока. Имхо. Поэтому сброс RX-флага вместо чтения данных ничего не даст.

А DMA изменит ситуацию в том плане, что отдельно программируется передающий DMA-поток (работающий по флагу TX и делающий N записей в буферный регистр), а отдельно - приёмный DMA-поток (работающий по флагу RX и выполняющий те же N пересылок). И программа ждёт завершения приёмного потока. Таким образом - и задержек между байтами лишних не будет и завершение транзакции будет определяться корректно.

 

PS: Если DMA не хочется, то и Ваш цикл можно "прокачать" до работоспособности и быстрой передачи:

short c, i, i1;
char dummy;
i1 = i = 10;
do {
  UCB0TXBUF = 255;
  do if ((c = UCB0IFG) & UCRXIFG) {
    dummy = UCB0RXBUF;
    i1--;
  } while (!(c & UCTXIFG));
} while (--i);
for (; --i1 >= 0; dummy = UCB0RXBUF) while (!(UCB0IFG & UCRXIFG));

За отсутствие ошибок - не ручаюсь, так как нет под рукой компилятора с MSP430. Да и типы переменных может не совсем оптимальны - давно не работал с MSP430.

Но смысл думаю ясен. И без всяких непредсказуемых задержек... :wink:

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

О, спасибо, попробую. С ходу смысл не уловил, надо сосредоточиться. :smile:  Это в качестве замены первой части, верно?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

2 часа назад, Herz сказал:

Это в качестве замены первой части, верно?

Да. Того цикла, который выполняется при CS_HIGH.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

18 hours ago, jcxz said:

Но смысл думаю ясен. И без всяких непредсказуемых задержек... :wink:

Что-то я никак постичь не могу. Там со скобками всё правильно? По-моему, нет...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...