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

 
 
> STM32: HardFault
k000858
сообщение Mar 27 2014, 04:16
Сообщение #1


Местный
***

Группа: Участник
Сообщений: 319
Регистрация: 31-01-12
Пользователь №: 69 978



Реализую 1-wire на UART+DMA, камень STM32F407
Делается все на фирменных ST библиотеках HAL (новые SPL)

После вызова функции HAL_UART_Receive_DMA(&UartHandle, (uint8_t *)ds18b20_buf_rx, sizeof(ds18b20_buf_rx)); попадаю в хардфаулт.
uint8_t ds18b20_buf_rx[8];

часть внутренностей функции:
Код
HAL_StatusTypeDef HAL_UART_Receive_DMA(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)
{
  uint32_t *tmp;
  tmp = (uint32_t*)&pData;
}


Прерывание происходит на строчке tmp = (uint32_t*)&pData;

Как так?

точно такая же функция на отправку работает нормально...
Go to the top of the page
 
+Quote Post
2 страниц V   1 2 >  
Start new topic
Ответов (1 - 27)
Сергей Борщ
сообщение Mar 27 2014, 04:55
Сообщение #2


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



Сама по себе строчка некриминальна. Надо пройтись по инструкциям в окне дизассемблера.

Зачем им указатель на указатель - надо смотреть дальше. И вот снова, хоть вы и говорите, что библиотека новая, но написана она кривовато. Они делают тут указатель на переданный вами указатель и явно приводят его к типу "указатель на uint32_t". Если это действительно то, чего они хотели, то нужно было применить специально созданный для таких случаев тип uintptr_t *, а не uint32_t *. А может они хотели привести ваш указатель на буфер к типу "указатель на uint32_t"? Тогда они написали тут лишний '&' и возможны проблемы с невыровненным доступом. Надо внимательно смотреть остальной текст функции.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
ISK2010
сообщение Mar 27 2014, 05:01
Сообщение #3


Местный
***

Группа: Участник
Сообщений: 205
Регистрация: 21-09-10
Из: г.Зеленоград
Пользователь №: 59 631



Может вы хотели написать "tmp = (uint32_t*)pData;" ?
Go to the top of the page
 
+Quote Post
k000858
сообщение Mar 27 2014, 05:38
Сообщение #4


Местный
***

Группа: Участник
Сообщений: 319
Регистрация: 31-01-12
Пользователь №: 69 978



это не я написал, это библиотека от ST

сейчас убрал все лишнее, только инициализация UART+DMA и отправка по dma, и сново хардфаулт.
сам в Си криминала так же не обнаружил, вероятно есть какие то особенности

погоняю еще отладчиком, может что выясню
Go to the top of the page
 
+Quote Post
KnightIgor
сообщение Mar 27 2014, 08:17
Сообщение #5


Знающий
****

Группа: Участник
Сообщений: 643
Регистрация: 29-05-09
Из: Германия
Пользователь №: 49 725



Цитата(k000858 @ Mar 27 2014, 05:16) *
Реализую 1-wire на UART+DMA, камень STM32F407
часть внутренностей функции:
Код
HAL_StatusTypeDef HAL_UART_Receive_DMA(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)
{
  uint32_t *tmp;
  tmp = (uint32_t*)&pData;
}


Прерывание происходит на строчке tmp = (uint32_t*)&pData;

Как так?

Процессор не любит словные (32-битовые) обращения по невыровненному адресу.
Вообще, (uint32_t*)&pData - явно чушь. Либо должно быть (uint32_t*)&pData[0], либо (uint32_t*)pData. Без вариантов. И если вышеуказаный код в библиотеке стоит, значит в ней типичная индусская ошибка.

Сообщение отредактировал KnightIgor - Mar 27 2014, 08:34
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Mar 27 2014, 11:03
Сообщение #6


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



