Перейти к содержанию
    

Исключение Hard Fault на Cortex-M3

2 hours ago, EdgeAligned said:

А, да, это от настроек компилятора зависит. Стандарт не задает однозначности. В принципе, переопределения uint32_t для того и придуманы, чтобы была однозначность. 
Ладно, но static тогда зачем? Да и сама переменная тоже как бы не нужна.

В принципе, я вот сколько не пытался понять этот код, всё время путался в закомменченных строках. Ну и я как бы не понимаю назначение этой функции, названной modbus_usart_5(). Вообще, осмысленные названия функций для того и придуманы, чтобы отражать назначение и выполняемые действия. Небрежность в оформлении и форматировании кода затрудняет его просмотр и отладку. 

а вот это серьезно

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

On 8/21/2024 at 11:42 PM, firstvald said:

Продолжаем разговор.

Опять всплыла бяка с hard fault.

//функция работающая в прерывани от последовательного порта

void modbus_usart_5(void)
{
	static unsigned char rx_flag=0;
	static unsigned char tx_flag=0;
	// static short unsigned int rx_reg; 
	static long unsigned int usart_sr_my=0;
	static long unsigned int usart_rdr_my=0;
	rx_flag=0;
	tx_flag=0;

	if((UART5->ISR & USART_ISR_PE) != 0){//по ошибке паритета
	   UART5->ICR |= USART_ICR_PECF;
	}
	if((UART5->ISR & USART_ISR_FE) != 0){//по ошибке кадрирования
	   UART5->ICR |= USART_ICR_FECF;
	}	

	if((UART5->ISR & USART_ISR_NE) != 0){//по шуму в посылке
	   UART5->ICR |= USART_ICR_NCF;
	}																	

	if((UART5->ISR & USART_ISR_ORE) != 0){//принятые данные не успели прочитать
	   UART5->ICR |= USART_ICR_ORECF;
	}																	
	if((UART5->ISR & USART_ISR_IDLE) != 0){//на линии долго ничего нет 
	//выставляется при обычном обмене
	   UART5->ICR |= USART_ICR_IDLECF;
	}																					

	if((UART5->ISR & USART_ISR_LBDF) != 0){//на линии длинный логический ноль
		UART5->ICR |= USART_ICR_LBDCF ;
	}		

	if((UART5->ISR & USART_ISR_RTOF) != 0){//тайм аут по приему
		UART5->ICR |= USART_ICR_RTOCF ;
	}		

	if((UART5->ISR & USART_ISR_EOBF) != 0){//конец блока - при работе со смарт картами
		//выставляется при обычном обмене
		UART5->ICR |= USART_ICR_EOBCF   ;
	}		

	if((UART5->ISR & USART_ISR_BUSY) != 0){// идет прием байта - флаг выставляется и сбрасывается аппаратно
		//UART5->ICR = USART_ICR_EOBCF   ;
		__NOP();// 
	}		
	if((UART5->ISR & USART_ISR_CTSIF) != 0){// CTS interrupt flag - флаг выставляется и сбрасывается аппаратно
		UART5->ICR |= USART_ICR_CTSCF   ;
		__NOP();// 
	}		
	if((UART5->ISR & USART_ISR_CTS) != 0){// CTS flag - флаг выставляется и сбрасывается аппаратно
		//UART5->ICR = USART_ICR_EOBCF   ;
		__NOP();// 
	}		
	if((UART5->ISR & USART_ISR_ABRE) != 0){// Auto-Baud Rate Error - флаг выставляется и сбрасывается аппаратно
		UART5->CR3 |= USART_RQR_ABRRQ   ;
		__NOP();// 
	}		
	if((UART5->ISR & USART_ISR_CMF) != 0){// Character Match Flag - флаг выставляется  аппаратно
		UART5->ICR |= USART_ICR_CMCF  ;
		//выставляется при обычном обмене
		__NOP();// 
	}

	if((UART5->ISR & USART_ISR_SBKF) != 0){// Send Break Flag - флаг выставляется программно и сбрасывается аппаратно
		//UART5->ICR = USART_ICR_EOBCF   ;
		__NOP();// 
	}

	if((UART5->ISR & USART_ISR_RWU) != 0){// Receive Wake Up from mute mode Flag - флаг выставляется и сбрасывается аппаратно
		//UART5->ICR = USART_ICR_EOBCF   ;
		//выставляется при обычном обмене
		__NOP();// 
	}																						
	if((UART5->ISR & USART_ISR_WUF) != 0){// Wake Up from stop mode Flag - флаг выставляется аппаратно
		UART5->ICR |= USART_ICR_WUCF   ;
		//выставляется при обычном обмене
		__NOP();// 
	}		

	if((UART5->ISR & USART_ISR_TEACK) != 0){// Transmit Enable Acknowledge Flag - флаг выставляется и сбрасывается аппаратно
		//UART5->ICR = USART_ICR_EOBCF   ;
		//выставляется при обычном обмене
		__NOP();// 
	}	

	if((UART5->ISR & USART_ISR_REACK) != 0){// Receive Enable Acknowledge Flag - флаг выставляется и сбрасывается аппаратно
		//UART5->ICR = USART_ICR_EOBCF   ;
		__NOP();// 
	}																							



	usart_sr_my = UART5->ISR;
	usart_rdr_my = UART5->RDR;//прочитали байт и при этом
								  //должен был сбросится флаг прерывания RXNE
	if((usart_sr_my & USART_ISR_TXE) != 0){//по передаче
	   //данные передались в сдвиговый регистр
		 //UART5->ISR &= ~USART_SR_TC;
	   //  UART5->ICR |= USART_ICR_TCCF  ;//сбросим флаг
		 UART5->RQR |= USART_RQR_TXFRQ  ;//сбросим USART_SR_TXE
	  // tx_flag=1;

		 __nop();
	}																
	if((usart_sr_my & USART_ISR_TC) != 0){//по передаче
	   //данные передались из сдвигового регистра	
		 //UART5->ISR &= ~USART_SR_TC;
		 UART5->ICR |= USART_ICR_TCCF  ;//сбросим флаг
		// UART5->RQR |= USART_RQR_TXFRQ  ;//сбросим USART_SR_TXE
	   tx_flag=1;
	}
	if((usart_sr_my & USART_ISR_RXNE) != 0){//по приему
		rx_flag=1;
		 //UART5->SR &= ~USART_SR_RXNE;
		  UART5->RQR |= USART_RQR_RXFRQ;//**сбросим флаг RXNE явно
		//rx_reg = UART5->RDR;//прочитали байт 
		//rx_reg = (UART5->DR);//прочитали байт 
	}


    if(tx_flag==1){//по передаче		
        tx_flag=0;		
        ...
		}//по передаче


	if(rx_flag==1){//по приему
        rx_flag=0;
		...
	}//по приему

	// заремарим сброс - вдруг какое то прерывание возникает повторно																	 
	UART5->ICR = 0xFFFF;//сбросим все флаги 

	UART5->ICR |= USART_ICR_PECF;

	UART5->ICR |= USART_ICR_FECF;

	UART5->ICR |= USART_ICR_NCF;

	UART5->ICR |= USART_ICR_ORECF;

	UART5->ICR |= USART_ICR_IDLECF;

	UART5->ICR |= USART_ICR_LBDCF ;
	UART5->ICR |= USART_ICR_RTOCF ;

}

