реклама на сайте
подробности

 
 
> Неверные данные при чтении по SPI через DMA
avg33
сообщение Aug 7 2018, 17:53
Сообщение #1





Группа: Участник
Сообщений: 12
Регистрация: 7-08-18
Пользователь №: 106 564



Всем привет. Пытаюсь прочитать SPI флэшку по DMA. Работаю через USART.
Суть дела в следующем. Допустим, буду читать из флэш по 100 байт. Для этого надо отправить на флэш 105 байт: 5 байт команды и 100 байт фиктивной записи.
Сначала я повесил прием на 2 канал DMA, а запись во флэш реализовал прямо в цикле for:

Код
uint8_t tx_buf[105]; //отсюда пишем во флэш, первые 5 байт - команда
uint8_t rx_buf[105]; //сюда DMA положит прочитанное

void read()
{
    //настройка DMA на прием по 2 каналу
    //по окончании приема 105 байт сработает прерывание IRQ_RX()
    init_DMA_RX();
    UART2_SSR2_RIE = 1; //разрешить прерывание по чтению
    
    //запись 105 байт
    FLASH_CS = FLASH_ON; //установить CS
    for(uint16_t i=0; i<105; ++i)
    {
        while (UART2_SSR2_TDRE == 0); //жду освобождения регистра передачи
        TRD2 = tx_buf[i]; //отправляю байт на флэш
    }
    FLASH_CS = FLASH_OFF; //снять CS
}

void IRQ_RX()
{
    //сюда придем по завершению приема
    //здесь выполняем всякие служебные вещи, чистим флаги и тд
    //и повторное чтение в заисивмости от условия
    if(/*условие*/)
        read();
}


Такой сценарий нормально работает. И при одиночном и при повторном вызове read() в rx_buf лежат валидные данные: 5 байт 0xFF и 100 байт из флэш
Но писать через for долго. Поэтому передачу tx_buf я тоже повесил на канал DMA:
Код
void read()
{
    //настройка DMA на прием по 2 каналу
    //по окончании приема 105 байт сработает прерывание IRQ_RX()
    init_DMA_RX();
    UART2_SSR2_RIE = 1; //разрешить прерыване по чтению
    
    //настройка DMA на передачу по 3 каналу
    //по окончании передачи 105 байт сработает прерывание IRQ_TX()
    init_DMA_TX();
    UART2_SSR2_TIE = 1; //разрешить прерывание по чтению
    
    FLASH_CS = FLASH_ON; //установить CS
}

void IRQ_TX()
{
    //сюда придем по завершению приема
    //здесь выполняем всякие служебные вещи, чистим флаги и тд
    //и снимаем CS
    FLASH_CS = FLASH_OFF;
}

void IRQ_RX()
{
/*...*/
    if(/*условие*/)
        read();
}


И вот этот сценарий дает сбой. Проблема в том, что в какой-то момент устанавливается в 1 флаг переполнения ORE USART`а.
Соответственно, в rx_buf по окончанию приема лежат невалидные данные. Обычно в конце буфера какая-то чушь, иногда в начале или вообще весь буфер бред.
Бывает и такое, что первый вызов read() дает корректные данные, но второй всегда невалидные.
Момент выставления ORE в единицу уловить невозможно, я так и не выявил зависимости. Что я делаю не так, в чем может быть проблема?
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
avg33
сообщение Aug 7 2018, 19:08
Сообщение #2





Группа: Участник
Сообщений: 12
Регистрация: 7-08-18
Пользователь №: 106 564



Arlleex, благодарю за оперативный ответ.

Цитата("Arlleex")
Что за контроллер-то?

F2MC-16FX MB96600 Series

Цитата("Arlleex")
Иначе снимите CS до в процессе передачи последнего слова.

И вправду. А если снять его в IRQ_RX() ? По идее прерывание по приему должно сработать после того, как DMA переложит последний байт в буфер. Или там тоже нюансы со сдвиговым регистром?

Цитата("Arlleex")
Либо Вы не правильно настроили связку сигналов DMA-контроллера с модулем USART по передаче.

По передаче или приему? Или и то и другое?) Я просто указал DMA сколько и откуда писать, куда читать, по каким перываниям срабатывать. Даже не знаю, где там можно ошибиться
Go to the top of the page
 
+Quote Post
Arlleex
сообщение Aug 7 2018, 19:26
Сообщение #3


Местный
***

Группа: Участник
Сообщений: 492
Регистрация: 12-11-11
Пользователь №: 68 264



Цитата(avg33 @ Aug 7 2018, 22:08) *
F2MC-16FX MB96600 Series

Не работал, но логика периферийных узлов во всех МК, в общем-то не глобально отличается...

Цитата(avg33 @ Aug 7 2018, 22:08) *
И вправду. А если снять его в IRQ_RX()?

Уже теплее. Так и нужно, да.

Цитата(avg33 @ Aug 7 2018, 22:08) *
По передаче или приему? Или и то и другое?) Я просто указал DMA сколько и откуда писать, куда читать, по каким перываниям срабатывать. Даже не знаю, где там можно ошибиться

Ну если прием у Вас работает при передаче "ручками", то, очевидно, исходя от противного - проблема в передаче laughing.gif Хотя не ручаюсь точно - ORE это же флаг переполнения входного буфера (то есть туда пришли данные когда еще предыдущие не считали). Поэкспериментируйте, решение где-то рядом.
Go to the top of the page
 
+Quote Post



Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 20th August 2025 - 05:27
Рейтинг@Mail.ru


Страница сгенерированна за 0.01368 секунд с 7
ELECTRONIX ©2004-2016