Цитата(KnightIgor @ Mar 27 2014, 10:17) *
Вообще, (uint32_t*)&pData - явно чушь.
Не видя остального кода функции этого нельзя утверждать со 100% уверенностью.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
KnightIgor
сообщение Mar 27 2014, 18:55
Сообщение #7


Знающий
****

Группа: Участник
Сообщений: 643
Регистрация: 29-05-09
Из: Германия
Пользователь №: 49 725



Цитата(Сергей Борщ @ Mar 27 2014, 12:03) *
Не видя остального кода функции этого нельзя утверждать со 100% уверенностью.

100% в инженерной практике не существуют. С 99.9% можно утверждать, что делать ссылку на указатель, переданый в качестве параметра - бессмысленно и вредно (Hardware Fault это доказывает): параметр pData содержит указатель на некий внешний буфер байтов. То есть, по соглашению о передаче параметров в ARM С, указатель содержится в регистре R1. Оператор пытается взять указатель на регистр R1, а это вам не MSC-51 архитектура, где все регистры есть одновременно и ячейки памяти.
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Mar 27 2014, 19:19
Сообщение #8


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Цитата(KnightIgor @ Mar 27 2014, 22:55) *
100% в инженерной практике не существуют. С 99.9% можно утверждать, что делать ссылку на указатель, переданый в качестве параметра - бессмысленно и вредно (Hardware Fault это доказывает): параметр pData содержит указатель на некий внешний буфер байтов. То есть, по соглашению о передаче параметров в ARM С, указатель содержится в регистре R1. Оператор пытается взять указатель на регистр R1, а это вам не MSC-51 архитектура, где все регистры есть одновременно и ячейки памяти.

Значит, такая конструкция тоже не имеет права на жизнь:
Код
void yyy(int **);

void xxx(int *a)
{
    yyy(&a);
}

Компилятор в курсе, что у него в регистрах, а что в памяти. И переместит в случае необходимости.
Go to the top of the page
 
+Quote Post
jcxz
сообщение Mar 27 2014, 23:53
Сообщение #9


Гуру
******

Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713



Цитата(KnightIgor @ Mar 28 2014, 00:55) *
То есть, по соглашению о передаче параметров в ARM С, указатель содержится в регистре R1. Оператор пытается взять указатель на регистр R1, а это вам не MSC-51 архитектура, где все регистры есть одновременно и ячейки памяти.

Прежде чем писать, потрудились-бы хотя-бы в листинг заглянуть: при взятии адреса аргумента функции переданного в регистре, компилятор переместит его на стек (внутри функции).

Цитата(KnightIgor @ Mar 27 2014, 14:17) *
Процессор не любит словные (32-битовые) обращения по невыровненному адресу.

"Любит-нелюбит" - это к девушкам.
А вообще Cortex-M вполне нормально переваривает невыровненные доступы (в отличие от ARM7/9) (исключение - инструкции LDM, STM, LDRD, STRD, но вряд-ли компилятор их там нагенерил).
Опционально можно разрешить Usage Fault при невыровненном доступе. Это делается в регистре CCR Cortex-ядра. Но по дефолту это там запрещено.
Go to the top of the page
 
+Quote Post
k000858
сообщение Mar 28 2014, 01:07
Сообщение #10


Местный
***

Группа: Участник
Сообщений: 319
Регистрация: 31-01-12
Пользователь №: 69 978



Проблема решилась. пошагал отладчиком и все такое.
после того как сделал структуры (для инициализации DMA на Tx и RX и тд) глобальными (видимо стека не хватало на локальные переменные) и изменил порядок вызова функций все задышало. + для работы новых HAL библиотек необходимо юзать прерывания для dma. ну в общем там ни мало особенностей появилось по сравнению со стрыми SPL
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Mar 28 2014, 03:39
Сообщение #11


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