@firstvald

1. Покажите код внутри тела условного оператора if(rx_flag==1) скрытое под многоточием

2. Проверьте логическим анализатором/осциллографом частоту вызова функции modbus_usart_5() во время сбоя перед сваливанием в hardfault

 

PS Это не мой код, я причесал портянку firstvald выложенную на 6 странице топика. Не задавайте мне вопросов по поводу этого ужаса)

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

9 hours ago, Sergey_Aleksandrovi4 said:
void modbus_usart_5(void)
{

И так для _каждого_ UART? ППЦ. Передавать указатель на структуру USART_TypeDef  не пробовали?

9 hours ago, Sergey_Aleksandrovi4 said:
	static unsigned char rx_flag=0;
	static unsigned char tx_flag=0;

Это зачем так, static? Вы обожаете стрелять себе по ногам?

9 hours ago, Sergey_Aleksandrovi4 said:
usart_sr_my = UART5->ISR;

Так это копия SR или ISR?

 

С такой кашей в голове вы далеко не уедите.

По UART и Модбас была хорошая статья на Хабре, плюс на форумах всё жёвано-пережёвано. В вашем МК немного другой UART, кастрированный, поэтому придётся принимать не по RTO, а по IDLE, а так всё однотипно.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Где логика, где логика... И этот господин еще утверждает, что оператор switch, по его мнению, говнокод. 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

On 8/23/2024 at 11:55 PM, Sergey_Aleksandrovi4 said:
//функция работающая в прерывани от последовательного порта

void modbus_usart_5(void)
{
	static unsigned char rx_flag=0;
	static unsigned char tx_flag=0;
	// static short unsigned int rx_reg; 
	static long unsigned int usart_sr_my=0;
	static long unsigned int usart_rdr_my=0;
	rx_flag=0;
	tx_flag=0;

	if((UART5->ISR & USART_ISR_PE) != 0){//по ошибке паритета
	   UART5->ICR |= USART_ICR_PECF;
	}
	if((UART5->ISR & USART_ISR_FE) != 0){//по ошибке кадрирования
	   UART5->ICR |= USART_ICR_FECF;
	}	

	if((UART5->ISR & USART_ISR_NE) != 0){//по шуму в посылке
	   UART5->ICR |= USART_ICR_NCF;
	}																	

	if((UART5->ISR & USART_ISR_ORE) != 0){//принятые данные не успели прочитать
	   UART5->ICR |= USART_ICR_ORECF;
	}																	
	if((UART5->ISR & USART_ISR_IDLE) != 0){//на линии долго ничего нет 
	//выставляется при обычном обмене
	   UART5->ICR |= USART_ICR_IDLECF;
	}																					

	if((UART5->ISR & USART_ISR_LBDF) != 0){//на линии длинный логический ноль
		UART5->ICR |= USART_ICR_LBDCF ;
	}		

	if((UART5->ISR & USART_ISR_RTOF) != 0){//тайм аут по приему
		UART5->ICR |= USART_ICR_RTOCF ;
	}		

	if((UART5->ISR & USART_ISR_EOBF) != 0){//конец блока - при работе со смарт картами
		//выставляется при обычном обмене
		UART5->ICR |= USART_ICR_EOBCF   ;
	}		

	if((UART5->ISR & USART_ISR_BUSY) != 0){// идет прием байта - флаг выставляется и сбрасывается аппаратно
		//UART5->ICR = USART_ICR_EOBCF   ;
		__NOP();// 
	}		
	if((UART5->ISR & USART_ISR_CTSIF) != 0){// CTS interrupt flag - флаг выставляется и сбрасывается аппаратно
		UART5->ICR |= USART_ICR_CTSCF   ;
		__NOP();// 
	}		
	if((UART5->ISR & USART_ISR_CTS) != 0){// CTS flag - флаг выставляется и сбрасывается аппаратно
		//UART5->ICR = USART_ICR_EOBCF   ;
		__NOP();// 
	}		
	if((UART5->ISR & USART_ISR_ABRE) != 0){// Auto-Baud Rate Error - флаг выставляется и сбрасывается аппаратно
		UART5->CR3 |= USART_RQR_ABRRQ   ;
		__NOP();// 
	}		
	if((UART5->ISR & USART_ISR_CMF) != 0){// Character Match Flag - флаг выставляется  аппаратно
		UART5->ICR |= USART_ICR_CMCF  ;
		//выставляется при обычном обмене
		__NOP();// 
	}

	if((UART5->ISR & USART_ISR_SBKF) != 0){// Send Break Flag - флаг выставляется программно и сбрасывается аппаратно
		//UART5->ICR = USART_ICR_EOBCF   ;
		__NOP();// 
	}

	if((UART5->ISR & USART_ISR_RWU) != 0){// Receive Wake Up from mute mode Flag - флаг выставляется и сбрасывается аппаратно
		//UART5->ICR = USART_ICR_EOBCF   ;
		//выставляется при обычном обмене
		__NOP();// 
	}																						
	if((UART5->ISR & USART_ISR_WUF) != 0){// Wake Up from stop mode Flag - флаг выставляется аппаратно
		UART5->ICR |= USART_ICR_WUCF   ;
		//выставляется при обычном обмене
		__NOP();// 
	}		

	if((UART5->ISR & USART_ISR_TEACK) != 0){// Transmit Enable Acknowledge Flag - флаг выставляется и сбрасывается аппаратно
		//UART5->ICR = USART_ICR_EOBCF   ;
		//выставляется при обычном обмене
		__NOP();// 
	}	

	if((UART5->ISR & USART_ISR_REACK) != 0){// Receive Enable Acknowledge Flag - флаг выставляется и сбрасывается аппаратно
		//UART5->ICR = USART_ICR_EOBCF   ;
		__NOP();// 
	}																							



	usart_sr_my = UART5->ISR;
	usart_rdr_my = UART5->RDR;//прочитали байт и при этом
								  //должен был сбросится флаг прерывания RXNE
	if((usart_sr_my & USART_ISR_TXE) != 0){//по передаче
	   //данные передались в сдвиговый регистр
		 //UART5->ISR &= ~USART_SR_TC;
	   //  UART5->ICR |= USART_ICR_TCCF  ;//сбросим флаг
		 UART5->RQR |= USART_RQR_TXFRQ  ;//сбросим USART_SR_TXE
	  // tx_flag=1;

		 __nop();
	}																
	if((usart_sr_my & USART_ISR_TC) != 0){//по передаче
	   //данные передались из сдвигового регистра	
		 //UART5->ISR &= ~USART_SR_TC;
		 UART5->ICR |= USART_ICR_TCCF  ;//сбросим флаг
		// UART5->RQR |= USART_RQR_TXFRQ  ;//сбросим USART_SR_TXE
	   tx_flag=1;
	}
	if((usart_sr_my & USART_ISR_RXNE) != 0){//по приему
		rx_flag=1;
		 //UART5->SR &= ~USART_SR_RXNE;
		  UART5->RQR |= USART_RQR_RXFRQ;//**сбросим флаг RXNE явно
		//rx_reg = UART5->RDR;//прочитали байт 
		//rx_reg = (UART5->DR);//прочитали байт 
	}


    if(tx_flag==1){//по передаче		
        tx_flag=0;		
        ...
		}//по передаче


	if(rx_flag==1){//по приему
        rx_flag=0;
		...
	}//по приему

	// заремарим сброс - вдруг какое то прерывание возникает повторно																	 
	UART5->ICR = 0xFFFF;//сбросим все флаги 

	UART5->ICR |= USART_ICR_PECF;

	UART5->ICR |= USART_ICR_FECF;

	UART5->ICR |= USART_ICR_NCF;

	UART5->ICR |= USART_ICR_ORECF;

	UART5->ICR |= USART_ICR_IDLECF;

	UART5->ICR |= USART_ICR_LBDCF ;
	UART5->ICR |= USART_ICR_RTOCF ;

}

@firstvald

1. Покажите код внутри тела условного оператора if(rx_flag==1) скрытое под многоточием

2. Проверьте логическим анализатором/осциллографом частоту вызова функции modbus_usart_5() во время сбоя перед сваливанием в hardfault

 

PS Это не мой код, я причесал портянку firstvald выложенную на 6 странице топика. Не задавайте мне вопросов по поводу этого ужаса)

 

