STM32 новичку в ARM что к чему

Кто любит RISC в жизни, заходим, не стесняемся.
Ответить
Мудрый кот
Сообщения: 1753
Зарегистрирован: Вт янв 05, 2016 10:14:25
Откуда: поселок Мелеуз

Сообщение Novice user »

Спасибо! Буду разбираться
Реклама
Мучитель микросхем
Сообщения: 418
Зарегистрирован: Вс апр 17, 2011 09:51:26
Откуда: Тула

Сообщение kvn234 »

Здравствуйте.
Изучаю SPI на STM32f030. Не могу понять почему из регистра DR считывается не правильное значение.
Спойлер

Код: Выделить всё

// Сигнатура
void w25qReadManuf(uint8_t *answer)
{
  
  uint8_t status = W25Q_JEDEC_ID;
  uint8_t i;

  W25Q_CS_LO();
  // Передать команду
  while(!LL_SPI_IsActiveFlag_TXE(SPI1));
  LL_SPI_TransmitData8(SPI1, status);
  while(LL_SPI_IsActiveFlag_BSY(SPI1));
  //LL_SPI_ReceiveData8(SPI1);//Очистка буфера

  // Прочитать сигнатуру
  for(i=0 ; i<3 ; i++)
    {
	  LL_SPI_TransmitData8(SPI1,0xFF);
	  while(!LL_SPI_IsActiveFlag_RXNE(SPI1));
      *(answer++) = LL_SPI_ReceiveData8(SPI1);
    }
  W25Q_CS_HI();
}
Вначале выдается команда на чтение сигнатуры, затем чтение 3х байт. Читаются из DR 0xFF, 0xC8 и 0x40.
Должно быть 0xC8, 0x40, 0x16.


Изображение


Если включаю строку LL_SPI_ReceiveData8(SPI1) то информация читается корректно.
Такое впечатление, что в SPI FIFO буфер. В интернете этот нюанс не нашел.
Последний раз редактировалось kvn234 Пт дек 18, 2020 00:45:53, всего редактировалось 1 раз.
Реклама
Поставщик валерьянки для Кота
Сообщения: 2089
Зарегистрирован: Вс июн 19, 2016 09:32:03

Сообщение Reflector »

[uquote="kvn234",url="/forum/viewtopic.php?p=3943137#p3943137"]Такое впечатление, что в SPI FIFO буфер.[/uquote]
Да, что в этом удивительного? Первый раз читается байт принятый при отправке status. По нормальному нужно перед чтением для RX FIFO делать flush:

Код: Выделить всё

while (SPI1->SR & SPI_SR_FRLVL)  SPI1->DR;
А перед этим дождаться окончания передачи, для чего проверки BSY недостаточно, такое работало для SPI без FIFO. Должно быть так:

Код: Выделить всё

while (SPI1->SR & (SPI_SR_FTLVL | SPI_SR_BSY)) {}
В интернете этот нюанс не нашел.
Не нашел в интернете RM на мк?
Мучитель микросхем
Сообщения: 418
Зарегистрирован: Вс апр 17, 2011 09:51:26
Откуда: Тула

Сообщение kvn234 »

[uquote="Reflector",url="/forum/viewtopic.php?p=3943142#p3943142"][/uquote]
Спасибо.

Здесь понятно, буфер очищается.

Код: Выделить всё

while (SPI1->SR & SPI_SR_FRLVL)  SPI1->DR;
Если будем дожидаться окончания передачи

Код: Выделить всё

while (SPI1->SR & (SPI_SR_FTLVL | SPI_SR_BSY)) {}
не попадем ли мы в бесконечный цикл, т.к. не происходит чтения DR ?
Реклама
Эиком - электронные компоненты и радиодетали
Поставщик валерьянки для Кота
Сообщения: 2089
Зарегистрирован: Вс июн 19, 2016 09:32:03

Сообщение Reflector »

