Jump to content

    
Alex_Golubev

Не могу запустить USART на stm32h743

Recommended Posts

Не могу запустить USART на stm32h743. Нет сигнала на выходе TX

Что сделал:

Скрытый текст

  /*настройка uart + DMA для внешнех блоков*/
  RCC->APB1LENR |= RCC_APB1LENR_USART3EN; // подключаем USART 3 к шине ABP1
  while(!(RCC->APB1LENR & RCC_APB1LENR_USART3EN));// ждем чтобы гарантировано подключился

  SET_BIT(RCC->AHB4ENR, RCC_AHB4ENR_GPIODEN);
  GPIOD->MODER |= 0x2 << GPIO_MODER_MODE8_Pos; // перевод порта на альтернативную функцию в частности USART_TX
  GPIOD->MODER |= 0x2 << GPIO_MODER_MODE9_Pos; // перевод порта на альтернативную функцию в частности USART_RX
  GPIOD->OSPEEDR |= 0x2 << GPIO_OSPEEDR_OSPEED8_Pos; // настройка скорости фронта USART скорость наибольшая
  GPIOD->OSPEEDR |= 0x2 << GPIO_OSPEEDR_OSPEED9_Pos; // настройка скорости фронта USART
  GPIOD->PUPDR &= 0x00 << GPIO_PUPDR_PUPD8_Pos; // отключение подтяжки
  GPIOD->PUPDR &= 0x00 << GPIO_PUPDR_PUPD9_Pos; // отключение подтяжки
  GPIOD->AFR[1] |= 0x7 << GPIO_AFRH_AFSEL8_Pos | 0x7 << GPIO_AFRH_AFSEL9_Pos;  // переключение мультиплексора на альтернативные выводы AF7

  USART3->CR1 &= ~USART_CR1_UE; // отключение USART 3 для настройки
  while(USART3->CR1 & USART_CR1_UE); // проверяем что бит включения USART сброшен
  USART3->CR2 = 0x00;
  /*USART3->CR2 = 0x00 << USART_CR2_ADD_Pos | ~USART_CR2_RTOEN | 0x00 << USART_CR2_ABRMODE_Pos | ~USART_CR2_ABREN | ~USART_CR2_MSBFIRST | ~USART_CR2_DATAINV | \
		  ~USART_CR2_TXINV | ~USART_CR2_RXINV | ~USART_CR2_SWAP | ~USART_CR2_LINEN | 0x00 << USART_CR2_STOP_Pos | ~USART_CR2_CLKEN | ~USART_CR2_CPOL | ~USART_CR2_CPHA | ~USART_CR2_LBCL | ~USART_CR2_LBDIE | \
		  ~USART_CR2_LBDL | 0x00 << USART_CR2_ADDM7_Pos | ~USART_CR2_DIS_NSS | ~USART_CR2_SLVEN; // 1 стоп, младшим байтом вперед, оверсемпл включен на 16 бит.*/
  USART3->CR3 = 0x00 << USART_CR3_TXFTCFG_Pos | 0x00 << USART_CR3_RXFTCFG_Pos /*| USART_CR3_DMAT | USART_CR3_DMAR*/; //
  USART3->PRESC = 0; // предделитель тактовой частоты. Частота на входе 120 МГц
  USART3->BRR = 521; // установка скорости расчетная формула. Хочу скорость 230400
  USART3->CR1 |= USART_CR1_UE; // включаем USART3

  while(1){
  USART3->TDR = 0xa5; // передаем данные в UART
  while(!USART3->ISR & USART_ISR_TC); // На ножке USART_TX сигнала нет.
  }

 

 

Share this post


Link to post
Share on other sites
11 minutes ago, Alex_Golubev said:

GPIOD->MODER |= 0x2 << GPIO_MODER_MODE8_Pos; // перевод порта на альтернативную функцию в частности USART_TX GPIOD->MODER |= 0x2 << GPIO_MODER_MODE9_Pos; // перевод порта на альтернативную функцию в частности USART_RX