Цитата(k000858 @ Mar 28 2014, 03:07) *
Проблема решилась. пошагал отладчиком и все такое.
А не могли бы вы выложить весь текст функции HAL_UART_Receive_DMA()? А то тут уже пошли теологические споры и было бы хорошо поставить жирную точку.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
k000858
сообщение Mar 28 2014, 04:00
Сообщение #12


Местный
***

Группа: Участник
Сообщений: 319
Регистрация: 31-01-12
Пользователь №: 69 978



Цитата(Сергей Борщ @ Mar 28 2014, 07:39) *
А не могли бы вы выложить весь текст функции HAL_UART_Receive_DMA()? А то тут уже пошли теологические споры и было бы хорошо поставить жирную точку.

на самом деле в самой функции ошибки нет. все работает корректно с передачей вышеописанных переменных.


Код
/**
  * @brief  Receives an amount of data in non blocking mode.
  * @param  huart: UART handle
  * @param  pData: Pointer to data buffer
  * @param  Size: Amount of data to be received
  * @note   When the UART parity is enabled (PCE = 1) the data received contain the parity bit.
  * @retval HAL status
  */
HAL_StatusTypeDef HAL_UART_Receive_DMA(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)
{
  uint32_t *tmp;
  uint32_t tmp1 = 0;
  
  tmp1 = huart->State;    
  if((tmp1 == HAL_UART_STATE_READY) || (tmp1 == HAL_UART_STATE_BUSY_TX))
  {
    if((pData == NULL ) || (Size == 0))
    {
      return HAL_ERROR;
    }
    
    /* Process Locked */
    __HAL_LOCK(huart);
    
    huart->pRxBuffPtr = pData;
    huart->RxXferSize = Size;
    
    huart->ErrorCode = HAL_UART_ERROR_NONE;
    /* Check if a transmit rocess is ongoing or not */
    if(huart->State == HAL_UART_STATE_BUSY_TX)
    {
      huart->State = HAL_UART_STATE_BUSY_TX_RX;
    }
    else
    {
      huart->State = HAL_UART_STATE_BUSY_RX;
    }
    
    /* Set the UART DMA transfer complete callback */
    huart->hdmarx->XferCpltCallback = UART_DMAReceiveCplt;
    
    /* Set the UART DMA Half transfer complete callback */
    huart->hdmarx->XferHalfCpltCallback = UART_DMARxHalfCplt;
    
    /* Set the DMA error callback */
    huart->hdmarx->XferErrorCallback = UART_DMAError;

    /* Enable the DMA Stream */
    tmp = (uint32_t*)&pData;
    HAL_DMA_Start_IT(huart->hdmarx, (uint32_t)&huart->Instance->DR, *(uint32_t*)tmp, Size);
    
    /* Enable the DMA transfer for the receiver request by setting the DMAR bit
    in the UART CR3 register */
    huart->Instance->CR3 |= USART_CR3_DMAR;
    
    /* Process Unlocked */
    __HAL_UNLOCK(huart);
    
    return HAL_OK;
  }
  else
  {
    return HAL_BUSY;
  }
}


причина хардфаулта крылась либо в использовании локальных структур (а размер у них не малый), что негативно сказывалось на стеке, либо в некорректном порядке инициализации.
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Mar 28 2014, 05:08
Сообщение #13


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



Цитата(k000858 @ Mar 28 2014, 06:00) *
на самом деле в самой функции ошибки нет. все работает корректно с передачей вышеописанных переменных.

Да, но вот конкретно этот кусочек кода - шедевр
Код
    tmp = (uint32_t*)&pData;
    HAL_DMA_Start_IT(huart->hdmarx, (uint32_t)&huart->Instance->DR, *(uint32_t*)tmp, Size);
Не говоря уже о том, что второе приведение типа абсолютно лишнее, можно было написать прямее:
Код
    HAL_DMA_Start_IT(huart->hdmarx, (uint32_t)&huart->Instance->DR, (uintptr_t)pData, Size);

