|
STM32: HardFault |
|
|
|
Mar 27 2014, 04:16
|

Местный
  
Группа: Участник
Сообщений: 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; Как так? точно такая же функция на отправку работает нормально...
|
|
|
|
2 страниц
1 2 >
|
 |
Ответов
(1 - 27)
|
Mar 27 2014, 08:17
|
Знающий
   
Группа: Участник
Сообщений: 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
|
|
|
|
|
Mar 27 2014, 19:19
|
Гуру
     
Группа: Свой
Сообщений: 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); } Компилятор в курсе, что у него в регистрах, а что в памяти. И переместит в случае необходимости.
|
|
|
|
|
Mar 27 2014, 23:53
|
Гуру
     
Группа: Свой
Сообщений: 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-ядра. Но по дефолту это там запрещено.
|
|
|
|
|
Mar 28 2014, 04:00
|

Местный
  
Группа: Участник
Сообщений: 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; } } причина хардфаулта крылась либо в использовании локальных структур (а размер у них не малый), что негативно сказывалось на стеке, либо в некорректном порядке инициализации.
|
|
|
|
|
Mar 28 2014, 05:08
|

Гуру
     
Группа: Модераторы
Сообщений: 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)
|
|
|
|
|
Mar 28 2014, 09:22
|
Гуру
     
Группа: Свой
Сообщений: 4 256
Регистрация: 17-02-06
Пользователь №: 14 454

|
ну не за пол дня, а за сутки все таки... тем более вы пишите Код причина хардфаулта крылась либо в использовании локальных структур (а размер у них не малый), что негативно сказывалось на стеке, либо в некорректном порядке инициализации. либо в чем то еще, и вы не уверены в чем, и то что оно сейчас завелось, не значит что когда в проекте появиться еще что-то оно так же случайно не выключится...
|
|
|
|
|
Sep 3 2016, 19:59
|

Участник

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

|
Цитата(k000858 @ Mar 27 2014, 07:16)  Реализую 1-wire на UART+DMA как успехи? получилось довести до ума?
|
|
|
|
|
Sep 7 2016, 22:38
|

Участник

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

|
Цитата(k000858 @ Sep 7 2016, 15:17)  да, все работает поделитесь пожалуйста кодом. имейл отпраил Вам в личку
Сообщение отредактировал RusikOk - Sep 7 2016, 22:39
|
|
|
|
|
Sep 8 2016, 07:28
|

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

|
Цитата(RusikOk @ Sep 8 2016, 01:38)  поделитесь пожалуйста кодом. имейл отпраил Вам в личку к сожалению, не получится: разработка коммерческая, исходниками не делюсь но если есть конкретные вопросы, постараюсь помочь чем смогу
|
|
|
|
|
Sep 10 2016, 09:01
|

Участник

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

|
Цитата(k000858 @ Sep 8 2016, 10:28)  постараюсь помочь чем смогу буджу благодарен. скажите какая схема подключения датчиков к контроллеру? и какая реальная максимальная длинна линии?
|
|
|
|
|
Sep 13 2016, 04:19
|

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

|
Цитата(RusikOk @ Sep 10 2016, 12:01)  буджу благодарен. скажите какая схема подключения датчиков к контроллеру? и какая реальная максимальная длинна линии? на сколько помню, до 100 метров в нашем случае работает схемы у меня толком нету (для меня, как для программиста, это просто ЮАРТ + 1 джио ножка для подтяжке питания на линию на время преобразования температуры), а если б и была то выложить по той же причине не смог бы
|
|
|
|
|
Sep 13 2016, 05:20
|

Участник

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

|
схема мне не нужна. главное что все построено на UART. a DMA у вас используется? по примеру как тут http://we.easyelectronics.ru/STM32/stm32-1...odolzhenie.htmlпланирую использовать эту библиотеку переписав ее под HAL P.S. дело в том, что это мой первый проект на STM32 да еще и такой сложный а тут еще этот HAL с минимальным набором готовых библиотек на нем и сроки поджимают. а в проекте не только датчики...
|
|
|
|
|
Sep 13 2016, 09:02
|

Местный
  
Группа: Участник
Сообщений: 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.
|
|
|
|
|
Feb 11 2017, 09:56
|
Группа: Новичок
Сообщений: 1
Регистрация: 11-02-17
Пользователь №: 95 391

|
проект на CubeMx? как делали изменение скорости порта? Если я правильно понял нужно прыгать между 9600 и 115200, но хотелось бы оставить сгенерированный кубом код
|
|
|
|
|
Feb 11 2017, 10:50
|

Участник

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

|
Цитата(IgorC @ Feb 11 2017, 12:56)  но хотелось бы оставить сгенерированный кубом код так скопируй этот кусок в нужное место с подправленной скоростью
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|