[uquote="kvn234",url="/forum/viewtopic.php?p=3943150#p3943150"]не попадем ли мы в бесконечный цикл, т.к. не происходит чтения DR ?[/uquote]
Дождаться нужно окончания передачи, там свое FIFO, чтение DR тут не при чем.
Реклама
Мучитель микросхем
Сообщения: 418
Зарегистрирован: Вс апр 17, 2011 09:51:26
Откуда: Тула

Сообщение kvn234 »

[uquote="Reflector",url="/forum/viewtopic.php?p=3943152#p3943152"][uquote="kvn234",url="/forum/viewtopic.php?p=3943150#p3943150"]не попадем ли мы в бесконечный цикл, т.к. не происходит чтения DR ?[/uquote]
Дождаться нужно окончания передачи, там свое FIFO, чтение DR тут не при чем.[/uquote]

Не увидел, что FIFO TX
Реклама
Мудрый кот
Сообщения: 1753
Зарегистрирован: Вт янв 05, 2016 10:14:25
Откуда: поселок Мелеуз

Сообщение Novice user »

Вот что выяснил-каждые 0,415 сек на выводе ресет STM32F040 у меня появляется лог 0,то есть каждые 0,415 сек STM перезагружается и программа работает сначала,потому толком ничего не выходит,загрузил простой блинк-если поставить переключение порта (на нем стоит резистор 1 ком и светодиод) 0,1 сек то успевает моргать,если поставить переключение на 0,5 сек то светодиод никогда не зажигается(в программе изначально на порту лог ноль,задержка,потом лог единичка)
Потому у меня и грабли с I2C...
Собутыльник Кота
Аватара пользователя
Сообщения: 2567
Зарегистрирован: Вт май 01, 2018 19:44:47

Сообщение VladislavS »

Собака?
Мудрый кот
Сообщения: 1753
Зарегистрирован: Вт янв 05, 2016 10:14:25
Откуда: поселок Мелеуз

Сообщение Novice user »

VladislavS, Вот спасибо! поставил галочку на WDG_SW,мой SSD1306 заработал,вернее инициализация проходит нормально,надо писать оставшиеся функции
Открыл глаза
Аватара пользователя
Сообщения: 56
Зарегистрирован: Вт дек 29, 2015 11:33:49

Сообщение pavell »

Приветствую уважаемые, подскажите причину следующего поведения.
Имеется F0 у которого настраиваю SPI с программным CS (чаще CS управляю "железно"). Сама настройка ничего экзотического не содержит - Master, MOSI, полярности и пр. все по дефолту. И при выполнении следующего кода:

Код: Выделить всё

while(!(SPI2-CR & SPI_SR_TXE));
SPI2->DR      = data;
GPIOB->BSRR  |= GPIO_BSRR_BS_12;
GPIOB->BSRR  |= GPIO_BSRR_BR_12;  
Получаем такую картину:
Изображение

Т.е. получается, что CS дергается в момент передачи данных, а не после. Мне вот этот момент и не понятен неужели это из за разницы в частоте тактирования GPIO и SPI (тут у меня максимально маленький делитель /2)?
Для исправления ситуации я прикостылил ассемблерную вставку с nop'ами, результат стал, каким я его и ожидал изначально:
Изображение

Но мне само решение мне не особо нравится и попутно на сколько поможет исправить ситуацию если использовать DMA?
Поставщик валерьянки для Кота
Сообщения: 2089
Зарегистрирован: Вс июн 19, 2016 09:32:03

Сообщение Reflector »

[uquote="pavell",url="/forum/viewtopic.php?p=3947288#p3947288"]Т.е. получается, что CS дергается в момент передачи данных, а не после. Мне вот этот момент и не понятен неужели это из за разницы в частоте тактирования GPIO и SPI (тут у меня максимально маленький делитель /2)?[/uquote]
Нет, это потому что ты CS дергаешь в момент передачи данных, а не после.
Открыл глаза
Аватара пользователя
Сообщения: 56
Зарегистрирован: Вт дек 29, 2015 11:33:49

Сообщение pavell »

Reflector писал(а):Нет, это потому что ты CS дергаешь в момент передачи данных, а не после.
хм, т.е. перед ногодрыгом надо еще и BUSY флаг у SPI отслеживать?
Ладно попробую, спасибо
Поставщик валерьянки для Кота
Сообщения: 2089
Зарегистрирован: Вс июн 19, 2016 09:32:03

Сообщение Reflector »

[uquote="pavell",url="/forum/viewtopic.php?p=3947334#p3947334"]хм, т.е. перед ногодрыгом надо еще и BUSY флаг у SPI отслеживать?[/uquote]
На предыдущей странице написано как ждать окончания передачи, даже именно для F0.
Открыл глаза
Аватара пользователя
Сообщения: 56
Зарегистрирован: Вт дек 29, 2015 11:33:49

Сообщение pavell »

[uquote="Reflector",url="/forum/viewtopic.php?p=3947336#p3947336"]На предыдущей странице написано как ждать окончания передачи, даже именно для F0.[/uquote]
Спасибо за наставление на путь истинный ))
В моём случае достаточно проверки BUSY флага т.к. данные посылаются одиночные. Ну соответственно это получается чуть быстрее:
- Только busy
Изображение

- Busy и буффер
Изображение

а nop'ы остаются лидерами, ну это так, лирика.
Поставщик валерьянки для Кота
Сообщения: 2089
Зарегистрирован: Вс июн 19, 2016 09:32:03

Сообщение Reflector »

[uquote="pavell",url="/forum/viewtopic.php?p=3947448#p3947448"]В моём случае достаточно проверки BUSY флага т.к. данные посылаются одиночные. Ну соответственно это получается чуть быстрее[/uquote]
Во-первых, правильно писать:

Код: Выделить всё

GPIOB->BSRR = GPIO_BSRR_BS_12;
GPIOB->BSRR = GPIO_BSRR_BR_12; 
Во-вторых, частота судя по всему 8MHz, но даже для нее 3us - это многовато, оптимизация хоть включена?
Открыл глаза
Аватара пользователя
Сообщения: 56
Зарегистрирован: Вт дек 29, 2015 11:33:49

Сообщение pavell »

[uquote="Reflector",url="/forum/viewtopic.php?p=3947454#p3947454"]оптимизация хоть включена?[/uquote]
В SeS cтояла L1 поменял на "L2 speed" ситуация кардинально изменилась - пауза стала одинаковой в обоих случаях 1.6 µs
В очередной раз компилятор оказался умнее меня )
Собутыльник Кота
Аватара пользователя
Сообщения: 2516
Зарегистрирован: Пт июл 12, 2019 22:52:01

Сообщение Eddy_Em »

Не получается завести DMA для изменения содержимого CCR1 таймера TIM1 на STM32F103. На F072 у меня завелось без проблем, здесь же чертовщина какая-то.
Инициализирую:

Код: Выделить всё

    GPIOA->CRH = CRH(15, CNF_PPOUTPUT|MODE_SLOW) | CRH(8, CNF_AFPP | MODE_FAST);
    RCC->APB2ENR |= RCC_APB2ENR_TIM1EN; // enable TIM1 clocking
    TIM1->ARR = 8; // 9 ticks till UEV
    TIM1->PSC = 7;
    // PWM mode 1 (active->inactive)
    TIM1->CCMR1 = TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC1M_1;
    // main output
    TIM1->BDTR = TIM_BDTR_MOE;
    // main PWM output
    TIM1->CCER = TIM_CCER_CC1E;
    NVIC_EnableIRQ(TIM1_UP_IRQn);
    RCC->AHBENR |= RCC_AHBENR_DMA1EN; // DMA1 clocking
    // memsize 8bit, periphsize 16bit, memincr, circular, mem2periph, half & full transfer interrupt
    DMA1_Channel5->CCR = DMA_CCR_PSIZE_0 | DMA_CCR_MINC | DMA_CCR_DIR | DMA_CCR_TCIE;
    DMA1_Channel5->CPAR = (uint32_t)&TIM1->CCR1;
    NVIC_EnableIRQ(DMA1_Channel2_IRQn);
Пытаюсь запустить:

Код: Выделить всё

uint8_t dmabuff[] = {0, 1, 2, 3, 4, 5, 6, 7, 8};
void dma1_channel5_isr(){
    if(DMA1->ISR & DMA_ISR_TCIF5){ // transfer complete - stop
        TIM1->CR1 = 0;
        DMA1_Channel5->CCR &= ~DMA_CCR_EN;
    }
    DMA1->IFCR = DMA_IFCR_CGIF5;
}
...
    TIM1->CR1 = 0; // stop
    TIM1->CCR1 = 1;
    TIM1->DIER = TIM_DIER_UDE; // enable DMA requests
    TIM1->CR1 = TIM_CR1_CEN | TIM_CR1_URS;
    DMA1->IFCR = DMA_IFCR_CGIF5;
    DMA1_Channel5->CNDTR = 9;
    DMA1_Channel5->CMAR = (uint32_t)dmabuff;
    DMA1_Channel5->CCR |= DMA_CCR_EN; // start DMA
И фигвам: вместо того, чтобы один раз выдать 9 импульсов с плавно нарастающей шириной, получаю бесконечную серию импульсов длительностью 111нс с шагом в микросекунду…
Вот чего этой собаке надо?
Linux rules! Windows must die. Здравомыслящий человек добровольно будет пользоваться мастдаем лишь в двух случаях: под дулом автомата или под влиянием анального зонда.
Я на гитхабе, в ЖЖ
Контактная информация:
Поставщик валерьянки для Кота
Сообщения: 2089
Зарегистрирован: Вс июн 19, 2016 09:32:03

Сообщение Reflector »

[uquote="Eddy_Em",url="/forum/viewtopic.php?p=3949377#p3949377"]NVIC_EnableIRQ(DMA1_Channel2_IRQn);[/uquote]
Собутыльник Кота
Аватара пользователя
Сообщения: 2516
Зарегистрирован: Пт июл 12, 2019 22:52:01

Сообщение Eddy_Em »

Ну я и осел… Спасибо!

Добавлено after 47 minutes:
А теперь - самая веселуха: как остановить таймер!

Код: Выделить всё

void tim1_up_isr(){
    TIM1->SR = 0;
    TIM1->CCR1 = 0;
    TIM1->CR1 = 0;
}

void dma1_channel5_isr(){
    if(DMA1->ISR & DMA_ISR_TCIF5){ // transfer complete - stop
        DMA1_Channel5->CCR &= ~DMA_CCR_EN;
        TIM1->DIER = TIM_DIER_UIE;
    }
    DMA1->IFCR = DMA_IFCR_CGIF5;
}
если так сделать, последний импульс обрезается, как будто бы в массиве была единица…
Проблема в том, что

Код: Выделить всё

TIM1->DIER = TIM_DIER_UIE
срабатывает сразу же - и вызывает обработчик прерывания, который останавливает таймер. Т.е. нужно каким-то чудом указать, чтобы прерывание сработало в следующий раз.
Linux rules! Windows must die. Здравомыслящий человек добровольно будет пользоваться мастдаем лишь в двух случаях: под дулом автомата или под влиянием анального зонда.
Я на гитхабе, в ЖЖ
Контактная информация:
Мучитель микросхем
Сообщения: 413
Зарегистрирован: Ср янв 04, 2012 11:57:40
Откуда: Алчевск

Сообщение Sergi »

Добавить в массив 10й элемент и потом не использовать.Не?
Ответить

Вернуться в «ARM»