А вы уверены, что MODER содержал нули по указанной позиции? Если там было, например 0x01b, то двоечки уже не будет.

 

13 minutes ago, Alex_Golubev said:

GPIOD->AFR[1] |= 0x7 << GPIO_AFRH_AFSEL8_Pos | 0x7 << GPIO_AFRH_AFSEL9_Pos; // переключение мультиплексора на альтернативные выводы AF7

А где включаете клок для этих пинов?

Share this post


Link to post
Share on other sites
8 минут назад, Alex_Golubev сказал:

Не могу запустить USART на stm32h743. Нет сигнала на выходе TX
Что сделал...

Ну, а разрешение работы приемника и передатчика где? Оно в CR1 должно быть.

Share this post


Link to post
Share on other sites
15 minutes ago, Alex_Golubev said:

USART3->CR1 |= USART_CR1_UE; // включаем USART3

А приёмник и передатчик не включили?

1 minute ago, Arlleex said:

Ну, а разрешение работы приемника и передатчика где? Оно в CR1 должно быть.

Уважаемый @Arlleex опередил)

17 minutes ago, Alex_Golubev said:

SET_BIT(RCC->AHB4ENR, RCC_AHB4ENR_GPIODEN);

А, увидел, что пины включаете. Стиль кодирования у вас разный. Не сразу заметил.

Share this post


Link to post
Share on other sites
11 минут назад, GenaSPB сказал:

Доктора!!!!!!!!!!!!!

А, кстати да - но я туда чего-то не посмотрел даже:this:

7 минут назад, GenaSPB сказал:

Разница между ! и ~ небольшая...

Тем не менее, оптимальнее все-таки через !.
Хотя при оптимизации, возможно, и не важно.

Share this post


Link to post
Share on other sites

Там скорее всего просто забыты скобки: while (!(USART3->ISR & USART_ISR_TC));

 

А вот такое: GPIOD->MODER |= 0x2 << GPIO_MODER_MODE8_Pos;

И такое: GPIOD->OSPEEDR |= 0x2 << GPIO_OSPEEDR_OSPEED8_Pos;

и подобное - признаки типичного быдлокода. Раз делается операция "|=" то предполагается, что предыдущее содержимое регистров может быть !=0, но тогда результат будет ошибочный. А если предыдущее содержимое ==0 то зачем тогда |= ???

Это уже не говоря о том, что нет никакой заботы об атомарности модификации этих регистров. Если в соседней задаче РТОС (или ISR) завтра потребуется сконфигурить другие пины порта из того же регистра - начнутся очередные поиски и костыление багов.  :unknw:

Вроде очевидные вещи, но чайники повторяют и повторяют такое, таская друг у друга такие "шедевры".

 

А здесь: GPIOD->PUPDR &= 0x00 << GPIO_PUPDR_PUPD8_Pos; // отключение подтяжки

(и строкой ниже) решили подтяжки для всего порта сразу отключить. Видимо - чтобы два раза не бегать.  :biggrin:

Фиг с ним что там могут использоваться ещё и другие пины, в другом месте.

 

RCC->APB1LENR |= RCC_APB1LENR_USART3EN; // подключаем USART 3 к шине ABP1

А если не повезёт - то параллельно отключаем тактирование другой периферии. Ежли вдруг в это время другая задача захочет его включить.  :biggrin:

Share this post


Link to post
Share on other sites
24 minutes ago, jcxz said:

Раз делается операция "|=" то предполагается, что предыдущее содержимое регистров может быть !=0, но тогда результат будет ошибочный.

Тут всё правильно, т.к. MODER включает в себя одинаковые группы битов для конфигруцаии пинов. И другие состояние мы трогать не имеем права. Другое дело, что перед такой операцией группу нужно обнулить, и наложить новую маску. Про атомарность операции согласен, сам так делаю. Хотя раньше грешил))

Вот фрагмент из либы управления пинами

            static void setAlternate( const Function func ) {
                TCritSect cs;
                auto &afr = base()->AFR[PinNum / 8];
                afr &= ~AFR_MASK;
                afr |= static_cast<uint32_t>(func) << AFR_SHIFT;
            }
            /* true sets aoutput as logic 1 and false sets it as logic 0*/
            static void set( const bool level ) {
                base()->BSRR = level ? SET_MASK : CLEAR_MASK; // здесь атомарность обеспечена железом
            }
            static void toggle() {
                TCritSect cs;
                base()->ODR ^= SET_MASK;
            }
            static void setModer( const Moder moder ) {
                TCritSect cs;
                base()->MODER &= ~MODER_MASK;
                base()->MODER  |= static_cast<uint8_t>(moder) << MODER_SHIFT;
            }

 

Share this post


Link to post
Share on other sites
9 минут назад, haker_fox сказал:

Тут всё правильно, т.к. MODER включает в себя одинаковые группы битов для конфигруцаии пинов.

А что именно "правильно"? Если до этого был режим 0, станет 2, если был 1 - станет 3. Сомневаюсь, что автор хотел именно такого поведения. Полагаю что он хотел какой-то один определённый режим поставить.

 

9 минут назад, haker_fox сказал:

 


            static void toggle() {
                TCritSect cs;
                base()->ODR ^= SET_MASK;
            }

 

А здесь можно и без критической секции обойтись. Подумайте как.  :wink2:

Если конечно не переключаете один и тот же пин из разных задач.

Share this post


Link to post
Share on other sites
1 час назад, Alex_Golubev сказал:

GPIOD->PUPDR &= 0x00 << GPIO_PUPDR_PUPD8_Pos; // отключение подтяжки

Здесь вы весь регистр обнулили, вместо одного бита.

Бит обнулять так:

GPIOD->PUPDR &= ~(1UL << GPIO_PUPDR_PUPD8_Pos);

Share this post


Link to post
Share on other sites

Поправил код с вашей критикой. USART заработал. 

Добавил DMA ---> USART3. И не смог запустить. 

Скрытый текст