там дальше в обработчике принятого при шуме в линии в рассчете контрольной суммы выезжал массив. но! это происходит ровно при шуме или если идет обращение на скорости через две на третью от настроенной. абсолютно четко соблюдается. это сильно указывало на что то в уарте. но оказывается может быть вот так.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А зачем вообще менять скорость во время коммуникации? Скорость передатчика и приемника в этом случае может быть несогласованной. При смене скорости обычно передается последовательность автодетектирования скорости.
У вас же вообще не реализован НИ ОДИН обработчик флагов - нет ни обработки ошибки фрейма, ни обнаружения Idle, ни чего, акромя тупо принятого байта. Мануал то читали хоть краем глаза?

Написана какая-то ерунда, почему-то написаны проверки флагов, которые в текущем режиме работы вообще никогда не выставляются. Некоторые флаги просто NOP-нуты, а самые нужные флаги просто забыты. Перепутано все что только можно.

Микроконтроллер то хоть какой? Что-то уровня H7хх чтоль?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

58 минут назад, EdgeAligned сказал:

У вас же вообще не реализован НИ ОДИН обработчик флагов - нет ни обработки ошибки фрейма, ни обнаружения Idle, ни чего, акромя тупо принятого байта. Мануал то читали хоть краем глаза?

Там и обработки флагов-то по факту нет никакой. Одни баги.

