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

    

В общем не получилось побороть SPI, когда количество кадров данных >1 в одном пакете. Ладно все-равно цель чтобы это все работало в связке с DMA. Буду разбираться и прикручивать теперь DMA.

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

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


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

Я кое-как скрутил отправку одного байта ... SPI дисплей (без ноги MISO) вроде задышал.

На каких-то странных костылях...

Сейчас попробую BME280 прикрутить.. Там обмен двунаправленный.

 

PS. Первые впечатления - хрень полная и тихий ужас ....

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


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

Почему одного байта? Я пакеты нормально слал. Да не хрень, просто сложно по сравнению со старыми версиями периферии.

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


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

Да нормально все работет... перепишите АККУРАТНО из моего проекта по смыслу обмен. И DMA и программный обмен...

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


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

О вы уже успели и ДМА изучить... это олично... намекните кде конкрентее рыть в вашем коде

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


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

Файл hardware.c

hardware_spi_master_initialize

hardware_spi_master_setfreq

 

hardware_spi_connect

 

hardware_spi_b8_p1, hardware_spi_b8_p2, hardware_spi_complete_b8

hardware_spi_master_send_frame

hardware_spi_master_read_frame (на H7 не тестировал)

 

hardware_spi_disconnect

 

Так же оттестирована 16-битная группа функций обмена (кроме чтения по DMA) - hardware_spi_connect_b16 и остальные.

А DMA в обе стороны с I2S и SAI оттестировано - файл hardwarecodecs.c

 

Подключение тактирования у источникам клока это не в этих функциях, но об этом уже тут говорили.

    // RCC Domain 1 Kernel Clock Configuration Register
    // Set per_ck clock output
    RCC->D1CCIPR = (RCC->D1CCIPR & ~ (RCC_D1CCIPR_CKPERSEL)) |
        0 * RCC_D1CCIPR_CKPERSEL_0 |    // 00: hsi_ker_ck clock selected as per_ck clock (default after reset) - 64 MHz - used as PER_CK_FREQ
        0;

    // RCC Domain 2 Kernel Clock Configuration Register
    RCC->D2CCIP1R = (RCC->D2CCIP1R & ~ (RCC_D2CCIP1R_SPI123SEL | RCC_D2CCIP1R_SPI45SEL)) |
        4 * RCC_D2CCIP1R_SPI123SEL_0 |        // per_ck
        3 * RCC_D2CCIP1R_SPI45SEL_0 |        // 011: hsi_ker_ck clock is selected as kernel clock
        0;

Проект делался в том числе для вот этой платы - https://electronix.ru/forum/index.php?act=a...t&id=113464.

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

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


Ссылка на сообщение
Поделиться на другие сайты
Почему одного байта? Я пакеты нормально слал. Да не хрень, просто сложно по сравнению со старыми версиями периферии.

 

Я просто постепенно делаю. Для простой инициализации дисплея и рисования точек и по одному достаточно. Попробую блоками картинки в дисплей кидать.

Ещё напоролся на какой-то странный баг: я работаю в Atollic TrueStudio, когда использовал код MasterElectric

 

        while ( SPI_PORT->SR & SPI_SR_RXP != 0 )
        {
            if ( RxBuffPos < TransLength )
            {
                RxBuff[RxBuffPos++] = *(volatile uint8_t *) &(SPI_PORT->RXDR);
            } // if
            else
                break;
        } // while

 

В цикл вообще не заходило, естетвенно ничего не принимало, хотя под отладкой виден бит SR.RXP==1 и в RXDR правильное принятое значение. Соответственно всё последующее летит к такой-то матери.

 

Переписал так:

        while ( 1 )
        {
                        uint32_t val;
            val = SPI_PORT->SR;
            val &= SPI_SR_RXP;

            if ( val != 0 )
            {
                if ( RxBuffPos < TransLength )
                {
                    r_value = RxBuff[RxBuffPos++] = *(volatile uint8_t *) &(SPI_PORT->RXDR);
                } // if
            } // if
            else
                break;

            if ( RxBuffPos == TransLength )
                break;
        } // while

 

Те же яйца, вид сбоку. Но работает. Никто не натыкался? Оптимизацию проверял, там None (-O0).

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


Ссылка на сообщение
Поделиться на другие сайты
( SPI_PORT->SR & SPI_SR_RXP != 0 )

Скобками обозначте нужную Вам последовательность операций. Вот так:

 ((SPI_PORT->SR & SPI_SR_RXP) != 0)

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

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


Ссылка на сообщение
Поделиться на другие сайты
Genadi Zawidowski , да, чёт я тупанул, спасибо, помогло.

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


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

Ситуация с передачей через ДМА совсем отвратительная. Пробовал 2 варианта первый вариант: когда числом передаваймых байт управляет модуль ДМА т.е. кол-во записываеться в NDTR модуля ДМА, так и в SPI->CR2. В итоге когда число передаваемых байт больше буфера SPI (16 байт) - передает нормально первые 16 байт и все ждет чего-то при этом ДМА стрим вываливает флаг ошибки. И второй вариант когда число передаваемых байт управляет перефирийное устройство (бит PFCTRL в регистре CR ДМА стрим установлен), так передает например все 19 байт, при этом после 16 пошел мусор, и в конце вываливает ошибку передачи (FEIFx: Stream x FIFO error interrupt flag) + к этому в NDTR (0xFFFF - NDTR) переваливает за 1500. В эррате тишина по этому направлению, значит косячу я. У кого есть положительный опыт, поделитесь кодом.

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


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

А чем мой не устраивает-то? SPI по DMA передает нормально...

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


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

Я смотрел Ваш код (частично взял оттуда), вроде бы все как обычно. Мой почти такой же. Если есть возможность попробуйте передать пакет > 16 байт.

 

Мой код:

  //
  RCC->D2CCIP1R = RCC_D2CCIP1R_SPI123SEL_2; // kernel clock выбираем per_ck
  RCC->AHB1ENR |= RCC_AHB1ENR_DMA2EN;
  RCC->AHB2ENR |= RCC_AHB2ENR_D2SRAM1EN | RCC_AHB2ENR_D2SRAM2EN | RCC_AHB2ENR_D2SRAM3EN;
  RCC->AHB4ENR |= RCC_AHB4ENR_GPIOAEN;  // разрешили тактирование GPIO на котором висит SPI
  RCC->APB2ENR |= RCC_APB2ENR_SPI1EN;  // включаем тактирование модуля

  SPI_NRF = new TSPI();
  SPI_NRF->SPI = SPI1;

  // конфигурируем SPI1
  SPI_NRF->SPI->CFG1 = SPI_CFG1_MBR_0 | SPI_CFG1_MBR_2 | SPI_CFG1_DSIZE_0 | SPI_CFG1_DSIZE_1 | SPI_CFG1_DSIZE_2;
  SPI_NRF->SPI->CFG2 = SPI_CFG2_SSOE | SPI_CFG2_MASTER | SPI_CFG2_AFCNTR;
  SPI_NRF->SPI->CR1 |= SPI_CR1_SPE;

  // настраиваем ДМА на передачу SPI1
  DMAMUX1_Channel11->CCR = 38 * DMAMUX_CxCR_DMAREQ_ID_0;    // SPI1_TX
  DMA2_Stream3->PAR = (uint32_t)&SPI_NRF->SPI->TXDR;
  DMA2_Stream3->FCR &= ~ DMA_SxFCR_DMDIS;  // use direct mode
  DMA2_Stream3->CR = DMA_SxCR_MINC | DMA_SxCR_DIR_0 | DMA_SxCR_PFCTRL;

  NVIC_EnableIRQ(SPI1_IRQn);

  // передаем
  a = 10;
  SPI_NRF->SendBuff_DMA(SPI1_TxBuff, SPI1_RxBuff, a);

 

функция передачи:

void TSPI::SendBuff_DMA(uint8_t *aTxBuff, uint8_t *aRxBuff, uint16_t aCnt)
{
  DMA2_Stream3->CR &= ~(DMA_SxCR_EN);

  RxBuffPos = 0;
  TxBuffPos = 0;
  RxBuff = aRxBuff;
  TxBuff = aTxBuff;
  TransLength = aCnt;
  SPI->CR2 = aCnt;
  SPI->CFG1 |= SPI_CFG1_TXDMAEN;

  DMA2->LIFCR = DMA_LIFCR_CFEIF3 | DMA_LIFCR_CDMEIF3 | DMA_LIFCR_CTEIF3 | DMA_LIFCR_CHTIF3 | DMA_LIFCR_CTCIF3;
  DMA2_Stream3->M0AR = (uint32_t)aTxBuff;
  DMA2_Stream3->CR |= DMA_SxCR_EN;

  SPI->CR1 |= SPI_CR1_CSTART;
  SPI->IER |= SPI_IER_EOTIE | SPI_IER_RXPIE;
}

 

Genadi Zawidowski, с пакетом < 16 байт передает нормально, хоть у канала ДМА ошибка. Но если пакеты при работе с неким устройством меньше 16 байт, то смысла в ДМА нет вовсе. А вот если > 16 байт, как я и писал передает 16 и процесс прекращаеться, когда ДМА рулит SPI передает напимер все 19 но после 16 байта мусор, во всех случаях у ДМА ошибка.

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

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


Ссылка на сообщение
Поделиться на другие сайты
Если есть возможность попробуйте передать пакет > 16 байт

Все-таки у меня передается блоками большими чем 16 байт. ПОд рукой сейчас H7 нету.

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


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

Удалось побороть как всегда благодаря RM:

When starting communication using DMA, to prevent DMA channel management raising 
error events, these steps must be followed in order:
1. Enable DMA Rx buffer in the RXDMAEN bit in the SPI_CFG1 register, if DMA Rx is 
used.
2.  Enable DMA requests for Tx and Rx in DMA registers, if the DMA is used.
3.  Enable DMA Tx buffer in the TXDMAEN bit in the SPI_CFG1 register, if DMA Tx is 
used.
4.  Enable the SPI by setting the SPE bit.

Все нормально в двух режимах, когда DMA ведет SPI, и когда SPI ведет DMA, без ошибок и прочего, но... только 1 раз... второй пакет вообще не идет, совсем... нет запроса ДМА. Прием по прерыванию. Совсем не ожидал что столь незначительная разница в инициализации дала такой результат.

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


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

Для публикации сообщений создайте учётную запись или авторизуйтесь

Вы должны быть пользователем, чтобы оставить комментарий

Создать учетную запись

Зарегистрируйте новую учётную запись в нашем сообществе. Это очень просто!

Регистрация нового пользователя

Войти

Уже есть аккаунт? Войти в систему.

Войти