|
|
  |
STM32H743 SPI, Не работает |
|
|
|
Jul 21 2018, 12:08
|
Участник

Группа: Участник
Сообщений: 24
Регистрация: 19-07-18
Пользователь №: 106 151

|
В общем не получилось побороть SPI, когда количество кадров данных >1 в одном пакете. Ладно все-равно цель чтобы это все работало в связке с DMA. Буду разбираться и прикручивать теперь DMA.
Сообщение отредактировал MasterElectric - Jul 21 2018, 13:44
|
|
|
|
|
Jul 21 2018, 17:46
|
Участник

Группа: Участник
Сообщений: 24
Регистрация: 19-07-18
Пользователь №: 106 151

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

Группа: Участник
Сообщений: 24
Регистрация: 19-07-18
Пользователь №: 106 151

|
О вы уже успели и ДМА изучить... это олично... намекните кде конкрентее рыть в вашем коде
|
|
|
|
|
Jul 21 2018, 17:58
|

Профессионал
    
Группа: Участник
Сообщений: 1 620
Регистрация: 22-06-07
Из: Санкт-Петербург, Россия
Пользователь №: 28 634

|
Файл 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 - Jul 21 2018, 18:59
|
|
|
|
|
Jul 21 2018, 18:18
|
Участник

Группа: Участник
Сообщений: 24
Регистрация: 19-07-18
Пользователь №: 106 151

|
Genadi Zawidowski Спасибо, буду изучать.
|
|
|
|
|
Jul 22 2018, 06:11
|

Профессионал
    
Группа: Свой
Сообщений: 1 202
Регистрация: 26-08-05
Из: Донецк, ДНР
Пользователь №: 7 980

|
Цитата(MasterElectric @ Jul 21 2018, 20:46)  Почему одного байта? Я пакеты нормально слал. Да не хрень, просто сложно по сравнению со старыми версиями периферии. Я просто постепенно делаю. Для простой инициализации дисплея и рисования точек и по одному достаточно. Попробую блоками картинки в дисплей кидать. Ещё напоролся на какой-то странный баг: я работаю в 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).
--------------------
Чтобы возить такого пассажира, необходим лимузин другого класса. (с) Мария Эдуарда
|
|
|
|
|
Jul 22 2018, 06:46
|

Профессионал
    
Группа: Участник
Сообщений: 1 620
Регистрация: 22-06-07
Из: Санкт-Петербург, Россия
Пользователь №: 28 634

|
Цитата ( SPI_PORT->SR & SPI_SR_RXP != 0 ) Скобками обозначте нужную Вам последовательность операций. Вот так: Код ((SPI_PORT->SR & SPI_SR_RXP) != 0)
Сообщение отредактировал Genadi Zawidowski - Jul 22 2018, 06:48
|
|
|
|
|
Jul 22 2018, 15:19
|
Участник

Группа: Участник
Сообщений: 24
Регистрация: 19-07-18
Пользователь №: 106 151

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

Группа: Участник
Сообщений: 24
Регистрация: 19-07-18
Пользователь №: 106 151

|
Я смотрел Ваш код (частично взял оттуда), вроде бы все как обычно. Мой почти такой же. Если есть возможность попробуйте передать пакет > 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 - Jul 22 2018, 16:17
|
|
|
|
|
Jul 23 2018, 07:01
|
Участник

Группа: Участник
Сообщений: 24
Регистрация: 19-07-18
Пользователь №: 106 151

|
Удалось побороть как всегда благодаря 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 раз... второй пакет вообще не идет, совсем... нет запроса ДМА. Прием по прерыванию. Совсем не ожидал что столь незначительная разница в инициализации дала такой результат.
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|