Далее, pData надо было делать void * а преобразование типа перенести внутрь HAL_DMA_Start_IT. А еще правильнее было бы объявить как void * сам регистр DMA_Channel_TypeDef.CPAR (и CMAR заодно).


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
k000858
сообщение Mar 28 2014, 05:39
Сообщение #14


Местный
***

Группа: Участник
Сообщений: 319
Регистрация: 31-01-12
Пользователь №: 69 978



ну библы новые, может причешут!
зато удалось реализовать работу DS18B20 по UART+DMA за пол дня, и даташит открыть пришлось только для того, что бы узнать какой поток/канал DMA активировать для нужного UART'а.
Go to the top of the page
 
+Quote Post
Golikov A.
сообщение Mar 28 2014, 09:22
Сообщение #15


Гуру
******

Группа: Свой
Сообщений: 4 256
Регистрация: 17-02-06
Пользователь №: 14 454



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


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

Go to the top of the page
 
+Quote Post
jcxz
сообщение Mar 28 2014, 10:10
Сообщение #16


Гуру
******

Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713



Цитата(Golikov A. @ Mar 28 2014, 15:22) *
либо в чем то еще, и вы не уверены в чем, и то что оно сейчас завелось, не значит что когда в проекте появиться еще что-то оно так же случайно не выключится...

Во-во - в точку! Шаманство вобщем sm.gif
Обычная практика когда не хотят открывать даташит...
Go to the top of the page
 
+Quote Post
DASM
сообщение Mar 28 2014, 14:09
Сообщение #17


Гуру
******

Группа: Свой
Сообщений: 3 644
Регистрация: 28-05-05
Пользователь №: 5 493



За это и можно ненавидеть язык С. В fault на ровном месте.
Go to the top of the page
 
+Quote Post
Genadi Zawidowsk...
сообщение Mar 29 2014, 06:43
Сообщение #18


Профессионал
*****

Группа: Участник
Сообщений: 1 620
Регистрация: 22-06-07
Из: Санкт-Петербург, Россия
Пользователь №: 28 634



HAL_DMA_Start_IT(huart->hdmarx, (uint32_t)&huart->Instance->DR, *(uint32_t*)tmp, Size);
Ничего себе, ровное место!
Go to the top of the page
 
+Quote Post
RusikOk
сообщение Sep 3 2016, 19:59
Сообщение #19


Участник
*

Группа: Участник
Сообщений: 46
Регистрация: 14-01-12
Пользователь №: 69 438



Цитата(k000858 @ Mar 27 2014, 07:16) *
Реализую 1-wire на UART+DMA
как успехи? получилось довести до ума?
Go to the top of the page
 
+Quote Post
k000858
сообщение Sep 7 2016, 12:17
Сообщение #20


Местный
***

Группа: Участник
Сообщений: 319
Регистрация: 31-01-12
Пользователь №: 69 978



Цитата(RusikOk @ Sep 3 2016, 22:59) *
как успехи? получилось довести до ума?

да, все работает
Go to the top of the page
 
+Quote Post
RusikOk
сообщение Sep 7 2016, 22:38
Сообщение #21


Участник
*

Группа: Участник
Сообщений: 46
Регистрация: 14-01-12
Пользователь №: 69 438



Цитата(k000858 @ Sep 7 2016, 15:17) *
да, все работает
поделитесь пожалуйста кодом. имейл отпраил Вам в личку

Сообщение отредактировал RusikOk - Sep 7 2016, 22:39
Go to the top of the page
 
+Quote Post
k000858
сообщение Sep 8 2016, 07:28
Сообщение #22


Местный
***

Группа: Участник
Сообщений: 319
Регистрация: 31-01-12
Пользователь №: 69 978



Цитата(RusikOk @ Sep 8 2016, 01:38) *
поделитесь пожалуйста кодом. имейл отпраил Вам в личку

к сожалению, не получится: разработка коммерческая, исходниками не делюсь
но если есть конкретные вопросы, постараюсь помочь чем смогу
Go to the top of the page
 
