Easyelectronics.ru

Электроника для всех
Текущее время: 24 окт 2020, 20:42

Часовой пояс: UTC + 5 часов



JLCPCB – Прототипы печатных плат за $2/5шт. два слоя. $5/5шт. четыре слоя
Крупнейший производитель печатных плат и прототипов. Более 600000 клиентов и свыше 10000 заказов в день!
Получите скидку на почтовую отправку при первом заказе в JLCPCB!

Начать новую тему Ответить на тему  [ Сообщений: 3 ] 
Автор Сообщение
 Заголовок сообщения: Заставить работать SPI+DMA для SD Card на STM32CL 105
СообщениеДобавлено: 25 сен 2012, 11:50 
Только пришел
Аватара пользователя

Зарегистрирован: 25 сен 2012, 11:32
Сообщения: 22
Откуда: Новосибирск
Добрый день, уважаемые коллеги!

Пробую реализовать работу с SD картой через SPI+DMA.

Прочитал статью http://mycontroller.ru/stm32-sd-card-in ... i-pamyati/
, всё прекрасно работает,
но добавить работу по DMA не получается.

Использую STM32 105 CL,
SPI2 DMA1_Channel4 и DMA1_Channel5
Буду крайне благодарен за помощь.

Удалось заставить отправлять биты на запись ( см. ф-цию SD_WriteSector ).
На чтение молчит.

Конфигурация SPI:

SPI2->CR2 = 0x0007; // Bit 0 RXDMAEN, Bit 1 TXDMAEN, Bit 2 SSOE: SS output enable.
SPI2->CR1 = 0x037C; //fPCLK/самый медленный
//SPI2->CR1 = 0x0364; //fPCLK/32
//SPI2->CR1 = 0x036C; //fPCLK/64


Конфигурация DMA:

void DMA_SPI_RX_init(unsigned int perif_addr, unsigned int mem_addr, unsigned int cnt_transfer) // канал совпадает с TX - USART1
{
if ((RCC->AHBENR & RCC_AHBENR_DMA1EN) != RCC_AHBENR_DMA1EN) // Если тактов нет
RCC->AHBENR |=RCC_AHBENR_DMA1EN; // подаю такты на DMA1

for(volatile int i=0; i<100; i++); //пауза для включения железки

DMA1_Channel4->CPAR = perif_addr; // адрес периферии
DMA1_Channel4->CMAR = mem_addr; // адрес памяти

DMA1_Channel4->CNDTR = cnt_transfer; // количество передач данных, при циклической передаче счетчик после достижения 0 будет обновляться

//DMA1_Channel1->CCR =0;

DMA1_Channel4->CCR = 0
| (1 * DMA_CCR1_EN ) // Channel enable // включаем канал DMA
| (0 * DMA_CCR1_TCIE ) // Transfer complete interrupt enable
| (0 * DMA_CCR1_HTIE ) // Half Transfer interrupt enable
| (0 * DMA_CCR1_TEIE ) // Transfer error interrupt enable
| (0 * DMA_CCR1_DIR ) // Data transfer direction: Peripheral->Memory // Из переферии в память
| (0 * DMA_CCR1_CIRC ) // Circular mode // циклическая передача
| (0 * DMA_CCR1_PINC ) // Peripheral increment mode
| (1 * DMA_CCR1_MINC ) // Memory increment mode //инкремент указателя памяти.
| (0 * DMA_CCR1_PSIZE_1 ) //10 - 32Bit //01: 16-bits переферия; DMA_CCR1_PSIZE_0=0x0100 // 0x0 -- 8 bit
| (0 * DMA_CCR1_MSIZE_1 ) //10 - 32Bit //01: 16-bits; // 0x0 -- 8 bit
| (0 * DMA_CCR1_PL ) // Channel Priority level: lowest, conversion frequency is low enough
| (0 * DMA_CCR1_MEM2MEM ) // Memory to memory mode disabled
;
}

void DMA_SPI_TX_init(unsigned int perif_addr, unsigned int mem_addr, unsigned int cnt_transfer) // канал совпадает с RX - USART1
{
if ((RCC->AHBENR & RCC_AHBENR_DMA1EN) != RCC_AHBENR_DMA1EN) // Если тактов нет
RCC->AHBENR |=RCC_AHBENR_DMA1EN; // подаю такты на DMA1

for(volatile int i=0; i<100; i++); //пауза для включения железки

DMA1_Channel5->CPAR = perif_addr; // адрес периферии
DMA1_Channel5->CMAR = mem_addr; // адрес памяти

DMA1_Channel5->CNDTR = cnt_transfer; // количество передач данных, при циклической передаче счетчик после достижения 0 будет обновляться

DMA1_Channel5->CCR = 0
| (1 * DMA_CCR1_EN ) // Channel enable // включаем канал DMA
| (0 * DMA_CCR1_TCIE ) // Transfer complete interrupt enable
| (0 * DMA_CCR1_HTIE ) // Half Transfer interrupt enable
| (0 * DMA_CCR1_TEIE ) // Transfer error interrupt enable
| (1 * DMA_CCR1_DIR ) // Data transfer direction: Peripheral<-Memory // Из памяти в переферию
| (0 * DMA_CCR1_CIRC ) // Circular mode // циклическая передача
| (0 * DMA_CCR1_PINC ) // Peripheral increment mode
| (1 * DMA_CCR1_MINC ) // Memory increment mode //инкремент указателя памяти.
| (0 * DMA_CCR1_PSIZE_1 ) //10 - 32Bit //01: 16-bits переферия; DMA_CCR1_PSIZE_0=0x0100 // 0x0 -- 8 bit
| (0 * DMA_CCR1_MSIZE_1 ) //10 - 32Bit //01: 16-bits; // 0x0 -- 8 bit
| (0 * DMA_CCR1_PL ) // Channel Priority level: lowest, conversion frequency is low enough
| (0 * DMA_CCR1_MEM2MEM ) // Memory to memory mode disabled
;
}

Карту инициализирую ф-цией SD_init() .

Вот мои модификации в коде на приём/передачу:
//********************************************************************************************
//function чтение выбранного сектора SD //
//аrguments номер сектора,указатель на буфер размером 512 байт //
//return 0 - сектор прочитан успешно //
//********************************************************************************************
uint8_t SD_ReadSector(uint32_t BlockNumb, uint8_t *buff)
{
uint16_t i=0;

//послать команду "чтение одного блока" с указанием его номера
if(SD_sendCommand(READ_SINGLE_BLOCK, BlockNumb)) return 1;
CS_ENABLE;
//ожидание маркера данных
while(spi_read() != 0xfe)
if(i++ > 0xfffe) {CS_DISABLE; return 1;}


LED_Status2_ON(); // Для иснхронизации осциллографа (ждущий режим)
//чтение 512 байт выбранного сектора
//for(i=0; i<512; i++) *buff++ = spi_read();

DMA_SPI_RX_init( (unsigned int)&(SPI2->DR), (unsigned int) &buff[0], 512);

//for(int i=0; i<512; i++)
SPI2->SR &= ~0x01; // Молчит как партизан, пробовал и нулём и единицей задавать.
/*In reception, a DMA request is issued each time RXNE is set to 1. The DMA then reads
the SPI_DR register (this clears the RXNE flag). */
/*Bit 0 RXNE: Receive buffer not empty
0: Rx buffer empty
1: Rx buffer not empty*/

Delay2_TIM1(500, TIM1_MILLI_SEC_DIV); //!!! Ахтунг!!! работа с ДМА предполагает другую логику (без блокировки).

LED_Status2_OFF(); // Для иснхронизации осциллографа (ждущий режим)


// spi_read();
// spi_read();
// spi_read();


CS_DISABLE;

return 0;
}


//********************************************************************************************
//function запись выбранного сектора SD //
//аrguments номер сектора, указатель на данные для записи //
//return 0 - сектор записан успешно //
//********************************************************************************************
uint8_t SD_WriteSector(uint32_t BlockNumb,uint8_t *buff)
{
uint8_t response;
uint16_t i,wait=0;

//послать команду "запись одного блока" с указанием его номера
if( SD_sendCommand(WRITE_SINGLE_BLOCK, BlockNumb)) return 1;

CS_ENABLE;
spi_send(0xfe);

//записать буфер сектора в карту
LED_Status1_ON(); // Для иснхронизации осциллографа (ждущий режим)
// for(i=0; i<512; i++) spi_send(*buff++);

DMA_SPI_TX_init( (unsigned int) &(SPI2->DR), (unsigned int) &buff[0], 512);

SPI2->SR |= 0x02; /* In transmission, a DMA request is issued each time TXE is set to 1. The DMA then
writes to the SPI_DR register (this clears the TXE flag).*/

while( ( (SPI2->SR) & 0x80) > 0) ; // Проверка BSY
/* The software must first wait until TXE=1 and
then until BSY=0.*/

//!!! Ахтунг!!! работа с ДМА предполагает другую логику (без блокировки).

LED_Status1_OFF();

// Дальше не понятные мне действия...
// spi_send(0xff); //читаем 2 байта CRC без его проверки
// spi_send(0xff);
//
// response = spi_read();
//
// if( (response & 0x1f) != 0x05) //если ошибка при приеме данных картой
// { CS_DISABLE; return 1; }
//
// //ожидаем окончание записи блока данных
// while(!spi_read()) //пока карта занята,она выдает ноль
// if(wait++ > 0xfffe){CS_DISABLE; return 1;}
//
// CS_DISABLE;
// spi_send(0xff);
// CS_ENABLE;
//
// while(!spi_read()) //пока карта занята,она выдает ноль
// if(wait++ > 0xfffe){CS_DISABLE; return 1;}
// CS_DISABLE;

return 0;
}

По выходу из SD_ReadSector значение SPI2->SR = 0x02

Спасибо!


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Заставить работать SPI+DMA для SD Card на STM32CL 105
СообщениеДобавлено: 27 сен 2012, 09:24 
Только пришел
Аватара пользователя

Зарегистрирован: 25 сен 2012, 11:32
Сообщения: 22
Откуда: Новосибирск
Насколько я понял, библиотечные ф-ции (stm32f10x_spi) мне помочь тоже не могут...
Возможно, у кого-то есть готовый пример SPI по DMA?


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Заставить работать SPI+DMA для SD Card на STM32CL 105
СообщениеДобавлено: 27 сен 2012, 10:10 
Только пришел
Аватара пользователя

Зарегистрирован: 25 сен 2012, 11:32
Сообщения: 22
Откуда: Новосибирск
Так, при чтении по DMA нет сигналов на CLK, а при записи они есть. Чем эти коды так существенно отличаются?.. Ума не приложу...


Вернуться к началу
 Профиль  
 
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 3 ] 


Часовой пояс: UTC + 5 часов


Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Перейти:  

Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
Русская поддержка phpBB