58 минут назад, EdgeAligned сказал:

Микроконтроллер то хоть какой? Что-то уровня H7хх чтоль?

Я так понял - что-то из L-серии STM. Хотя - раз автор не указал какой именно - мы имеем полное право подразумевать любой.

 

PS: А вообще - за вопросы по конкретным МК, без точного указания - о каком конкретно МК идёт речь - давно пора минусовать по полной.

Так как в таком случае это скорее не технический вопрос, а попытка разжигания флейма.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Мне что кажется, что это H743/H750, потому что UART5 представлен в виде UART, а не USART.

Впрочем, глядя на все это, поднимается рука к лицу в очередной раз - автор кода просто вообще не понимает ни-че-го и даже не пытается понять

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Цитата
if((usart_sr_my & USART_ISR_TXE) != 0){//по передаче

Ключевой ошибкой в этой записи является то, что вообще-то флаг TXE установлен всегда, за исключением одного случая. А теперь представим, что в прерывание USART попадаем например по флагу RXNE. И когда доходим до проверки флага TXE, а он оказывается установлен (передача не выполняется), то будет выполняться код внутри показанного if(), то есть, будет записан регистр TDR байтом для передачи. Отсюда - ложный запуск передачи в момент чтения принятого байта. И получаем вот такую картину:

2024-08-28202722.thumb.jpg.70990aa8ab9fd15e17ae9704e78f649d.jpg

Казалось бы, мы запретили прерывание от TXE, оставив только RXNE, но передача запускается после каждого принятого байта (здесь в схеме TX соединен с RX перемычкой). Но стоит только добавить одно маленькое дополнительное условие в проверку if, как тут же все встает на свои места.

Всё, что написано в том коде дальше - плод слепого тыкания наугад.

UART5->RQR |= USART_RQR_TXFRQ  ;//сбросим USART_SR_TXE

вообще не имеет отношения к рассматриваемому случаю, поскольку работает либо в смарткард-режиме, либо с FIFO, и не сбрасывает TXE, а наоборот устанавливает его.
Тут можно сказать только одно - RTFM, то есть, "рид зе факинь мануал". Я не знаю, как это всё там работало (как утверждает автор), видимо, на честном слове по чистой случайности. В общем, того, кто писал тот текст, следует отстегать розгами на полном серьезе. Ошибки - буквально в каждой строчке, без преувеличения. 

Я уже не говорю о том, что специфические тайминги и завершающие символы модбаса в этом УАРТе могут обрабатываться аппаратно. 
А при смене скорости коммуникации приемник должен включить режим автодетектирования скорости, а передатчик должен передать синхронизирующую посылку. Например, несколько раз 0x55. При этом в приемнике автоматически заносится в BRR вычисленное значение скорости. Но я не встречал случаев, чтобы во время сеанса обмена скорость УАРТа неожиданно менялась. Во избежание конфликтов всё подключенное к линии оборудование должно работать на одной и той же скорости. Тем более, адресный модбас.
Флаги, которые не могут устанавливаться в текущем режиме работы, опрашивать НЕ нужно. То есть, флаги, относящиеся к смарткард-режиму, они не могут быть установлены в режиме базового UART. А вот флаги ошибок не следует "NOP-ать" и сбрасывать, они ж как раз и предназначены для обнаружения событий, а не просто для того, чтоб были.

Кароч, RTFM (реад тхе фукинг мануал). И надавать по рукам тому, кто писал ту портянку. Совершенно безграмотно, ни одной правильной строчки, ни одной!

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

5 minutes ago, EdgeAligned said:

Ключевой ошибкой в этой записи является то, что

Нужно проверять вместе с флагом разрешения прерывания по TXE и фатальной ошибки не будет.

А можно взять текст от HAL и изучить с карандашом

(это всё для ТС)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

вместе с флагом разрешения прерывания по TXE

что я выше, соппсна и написал /*в закомментированном тексте*/.
Я просто хотел показать, к чему реально приводит пренебрежение такой проверкой.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

26 minutes ago, EdgeAligned said:

что я выше, соппсна и написал /*в закомментированном тексте*/.
Я просто хотел показать, к чему реально приводит пренебрежение такой проверкой.

Полностью согласен.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1 час назад, EdgeAligned сказал:

что я выше, соппсна и написал /*в закомментированном тексте*/.
Я просто хотел показать, к чему реально приводит пренебрежение такой проверкой.

Просто однажды что-то кое-какерски работающее перетаскивается из проекта в проект. Вот потом и вылезает.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

44 минуты назад, Arlleex сказал:

Просто однажды что-то кое-какерски работающее перетаскивается из проекта в проект. Вот потом и вылезает.

Там, судя по тексту - плод "труда" коллектива авторов. И коллектив этот работал в том же стиле, что известные персонажи при написании письма из Простоквашино: "То лапы ломит, то хвост отваливается…"  :biggrin:

Каждый добавлял в меру своих способностей.... 

А ведь коллектив этот вполне может работать под соусом какого-нить нац.проекта. А потом и падают, сляпанные такими коллективами, "Луны-25" и "Фобос-в-грунты"....

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

2 минуты назад, jcxz сказал:

Там, судя по тексту - плод "труда" коллектива авторов. И коллектив этот работал в том же стиле, что известные персонажи при написании письма из Простоквашино: "То лапы ломит, то хвост отваливается…"  :biggrin:

Каждый добавлял в меру своих способностей....

Лично я доставшийся "проблемный" проект под МК сразу начинаю заново, если он объективно простой. Но, к сожалению, зачастую в таких случаях проблем набирается с другой стороны - с аппаратной: то ШИМ выведен на обычный пин, то SPI ногодрыгом завели, то еще чего-нибудь.

Емкие по объему кода проекты стараюсь допиливать как есть. Некоторые модули просто переписываю, не ломая код основной логики.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
К сожалению, ваш контент содержит запрещённые слова. Пожалуйста, отредактируйте контент, чтобы удалить выделенные ниже слова.
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...