+Quote Post
RusikOk
сообщение Sep 10 2016, 09:01
Сообщение #23


Участник
*

Группа: Участник
Сообщений: 46
Регистрация: 14-01-12
Пользователь №: 69 438



Цитата(k000858 @ Sep 8 2016, 10:28) *
постараюсь помочь чем смогу
буджу благодарен.
скажите какая схема подключения датчиков к контроллеру? и какая реальная максимальная длинна линии?
Go to the top of the page
 
+Quote Post
k000858
сообщение Sep 13 2016, 04:19
Сообщение #24


Местный
***

Группа: Участник
Сообщений: 319
Регистрация: 31-01-12
Пользователь №: 69 978



Цитата(RusikOk @ Sep 10 2016, 12:01) *
буджу благодарен.
скажите какая схема подключения датчиков к контроллеру? и какая реальная максимальная длинна линии?

на сколько помню, до 100 метров в нашем случае работает
схемы у меня толком нету (для меня, как для программиста, это просто ЮАРТ + 1 джио ножка для подтяжке питания на линию на время преобразования температуры), а если б и была то выложить по той же причине не смог бы
Go to the top of the page
 
+Quote Post
RusikOk
сообщение Sep 13 2016, 05:20
Сообщение #25


Участник
*

Группа: Участник
Сообщений: 46
Регистрация: 14-01-12
Пользователь №: 69 438



схема мне не нужна. главное что все построено на UART. a DMA у вас используется? по примеру как тут http://we.easyelectronics.ru/STM32/stm32-1...odolzhenie.html
планирую использовать эту библиотеку переписав ее под HAL

P.S.
дело в том, что это мой первый проект на STM32 да еще и такой сложный а тут еще этот HAL с минимальным набором готовых библиотек на нем и сроки поджимают. а в проекте не только датчики...
Go to the top of the page
 
+Quote Post
k000858
сообщение Sep 13 2016, 09:02
Сообщение #26


Местный
***

Группа: Участник
Сообщений: 319
Регистрация: 31-01-12
Пользователь №: 69 978



Цитата(RusikOk @ Sep 13 2016, 08:20) *
схема мне не нужна. главное что все построено на UART. a DMA у вас используется? по примеру как тут http://we.easyelectronics.ru/STM32/stm32-1...odolzhenie.html
планирую использовать эту библиотеку переписав ее под HAL

P.S.
дело в том, что это мой первый проект на STM32 да еще и такой сложный а тут еще этот HAL с минимальным набором готовых библиотек на нем и сроки поджимают. а в проекте не только датчики...

все так же делал: все написано на основе HAL:
DMA используется по RX линии, по TX линии использовать его не вижу смысла; в ТХ плюю байтики, а между тем они же (но с учетом влияния шины 1-wire и устройств на ней) складываются по DMA в RX.
Go to the top of the page
 
+Quote Post
IgorC
сообщение Feb 11 2017, 09:56
Сообщение #27





Группа: Новичок
Сообщений: 1
Регистрация: 11-02-17
Пользователь №: 95 391



проект на CubeMx? как делали изменение скорости порта?
Если я правильно понял нужно прыгать между 9600 и 115200, но хотелось бы оставить сгенерированный кубом код
Go to the top of the page
 
+Quote Post
RusikOk
сообщение Feb 11 2017, 10:50
Сообщение #28


Участник
*

Группа: Участник
Сообщений: 46
Регистрация: 14-01-12
Пользователь №: 69 438



Цитата(IgorC @ Feb 11 2017, 12:56) *
но хотелось бы оставить сгенерированный кубом код
так скопируй этот кусок в нужное место с подправленной скоростью
Go to the top of the page
 
+Quote Post

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

 


RSS Текстовая версия Сейчас: 23rd August 2025 - 12:32
Рейтинг@Mail.ru


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