ur5cuj 0 31 августа, 2017 Опубликовано 31 августа, 2017 (изменено) · Жалоба Привожу код что и как делаю, вопрос в том, что в прерывание ДМА входит, а вот уже в обработчике прерывания в if не входити ессно нет переключения между массивами, что не так?Надеюсь на конструктивный диалог, заранее спасибо. void DMA2_Stream5_IRQHandler ( void ) { uart2_putcharPoll ( 'I' );//, xNoBlock ); portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE; if ( DMA_GetITStatus ( SPI_DMA_MASTER_Tx_DMA_Stream, DMA_IT_TCIF5 ) == SET ) { uart2_putcharPoll ( 'F' );//, xNoBlock ); // Clear DMA Stream Transfer Complete interrupt pending bit if ( CurrentBufSPI1 == buf1 ) { CurrentBufSPI1 = buf2; uart2_putcharPoll ( '2' );//, xNoBlock ); } if ( CurrentBufSPI1 == buf2 ) { CurrentBufSPI1 = buf1; uart2_putcharPoll ( '1' );//, xNoBlock ); } DMA_Cmd ( SPI_DMA_MASTER_Tx_DMA_Stream, DISABLE ); DMA_ClearITPendingBit ( SPI_DMA_MASTER_Tx_DMA_Stream, DMA_IT_TCIF5 ); } xSemaphoreGiveFromISR ( xSemaphore_spi1, &xHigherPriorityTaskWoken ); xTaskResumeFromISR (&xHandleSPI1); uart2_putcharPoll ( 'E' );//, xNoBlock ); portEND_SWITCHING_ISR ( xHigherPriorityTaskWoken ); } void Task_SPI1 ( void *pvParameters ) { xSemaphoreTake ( xSemaphore_spi1, portMAX_DELAY ); for (;; ) { if ( CurrentBufSPI1 == buf1 ) { ukladkabufTXSPI1 ( Buffer1TX_SPI1 ); DMA_Config ( Buffer1TX_SPI1, indexTX*8 ); } if ( CurrentBufSPI1 == buf2 ) { ukladkabufTXSPI1 ( Buffer2TX_SPI1 ); DMA_Config ( Buffer2TX_SPI1, indexTX*8 ); } vTaskSuspend ( &xHandleSPI1 ); } } void DMA_Config ( uint8_t * Memory0BaseAddr, uint16_t size ) { DMA_InitTypeDef DMA_InitStructure; NVIC_InitTypeDef NVIC_InitStructure; // Сброс настроек DMA каналов DMA_DeInit ( SPI_DMA_MASTER_Tx_DMA_Stream ); RCC_AHB1PeriphClockCmd ( SPI_DMA_MASTER_DMA_CLK, ENABLE ); DMA_DeInit(SPIx_TX_DMA_STREAM); /* Configure DMA Initialization Structure */ DMA_InitStructure.DMA_BufferSize = size; DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable; DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_1QuarterFull; DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single; DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; DMA_InitStructure.DMA_PeripheralBaseAddr =(uint32_t) (&(SPIx->DR)); DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single; DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; DMA_InitStructure.DMA_Priority = DMA_Priority_High; /* Configure TX DMA */ DMA_InitStructure.DMA_Channel = SPIx_TX_DMA_CHANNEL; DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral; DMA_InitStructure.DMA_Memory0BaseAddr =(uint32_t)Memory0BaseAddr; DMA_Init(SPIx_TX_DMA_STREAM, &DMA_InitStructure); // Configure the DMA interrupt priority NVIC_InitStructure.NVIC_IRQChannel = DMAx_Streamx_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init ( &NVIC_InitStructure ); SPI_I2S_ITConfig ( SPIx, SPI_I2S_IT_TXE, ENABLE ); DMA_ClearITPendingBit ( SPI_DMA_MASTER_Tx_DMA_Stream, SPI_DMA_MASTER_Tx_DMA_IT ); DMA_ClearFlag ( SPI_DMA_MASTER_Tx_DMA_Stream, SPI_DMA_MASTER_Tx_DMA_FLAG ); SPI_I2S_DMACmd ( SPI_DMA_MASTER, SPI_I2S_DMAReq_Tx, ENABLE ); DMA_ITConfig ( SPI_DMA_MASTER_Tx_DMA_Stream, DMA_IT_TC, ENABLE ); DMA_Cmd ( SPI_DMA_MASTER_Tx_DMA_Stream, ENABLE ); }[/code] знаю есть режим дабл-буфер в f411, но как его заюзать на SPL? дефайны: #define SPI_DMA_MASTER SPI1 #define SPI_DMA_MASTER_DMA DMA2 #define SPI_DMA_MASTER_DMA_CLK RCC_AHB1Periph_DMA2 #define SPI_DMA_MASTER_Tx_DMA_Stream DMA2_Stream5 #define SPI_DMA_MASTER_Tx_DMA_Channel DMA_Channel_3 #define SPI_DMA_MASTER_Tx_DMA_FLAG DMA_FLAG_TCIF5 #define SPI_DMA_MASTER_Tx_DMA_IT DMA_IT_TCIF5 #define DMAx_Streamx_IRQn DMA2_Stream5_IRQn #define SPIx_DMA DMA2 #define SPIx_DMA_CLK RCC_AHB1Periph_DMA2 #define SPIx_TX_DMA_CHANNEL DMA_Channel_3 #define SPIx_TX_DMA_STREAM DMA2_Stream5 #define SPIx_TX_DMA_FLAG_TCIF DMA_FLAG_TCIF5 Изменено 31 августа, 2017 пользователем Volldemar Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AHTOXA 18 31 августа, 2017 Опубликовано 31 августа, 2017 · Жалоба После if ( CurrentBufSPI1 == buf1 ) нужен else. Иначе во втором if буфер переключается обратно. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ur5cuj 0 1 сентября, 2017 Опубликовано 1 сентября, 2017 · Жалоба После if ( CurrentBufSPI1 == buf1 ) нужен else. Иначе во втором if буфер переключается обратно. Спасибо за подсказку, но почему в прерывании не заходит в if?: if ( DMA_GetITStatus ( SPI_DMA_MASTER_Tx_DMA_Stream, DMA_IT_TCIF5 ) == SET ) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AHTOXA 18 1 сентября, 2017 Опубликовано 1 сентября, 2017 · Жалоба #define SPI_DMA_MASTER_Tx_DMA_Channel DMA_Channel_3 #define SPI_DMA_MASTER_Tx_DMA_FLAG DMA_FLAG_TCIF5 Вы запусакете третий канал, а проверяете почему-то пятый. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 143 1 сентября, 2017 Опубликовано 1 сентября, 2017 · Жалоба Вы запусакете третий канал, а проверяете почему-то пятый.Не, у них в старших "канал" - это номер входа запроса. Запускается пятый поток с запросами по третьему каналу: #define SPI_DMA_MASTER_Tx_DMA_Stream DMA2_Stream5 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AHTOXA 18 1 сентября, 2017 Опубликовано 1 сентября, 2017 · Жалоба А, точно, забыл уже, что там ещё один уровень добавили. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
adnega 11 1 сентября, 2017 Опубликовано 1 сентября, 2017 · Жалоба Надеюсь на конструктивный диалог, заранее спасибо. Похоже на FreeRTOS. Там с приоритетами прерываний нужно быть очень аккуратным. Не все функции можно использовать в обработчике. Мне кажется, что причиной может быть строчка uart2_putcharPoll ( 'I' );//, xNoBlock ); Для DMA у вас задан самый высокий приоритет // Configure the DMA interrupt priority NVIC_InitStructure.NVIC_IRQChannel = DMAx_Streamx_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init ( &NVIC_InitStructure ); - вы не имеете право пользоваться функциями ОС внутри такого обработчика. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ur5cuj 0 4 сентября, 2017 Опубликовано 4 сентября, 2017 (изменено) · Жалоба Похоже на FreeRTOS. Это и есть оно. Там с приоритетами прерываний нужно быть очень аккуратным. Не все функции можно использовать в обработчике. Мне кажется, что причиной может быть строчка uart2_putcharPoll ( 'I' );//, xNoBlock ); Для DMA у вас задан самый высокий приоритет // Configure the DMA interrupt priority NVIC_InitStructure.NVIC_IRQChannel = DMAx_Streamx_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init ( &NVIC_InitStructure ); - вы не имеете право пользоваться функциями ОС внутри такого обработчика. - вы не имеете право пользоваться функциями ОС внутри такого обработчика. я об этом в курсе, но ф-ция uart2_putcharPoll не содержит вызовов ф-ций ОС: usart_err_t uart2_putcharPoll ( uint8_t byte ) { USART_SendData ( USART2, byte ); while ( USART_GetFlagStatus( USART2, USART_FLAG_TC ) == RESET ); return USART_OK; }/* end uart2_putchar */ Изменено 4 сентября, 2017 пользователем Volldemar Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
adnega 11 4 сентября, 2017 Опубликовано 4 сентября, 2017 · Жалоба я об этом в курсе А как же это в конце обработчика? xSemaphoreGiveFromISR ( xSemaphore_spi1, &xHigherPriorityTaskWoken ); xTaskResumeFromISR (&xHandleSPI1); uart2_putcharPoll ( 'E' );//, xNoBlock ); portEND_SWITCHING_ISR ( xHigherPriorityTaskWoken ); Попробуйте приоритет сделать ниже системного. Насчет while ( USART_GetFlagStatus( USART2, USART_FLAG_TC ) == RESET ); - это не лучшее решение ждать отправки в самом высокоуровневом прерывании. Лучше сделать для uart очередь и в idle ее опустошать. Если вам для отладки, то лучше светодиод на выводе МК. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ur5cuj 0 4 сентября, 2017 Опубликовано 4 сентября, 2017 · Жалоба А как же это в конце обработчика? xSemaphoreGiveFromISR ( xSemaphore_spi1, &xHigherPriorityTaskWoken ); xTaskResumeFromISR (&xHandleSPI1); uart2_putcharPoll ( 'E' );//, xNoBlock ); portEND_SWITCHING_ISR ( xHigherPriorityTaskWoken ); ничего криминального не вижу, увы :( если что то есть, подскажите плиз. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
adnega 11 4 сентября, 2017 Опубликовано 4 сентября, 2017 · Жалоба ничего криминального не вижу, увы :( если что то есть, подскажите плиз. Вы используете функции ОС в прерывании, у которого приоритет выше системного. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ur5cuj 0 4 сентября, 2017 Опубликовано 4 сентября, 2017 · Жалоба Вы используете функции ОС в прерывании, у которого приоритет выше системного. какой уровень посоветуете установить? Имею ввиду конкретную цифру. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
adnega 11 4 сентября, 2017 Опубликовано 4 сентября, 2017 · Жалоба какой уровень посоветуете установить? Имею ввиду конкретную цифру. О, я рекомендую почитать. Очень хорошие статьи у Курница. На странице 40 раздел "Вложенность прерываний" и далее. Еще обсуждали тут. Есть на английском тут. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ur5cuj 0 4 сентября, 2017 Опубликовано 4 сентября, 2017 · Жалоба О, я рекомендую почитать. Очень хорошие статьи у Курница. На странице 40 раздел "Вложенность прерываний" и далее. Еще обсуждали тут. Есть на английском тут. По Вашим ссылкам на обсуждение: - из Вашего кода: NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = (uint8_t)(configKERNEL_INTERRUPT_PRIORITY >> 4); это обкатано? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Hold 0 4 сентября, 2017 Опубликовано 4 сентября, 2017 (изменено) · Жалоба У себя делал так, на STM32F4x9: #include "globals.h" #include "SPIRoutines.h" static uint8_t RxDummy; static uint8_t TxDummy; static xSemaphoreHandle MEM_Complete; static xSemaphoreHandle SpiBusy; static DMA_InitTypeDef DMA_InitStructure; _SPI_CS_PIN_STRUCT CS_DevList[] = { { "FLASH", GPIO_Pin_14, GPIOC, RCC_AHB1Periph_GPIOC }, { "FRAM 1", GPIO_Pin_3, GPIOE, RCC_AHB1Periph_GPIOE }, { "FRAM 2", GPIO_Pin_4, GPIOE, RCC_AHB1Periph_GPIOE }, { "FRAM 3", GPIO_Pin_13, GPIOC, RCC_AHB1Periph_GPIOC }, { "FRAM 4", GPIO_Pin_8, GPIOI, RCC_AHB1Periph_GPIOI }, }; void InitSPI4(void) { GPIO_InitTypeDef GPIO_InitStructure; SPI_InitTypeDef SPI_InitStructure; NVIC_InitTypeDef NVIC_InitStructure; // Тактирование модуля SPI, портов, DMA RCC_AHB1PeriphClockCmd(SPI_EXT_MEM_GPIO_RCC, ENABLE); RCC_APB2PeriphClockCmd(SPI_EXT_MEM_RCC, ENABLE); RCC_AHB1PeriphClockCmd(SPI_EXT_MEM_DMA_CLK, ENABLE); //Настроим порты GPIO_InitStructure.GPIO_Pin = SPI_EXT_MEM_SCK | SPI_EXT_MEM_MOSI | SPI_EXT_MEM_MISO; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_Init(SPI_EXT_MEM_GPIO, &GPIO_InitStructure); GPIO_PinAFConfig(SPI_EXT_MEM_GPIO ,GPIO_PinSource2 ,GPIO_AF_SPI4 ); GPIO_PinAFConfig(SPI_EXT_MEM_GPIO ,GPIO_PinSource5 ,GPIO_AF_SPI4 ); GPIO_PinAFConfig(SPI_EXT_MEM_GPIO ,GPIO_PinSource6 ,GPIO_AF_SPI4 ); GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; for (uint8_t i = 0; i < SPI_EXT_MEM_NUM_CS; i++) { RCC_AHB1PeriphClockCmd( CS_DevList[i].Rcc, ENABLE); GPIO_InitStructure.GPIO_Pin = CS_DevList[i].Pin; GPIO_Init(CS_DevList[i].Port, &GPIO_InitStructure); SPI_CS_High((List_CsDev)i); } //Заполняем структуру с параметрами SPI модуля SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; // полный дуплекс SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; // передаем по 8 бит SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low; // Полярность и SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge; // фаза тактового сигнала SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; // Управлять состоянием сигнала NSS программно SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4; // Предделитель SCK (APB2 90 MHz) SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; // Первым отправляется старший бит SPI_InitStructure.SPI_Mode = SPI_Mode_Master; // Режим - мастер SPI_Init(SPI_EXT_MEM, &SPI_InitStructure); // Настраиваем SPI1 // SPI_Cmd(SPI_EXT_MEM, ENABLE); // Включаем модуль SPI_NSSInternalSoftwareConfig(SPI_EXT_MEM, SPI_NSSInternalSoft_Set); SPI_I2S_DMACmd(SPI_EXT_MEM, SPI_I2S_DMAReq_Rx, ENABLE); SPI_I2S_DMACmd(SPI_EXT_MEM, SPI_I2S_DMAReq_Tx, ENABLE); //настройка прерываний DMA //Прерывания только по Rx, когда байт уже ушел NVIC_InitStructure.NVIC_IRQChannel = SPI_EXT_MEM_Rx_DMA_IRQ; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = SPI_EXT_MEM_Rx_DMA_IRQ_PRIORITY; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); DMA_StructInit(&DMA_InitStructure); DMA_InitStructure.DMA_Channel = SPI_EXT_MEM_DMA_Channel; DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&SPI_EXT_MEM->DR; DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; DMA_InitStructure.DMA_Priority = DMA_Priority_High; DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable; DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_1QuarterFull; DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single; DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single; vSemaphoreCreateBinary(MEM_Complete); xSemaphoreTake(MEM_Complete, 0); SpiBusy = xSemaphoreCreateMutex(); } void SPI4_SetDMA_RxTx(uint32_t MemAddr ,uint16_t NumByte ,List_DMA_Mode Mode ) { xSemaphoreTake(SpiBusy, portMAX_DELAY); DMA_DeInit(SPI_EXT_MEM_Rx_DMA_Stream); DMA_DeInit(SPI_EXT_MEM_Tx_DMA_Stream); DMA_InitStructure.DMA_BufferSize = NumByte; if (Mode == DMA_MODE_TX || Mode == DMA_MODE_TX_FILL) { DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&RxDummy; //при записи пишем в переменную-пустышку без инкремента DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Disable; DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory; DMA_Init(SPI_EXT_MEM_Rx_DMA_Stream, &DMA_InitStructure); DMA_InitStructure.DMA_Memory0BaseAddr = MemAddr; if (Mode == DMA_MODE_TX) DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; else DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Disable; DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral; DMA_Init(SPI_EXT_MEM_Tx_DMA_Stream, &DMA_InitStructure); } else { DMA_InitStructure.DMA_Memory0BaseAddr = MemAddr; DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory; DMA_Init(SPI_EXT_MEM_Rx_DMA_Stream, &DMA_InitStructure); DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&TxDummy; //при чтении передаем переменную-пустышку без инкремента DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Disable; DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral; DMA_Init(SPI_EXT_MEM_Tx_DMA_Stream, &DMA_InitStructure); } DMA_ITConfig(SPI_EXT_MEM_Rx_DMA_Stream, DMA_IT_TC, ENABLE); DMA_Cmd(SPI_EXT_MEM_Rx_DMA_Stream, ENABLE); // Запускаем на прием DMA_Cmd(SPI_EXT_MEM_Tx_DMA_Stream, ENABLE); // Запускаем на передачу SPI_Cmd(SPI_EXT_MEM, ENABLE); // Включаем модуль (для одновременного старта RX/TX) xSemaphoreTake(MEM_Complete, portMAX_DELAY); // Ждем пока отработает while (DMA_GetCmdStatus(SPI_EXT_MEM_Tx_DMA_Stream) != DISABLE); while (DMA_GetCmdStatus(SPI_EXT_MEM_Rx_DMA_Stream) != DISABLE); SPI_Cmd(SPI_EXT_MEM, DISABLE); // Выключаем модуль xSemaphoreGive(SpiBusy); } //Завершение чтения(а оно возникает только после полной записи) DMA void DMA2_Stream0_IRQHandler(void) { static portBASE_TYPE xHigherPriorityTaskWoken; xHigherPriorityTaskWoken = pdFALSE; if (DMA_GetITStatus(SPI_EXT_MEM_Rx_DMA_Stream ,SPI_EXT_MEM_Rx_DMA_FLAG )) { DMA_ClearITPendingBit(SPI_EXT_MEM_Rx_DMA_Stream, SPI_EXT_MEM_Rx_DMA_FLAG); xSemaphoreGiveFromISR(MEM_Complete ,&xHigherPriorityTaskWoken ); if( xHigherPriorityTaskWoken == pdTRUE ) taskYIELD(); } } void SPI_CS_Low(List_CsDev Device) { asm("nop"); GPIO_ResetBits(CS_DevList[Device].Port, CS_DevList[Device].Pin); asm("nop"); } void SPI_CS_High(List_CsDev Device) { asm("nop"); GPIO_SetBits(CS_DevList[Device].Port, CS_DevList[Device].Pin); asm("nop"); } #ifndef SPI_ROUTINES_H #define SPI_ROUTINES_H #define SPI_EXT_MEM SPI4 #define SPI_EXT_MEM_RCC RCC_APB2Periph_SPI4 #define SPI_EXT_MEM_GPIO GPIOE #define SPI_EXT_MEM_GPIO_RCC RCC_AHB1Periph_GPIOE #define SPI_EXT_MEM_SCK GPIO_Pin_2 #define SPI_EXT_MEM_MISO GPIO_Pin_5 #define SPI_EXT_MEM_MOSI GPIO_Pin_6 #define SPI_EXT_MEM_NUM_CS 5 #define SPI_EXT_MEM_DMA_CLK RCC_AHB1Periph_DMA2 #define SPI_EXT_MEM_DMA_Channel DMA_Channel_4 #define SPI_EXT_MEM_Rx_DMA_Stream DMA2_Stream0 #define SPI_EXT_MEM_Tx_DMA_Stream DMA2_Stream1 #define SPI_EXT_MEM_Rx_DMA_IRQ DMA2_Stream0_IRQn #define SPI_EXT_MEM_Rx_DMA_FLAG DMA_IT_TCIF0 #define SPI_EXT_MEM_Rx_DMA_IRQ_PRIORITY 15 typedef enum { EXT_MEM_FLASH = 0, // AT45DB641E EXT_MEM_FRAM1, EXT_MEM_FRAM2, EXT_MEM_FRAM3, EXT_MEM_FRAM4, }List_CsDev; typedef struct { const uint8_t *Str; uint16_t Pin; GPIO_TypeDef *Port; uint32_t Rcc; } _SPI_CS_PIN_STRUCT; typedef enum { DMA_MODE_RX=1, // читаем данные DMA_MODE_TX, // пишем данные DMA_MODE_TX_FILL, // Заполняем одним и тем же }List_DMA_Mode; extern void InitSPI4(void); extern void SPI_CS_Low(List_CsDev Device); extern void SPI_CS_High(List_CsDev Device); extern void SPI4_SetDMA_RxTx(uint32_t MemAddr ,uint16_t NumByte ,List_DMA_Mode Mode ); extern _SPI_CS_PIN_STRUCT CS_DevList[]; #endif Для чтения/записи в нужный CS необходимо лишь: SPI_CS_Low(EXT_MEM_FLASH); SPI4_SetDMA_RxTx((uint32_t)TxBuf, 1,DMA_MODE_TX); SPI4_SetDMA_RxTx((uint32_t)RxBuf, 9,DMA_MODE_RX); SPI_CS_High(EXT_MEM_FLASH); Естественно вызывать только из тасков FreeRTOS, т.е. используется ожидания завершения передачи через семафор. В вашем прерывании нет необходимости вызывать: DMA_Cmd ( SPI_DMA_MASTER_Tx_DMA_Stream, DISABLE ); Т.к. Stream автоматически выключается после окончания передачи, что явно указано в ДШ: UPD: И еще важная мелочь - т.к. вы используете только Tx на DMA, фактически, прерывание не гарантирует того, что все данные вышли с MOSI-линии. Это значит лишь то, что DMA закончил работу, и переправил все байты в регистр данных SPI, который буферизирован. Для однозначного отслеживания окончания передачи следует дожидаться флага SPI_SR_BSY в статусном регистре SPI. Это не особо заметно на маленьких скоростях, но на больших это вылазит тут же. Помню долго голову ломал, почему , при снятии CS после срабатывания DMA прерывания по Tx, фактически на осциллографе CS снимался посередине последнего байта, естественно данные портились. Изменено 4 сентября, 2017 пользователем Hold Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться