zemlemer 0 7 ноября, 2016 Опубликовано 7 ноября, 2016 · Жалоба Добрый день. Вроде не первый раз пишу для STM и вроде по букварю, но нарвался. Есть STM32F405. К нему через SPI2 присоединена флеша на spi. Читаю из порта данные флеши вручную - корректно. Как только читаю по DMA - в приемном буфере нули. Код инициализации порта: // 1. Clock setup: spi port and pins RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE); RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE); RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE); RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1, ENABLE); // 2. Pins setup GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN; // SCK GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; GPIO_Init(GPIOB, &GPIO_InitStructure); // MISO GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; GPIO_Init(GPIOC, &GPIO_InitStructure); // MOSI GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3; GPIO_Init(GPIOC, &GPIO_InitStructure); GPIO_PinAFConfig(GPIOB, GPIO_PinSource10, GPIO_AF_SPI2); // SCK GPIO_PinAFConfig(GPIOC, GPIO_PinSource2, GPIO_AF_SPI2); // MISO GPIO_PinAFConfig(GPIOC, GPIO_PinSource3, GPIO_AF_SPI2); // MOSI // NSS GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_Init(GPIOB, &GPIO_InitStructure); GPIO_SetBits(GPIOB, GPIO_Pin_12); // 3. SPI setup setFlashNssHigh(); SPI_InitTypeDef SPI_InitStructure; SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; SPI_InitStructure.SPI_Mode = SPI_Mode_Master; SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; SPI_InitStructure.SPI_CPOL = SPI_CPOL_High; // SPI_CPOL_Low SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge; //SPI_CPHA_1Edge SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_16; // SPI_BaudRatePrescaler_2 SPI_BaudRatePrescaler_4;// SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; SPI_InitStructure.SPI_CRCPolynomial = 7; SPI_Init(SPI2, &SPI_InitStructure); while(SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET); SPI_Cmd(SPI2, ENABLE); Читаю данные: setTerminalMessage(info, "Reading data"); setFlashNssLow(); spiByteExchange(READ_DATA); // command spiByteExchange(0x00); // address spiByteExchange(0x00); // address spiByteExchange(0x00); // address for(i = 0; i < 20; i++){ rcvByte = spiByteExchange(0x00); setTerminalMessage(info, "Data[%02d] - %02x", i, rcvByte); } setFlashNssHigh(); Получаю FF на выходе, что корректно. Также корректно читается ID flash памяти. Пытаюсь инициализировать DMA DMA_Cmd(DMA1_Stream3, DISABLE); DMA_Cmd(DMA1_Stream4, DISABLE); SPI_I2S_DMACmd(SPI2, SPI_I2S_DMAReq_Rx, DISABLE); SPI_I2S_DMACmd(SPI2, SPI_I2S_DMAReq_Tx, DISABLE); SPI_Cmd(SPI2, DISABLE); DMA_DeInit(DMA1_Stream4); while (DMA_GetCmdStatus(DMA1_Stream4) != DISABLE); DMA_DeInit(DMA1_Stream3); while (DMA_GetCmdStatus(DMA1_Stream3) != DISABLE); memset((void *)gl_rcvFlashBuffer, 0, DMA_BUFF_SZ); memset((void *)gl_trnFlashBuffer, 0, DMA_BUFF_SZ); gl_trnFlashBuffer[0] = READ_DATA; // PAGE_PROGRAM; // 1. DMA Clock RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1, ENABLE); // 2. Interrupt NVIC_InitTypeDef NVIC_InitStructure; NVIC_InitStructure.NVIC_IRQChannel = DMA1_Stream3_IRQn; // Only rx interrupt NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); // 2. DMA Structure // DMA_InitTypeDef DMA_InitStructure; // 2.2. Common 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; DMA_InitStructure.DMA_Priority = DMA_Priority_High; DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; DMA_InitStructure.DMA_Channel = DMA_Channel_0; DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)(&(SPI2->DR)); // 2.3. TX DMA DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)gl_trnFlashBuffer; DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral; DMA_InitStructure.DMA_BufferSize = DMA_BUFF_SZ; DMA_Init(DMA1_Stream4, &DMA_InitStructure); // 2.3. RX DMA DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)gl_rcvFlashBuffer; DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory; DMA_InitStructure.DMA_BufferSize = DMA_BUFF_SZ; DMA_Init(DMA1_Stream3, &DMA_InitStructure); // 2.4. Enabling only rx interrupt DMA_ITConfig(DMA1_Stream3, DMA_IT_TC , ENABLE); DMA_ClearFlag(DMA1_Stream3, DMA_FLAG_TCIF3); DMA_ClearFlag(DMA1_Stream4, DMA_FLAG_TCIF4); DMA_Cmd(DMA1_Stream3, ENABLE); // Enable the DMA SPI RX Stream DMA_Cmd(DMA1_Stream4, ENABLE); // Enable the DMA SPI TX Stream SPI_I2S_DMACmd(SPI2, SPI_I2S_DMAReq_Rx, ENABLE); SPI_I2S_DMACmd(SPI2, SPI_I2S_DMAReq_Tx, ENABLE); setTerminalMessage(info, "Starting"); setFlashNssLow(); gl_FlashDmaOn = true; SPI_Cmd(SPI2, ENABLE); while(true == gl_FlashDmaOn); setTerminalMessage(info, "Done"); setTerminalMessage(info, "DMA read data"); for(i = 0; i < 50; i++){ setTerminalMessage(info, "Data[%02d] - %02x", i, gl_rcvFlashBuffer[i]); } Код прерывания: void DMA1_Stream3_IRQHandler(void) { if(DMA_GetITStatus(DMA1_Stream3, DMA_IT_TCIF3)!= RESET){ DMA_ClearITPendingBit(DMA1_Stream3, DMA_IT_TCIF3); // Clear NSS gl_FlashDmaOn = false; setFlashNssHigh(); } } Буфера объявлены как #define DMA_BUFF_SZ (256 + 4) static uint8_t gl_trnFlashBuffer[DMA_BUFF_SZ]; static uint8_t gl_rcvFlashBuffer[DMA_BUFF_SZ]; volatile bool_t gl_FlashDmaOn = false; По осциллогафу на chip select DMA отрабатывает корректно, в приемном буфере - нули. Есть ли мысли? Может надо как-то выравнивать буфер? Или забыл что? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
rtfcnf 0 8 ноября, 2016 Опубликовано 8 ноября, 2016 (изменено) · Жалоба Попробуйте определить массивы для DMA, с атрибутом __attribute__((aligned(32))) мой массив uint8_t spi1_rx[ADS131_DATA_SIZE] __attribute__((aligned(32))); Изменено 8 ноября, 2016 пользователем rtfcnf Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
zemlemer 0 8 ноября, 2016 Опубликовано 8 ноября, 2016 (изменено) · Жалоба Попробуйте определить массивы для DMA, с атрибутом __attribute__((aligned(32))) мой массив uint8_t spi1_rx[ADS131_DATA_SIZE] __attribute__((aligned(32))); Без изменений, к сожалению. Изменено 8 ноября, 2016 пользователем zemlemer Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
romas2010 1 8 ноября, 2016 Опубликовано 8 ноября, 2016 · Жалоба Без изменений, к сожалению. 1 ) Попробуйте DMA_PeripheralDataSize = DMA_PeripheralDataSize_Long. как пишут в даташите на STM,к регистрам периферии доступ по слову или по двойному слову 2) в DMA установить бит , отвечающий за flow control "dma".CR.PFCTRL=1;(по идее нужно устанавливать,но не факт) ну само собой буфер данных выровнен по 4 байтной границе Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AHTOXA 14 9 ноября, 2016 Опубликовано 9 ноября, 2016 · Жалоба Есть ли мысли? Может надо как-то выравнивать буфер? Или забыл что? Для побайтового доступа надо установить MBURST в 16 (не знаю, чему это соответствует в терминах StdPeriphLib). Вот топик, где я с этим разбирался: ссылка (читать до конца, там есть тонкие моменты с выравниванием). Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
zemlemer 0 10 ноября, 2016 Опубликовано 10 ноября, 2016 · Жалоба Для побайтового доступа надо установить MBURST в 16 (не знаю, чему это соответствует в терминах StdPeriphLib). Вот топик, где я с этим разбирался: ссылка (читать до конца, там есть тонкие моменты с выравниванием). Оказалось все гораздо проще. Если выставить chip select до старта spi, то ловится лишний клок. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AHTOXA 14 10 ноября, 2016 Опубликовано 10 ноября, 2016 · Жалоба И от этого все FF-ы превращаются в нули? :) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Allregia 9 11 ноября, 2016 Опубликовано 11 ноября, 2016 · Жалоба Оказалось все гораздо проще. Если выставить chip select до старта spi, то ловится лишний клок. Так может у SPI неправильно настроена полярность клока? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
k155la3 26 11 ноября, 2016 Опубликовано 11 ноября, 2016 · Жалоба У Вас . . . SPI_I2S_DMACmd(SPI2, SPI_I2S_DMAReq_Rx, ENABLE); SPI_I2S_DMACmd(SPI2, SPI_I2S_DMAReq_Tx, ENABLE); . . . Попробуйте оставить только один канал DMA для проверки - который работает с флеш. Если не секрет, что за флеш используется ? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
zemlemer 0 11 ноября, 2016 Опубликовано 11 ноября, 2016 · Жалоба И от этого все FF-ы превращаются в нули? :) От лишнего клока вначале? Естественно. Вместо команды на чтение идет неизвестно что. У Вас . . . SPI_I2S_DMACmd(SPI2, SPI_I2S_DMAReq_Rx, ENABLE); SPI_I2S_DMACmd(SPI2, SPI_I2S_DMAReq_Tx, ENABLE); . . . Попробуйте оставить только один канал DMA для проверки - который работает с флеш. Если не секрет, что за флеш используется ? M25P80. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться