Easyelectronics.ru

Электроника для всех
Текущее время: 28 фев 2021, 15:50

Часовой пояс: 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 часов


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

Сейчас этот форум просматривают: woroba


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

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

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