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

Привожу код что и как делаю, вопрос в том, что в прерывание ДМА входит, а вот уже в обработчике прерывания в 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

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

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


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

После

if ( CurrentBufSPI1 == buf1 )

нужен else. Иначе во втором if буфер переключается обратно.

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


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

После

if ( CurrentBufSPI1 == buf1 )

нужен else. Иначе во втором if буфер переключается обратно.

Спасибо за подсказку, но почему в прерывании не заходит в if?:

if ( DMA_GetITStatus ( SPI_DMA_MASTER_Tx_DMA_Stream, DMA_IT_TCIF5 ) == SET )

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


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

#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_Stream    DMA2_Stream5

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


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

Надеюсь на конструктивный диалог, заранее спасибо.

Похоже на 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 );

- вы не имеете право пользоваться функциями ОС внутри такого обработчика.

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


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

Похоже на 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 */

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

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


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

я об этом в курсе

А как же это в конце обработчика?

   xSemaphoreGiveFromISR ( xSemaphore_spi1, &xHigherPriorityTaskWoken );
    xTaskResumeFromISR (&xHandleSPI1);
    uart2_putcharPoll ( 'E' );//, xNoBlock );
    portEND_SWITCHING_ISR ( xHigherPriorityTaskWoken );

Попробуйте приоритет сделать ниже системного.

Насчет

while ( USART_GetFlagStatus( USART2, USART_FLAG_TC ) == RESET );

- это не лучшее решение ждать отправки в самом высокоуровневом прерывании.

Лучше сделать для uart очередь и в idle ее опустошать.

Если вам для отладки, то лучше светодиод на выводе МК.

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


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

А как же это в конце обработчика?

   xSemaphoreGiveFromISR ( xSemaphore_spi1, &xHigherPriorityTaskWoken );
    xTaskResumeFromISR (&xHandleSPI1);
    uart2_putcharPoll ( 'E' );//, xNoBlock );
    portEND_SWITCHING_ISR ( xHigherPriorityTaskWoken );

ничего криминального не вижу, увы :(

если что то есть, подскажите плиз.

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


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

ничего криминального не вижу, увы :(

если что то есть, подскажите плиз.

Вы используете функции ОС в прерывании, у которого приоритет выше системного.

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


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

Вы используете функции ОС в прерывании, у которого приоритет выше системного.

какой уровень посоветуете установить? Имею ввиду конкретную цифру.

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


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

какой уровень посоветуете установить? Имею ввиду конкретную цифру.

О, я рекомендую почитать. Очень хорошие статьи у Курница.

На странице 40 раздел "Вложенность прерываний" и далее. Еще обсуждали тут.

Есть на английском тут.

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


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

О, я рекомендую почитать. Очень хорошие статьи у Курница.

На странице 40 раздел "Вложенность прерываний" и далее. Еще обсуждали тут.

Есть на английском тут.

По Вашим ссылкам на обсуждение:

- из Вашего кода:

NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority  = (uint8_t)(configKERNEL_INTERRUPT_PRIORITY >> 4);

это обкатано?

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


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

У себя делал так, на 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 автоматически выключается после окончания передачи, что явно указано в ДШ:

post-95184-1504521284_thumb.jpg

 

UPD:

И еще важная мелочь - т.к. вы используете только Tx на DMA, фактически, прерывание не гарантирует того, что все данные вышли с MOSI-линии. Это значит лишь то, что DMA закончил работу, и переправил все байты в регистр данных SPI, который буферизирован. Для однозначного отслеживания окончания передачи следует дожидаться флага SPI_SR_BSY в статусном регистре SPI. Это не особо заметно на маленьких скоростях, но на больших это вылазит тут же. Помню долго голову ломал, почему , при снятии CS после срабатывания DMA прерывания по Tx, фактически на осциллографе CS снимался посередине последнего байта, естественно данные портились.

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

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


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

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

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

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

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

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

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

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

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

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