ExternalsBlocks_TX[0] = 0x85;

	RCC->APB1LENR |= RCC_APB1LENR_USART3EN; // подключаем USART 3 к шине ABP1
	while (!(RCC->APB1LENR & RCC_APB1LENR_USART3EN)); // ждем чтобы гарантированно подключилась
	MODIFY_REG(GPIOD->MODER, GPIO_MODER_MODE8, 0x2 << GPIO_MODER_MODE8_Pos); // перевод порта на альтернативную функцию в частности USART_TX
	MODIFY_REG(GPIOD->MODER, GPIO_MODER_MODE9, 0x2 << GPIO_MODER_MODE9_Pos); // перевод порта на альтернативную функцию в частности USART_RX
	MODIFY_REG(GPIOD->OSPEEDR, GPIO_OSPEEDR_OSPEED8,0x2 << GPIO_OSPEEDR_OSPEED8_Pos); // настройка скорости фронта USART скорость наибольшая
	MODIFY_REG(GPIOD->OSPEEDR, GPIO_OSPEEDR_OSPEED9,0x2 << GPIO_OSPEEDR_OSPEED9_Pos); // настройка скорости фронта USART скорость наибольшая
	MODIFY_REG(GPIOD->PUPDR, GPIO_PUPDR_PUPD8, 0x00 << GPIO_PUPDR_PUPD8_Pos); // отключение подтяжки
	MODIFY_REG(GPIOD->PUPDR, GPIO_PUPDR_PUPD9, 0x00 << GPIO_PUPDR_PUPD9_Pos); // отключение подтяжки
	MODIFY_REG(GPIOD->AFR[1], GPIO_AFRH_AFSEL8, 0x7 << GPIO_AFRH_AFSEL8_Pos); // переключение на альтернативный режим работы порта AF7
	MODIFY_REG(GPIOD->AFR[1], GPIO_AFRH_AFSEL9, 0x7 << GPIO_AFRH_AFSEL9_Pos); // переключение на альтернативный режим работы порта AF7

	MODIFY_REG(GPIOD->MODER, GPIO_MODER_MODE10, 0x1 << GPIO_MODER_MODE10_Pos); // перевод порта на выход RE
	MODIFY_REG(GPIOD->OSPEEDR,GPIO_OSPEEDR_OSPEED10,0x2 << GPIO_OSPEEDR_OSPEED10_Pos); // настройка скорости фронта для RE скорость наибольшая
	MODIFY_REG(GPIOD->PUPDR, GPIO_PUPDR_PUPD10, 0x00 << GPIO_PUPDR_PUPD10_Pos); // отключение подтяжки
	SET_BIT(GPIOD->BSRR, GPIO_BSRR_BR10); //установка логического нуля на линии RE

	USART3->CR1 &= ~USART_CR1_UE; // отключение USART 3 для настройки
	while (USART3->CR1 & USART_CR1_UE); // проверяем что бит включения USART3 сброшен
	USART3->CR2 = 0x00;
	USART3->CR3 = USART_CR3_DMAT | USART_CR3_DMAR; // включение DMA
	USART3->PRESC = 0; // предделитель тактовой частоты
	USART3->BRR = 521; // установка скорости расчетная формула 521
	USART3->CR1 |= USART_CR1_TE; // включение передатчика
	USART3->CR1 |= USART_CR1_RE; // включение приемника
	USART3->CR1 |= USART_CR1_UE; // включаем USART3
	while (!(USART3->CR1 & USART_CR1_UE)); // проверяем что бит включения USART3 установлен

	RCC->AHB1ENR |= RCC_AHB1LPENR_DMA1LPEN; // подключаем DMA1 к шине AHB1
	while (!(RCC->AHB1ENR & RCC_AHB1LPENR_DMA1LPEN)); // ждем гарантированого включения
	DMA1_Stream1->CR &= ~DMA_SxCR_EN; // выключаем DMA
	while (DMA1_Stream1->CR & DMA_SxCR_EN); // ждем чтобы гарантировано был отключен DMA
	DMA1_Stream1->CR = DMA_SxCR_MINC | DMA_SxCR_TCIE; // настройка ДМА для USART3 инкремент памяти, включение прерывания по завершению приема
	DMA1_Stream1->NDTR = 1; // количество данных для передачи с USART3 в ОЗУ буфер
	DMA1_Stream1->PAR = (uint32_t) &USART3->RDR; // адрес от куда брать данные
	DMA1_Stream1->M0AR = (uint32_t)&ExternalsBlocks_RX; // указываем адрес масива куда писать
	DMA1_Stream1->CR |= DMA_SxCR_EN; // включаем DMA
	while (!(DMA1_Stream1->CR & DMA_SxCR_EN)); // ждем гарантированого включения

	DMA1_Stream2->CR &= ~DMA_SxCR_EN; // выключаем DMA
	while (DMA1_Stream2->CR & DMA_SxCR_EN); // ждем чтобы гарантировано был отключен DMA
	DMA1_Stream2->CR = DMA_SxCR_MINC | DMA_SxCR_DIR_0 | DMA_SxCR_CIRC; // настройка ДМА для USART3 инкремент памяти, передача из памяти ---> USART3
	DMA1_Stream2->NDTR = 1; // количество данных для передачи с USART3 в ОЗУ буфер
	DMA1_Stream2->PAR = (uint32_t) &USART3->TDR; // адрес от куда брать данные
	DMA1_Stream2->M0AR = (uint32_t)&ExternalsBlocks_TX; // указываем адрес масива куда писать
	DMA1_Stream2->CR |= DMA_SxCR_EN; // включаем DMA
	while (!(DMA1_Stream2->CR & DMA_SxCR_EN)); // ждем гарантированого включения

 

Добавил буферы:

Скрытый текст

__attribute__((section(".dma_buffer")))
 uint8_t ExternalsBlocks_TX[256]; 
__attribute__((section(".dma_buffer")))
 uint8_t ExternalsBlocks_RX[256]; 

 

Определил их в файле flash.id

Скрытый текст

  .dma_buffer : 
  { *(.dma_buffer) 
  } >RAM_D3

 

 

Edited by Alex_Golubev

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.