k000858 0 27 марта, 2014 Опубликовано 27 марта, 2014 · Жалоба Реализую 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; Как так? точно такая же функция на отправку работает нормально... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 119 27 марта, 2014 Опубликовано 27 марта, 2014 · Жалоба Сама по себе строчка некриминальна. Надо пройтись по инструкциям в окне дизассемблера. Зачем им указатель на указатель - надо смотреть дальше. И вот снова, хоть вы и говорите, что библиотека новая, но написана она кривовато. Они делают тут указатель на переданный вами указатель и явно приводят его к типу "указатель на uint32_t". Если это действительно то, чего они хотели, то нужно было применить специально созданный для таких случаев тип uintptr_t *, а не uint32_t *. А может они хотели привести ваш указатель на буфер к типу "указатель на uint32_t"? Тогда они написали тут лишний '&' и возможны проблемы с невыровненным доступом. Надо внимательно смотреть остальной текст функции. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ISK2010 0 27 марта, 2014 Опубликовано 27 марта, 2014 · Жалоба Может вы хотели написать "tmp = (uint32_t*)pData;" ? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
k000858 0 27 марта, 2014 Опубликовано 27 марта, 2014 · Жалоба это не я написал, это библиотека от ST сейчас убрал все лишнее, только инициализация UART+DMA и отправка по dma, и сново хардфаулт. сам в Си криминала так же не обнаружил, вероятно есть какие то особенности погоняю еще отладчиком, может что выясню Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
KnightIgor 2 27 марта, 2014 Опубликовано 27 марта, 2014 (изменено) · Жалоба Реализую 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. Без вариантов. И если вышеуказаный код в библиотеке стоит, значит в ней типичная индусская ошибка. Изменено 27 марта, 2014 пользователем KnightIgor Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 119 27 марта, 2014 Опубликовано 27 марта, 2014 · Жалоба Вообще, (uint32_t*)&pData - явно чушь.Не видя остального кода функции этого нельзя утверждать со 100% уверенностью. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
KnightIgor 2 27 марта, 2014 Опубликовано 27 марта, 2014 · Жалоба Не видя остального кода функции этого нельзя утверждать со 100% уверенностью. 100% в инженерной практике не существуют. С 99.9% можно утверждать, что делать ссылку на указатель, переданый в качестве параметра - бессмысленно и вредно (Hardware Fault это доказывает): параметр pData содержит указатель на некий внешний буфер байтов. То есть, по соглашению о передаче параметров в ARM С, указатель содержится в регистре R1. Оператор пытается взять указатель на регистр R1, а это вам не MSC-51 архитектура, где все регистры есть одновременно и ячейки памяти. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
aaarrr 63 27 марта, 2014 Опубликовано 27 марта, 2014 · Жалоба 100% в инженерной практике не существуют. С 99.9% можно утверждать, что делать ссылку на указатель, переданый в качестве параметра - бессмысленно и вредно (Hardware Fault это доказывает): параметр pData содержит указатель на некий внешний буфер байтов. То есть, по соглашению о передаче параметров в ARM С, указатель содержится в регистре R1. Оператор пытается взять указатель на регистр R1, а это вам не MSC-51 архитектура, где все регистры есть одновременно и ячейки памяти. Значит, такая конструкция тоже не имеет права на жизнь: void yyy(int **); void xxx(int *a) { yyy(&a); } Компилятор в курсе, что у него в регистрах, а что в памяти. И переместит в случае необходимости. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 184 27 марта, 2014 Опубликовано 27 марта, 2014 · Жалоба То есть, по соглашению о передаче параметров в ARM С, указатель содержится в регистре R1. Оператор пытается взять указатель на регистр R1, а это вам не MSC-51 архитектура, где все регистры есть одновременно и ячейки памяти. Прежде чем писать, потрудились-бы хотя-бы в листинг заглянуть: при взятии адреса аргумента функции переданного в регистре, компилятор переместит его на стек (внутри функции). Процессор не любит словные (32-битовые) обращения по невыровненному адресу. "Любит-нелюбит" - это к девушкам. А вообще Cortex-M вполне нормально переваривает невыровненные доступы (в отличие от ARM7/9) (исключение - инструкции LDM, STM, LDRD, STRD, но вряд-ли компилятор их там нагенерил). Опционально можно разрешить Usage Fault при невыровненном доступе. Это делается в регистре CCR Cortex-ядра. Но по дефолту это там запрещено. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
k000858 0 28 марта, 2014 Опубликовано 28 марта, 2014 · Жалоба Проблема решилась. пошагал отладчиком и все такое. после того как сделал структуры (для инициализации DMA на Tx и RX и тд) глобальными (видимо стека не хватало на локальные переменные) и изменил порядок вызова функций все задышало. + для работы новых HAL библиотек необходимо юзать прерывания для dma. ну в общем там ни мало особенностей появилось по сравнению со стрыми SPL Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 119 28 марта, 2014 Опубликовано 28 марта, 2014 · Жалоба Проблема решилась. пошагал отладчиком и все такое.А не могли бы вы выложить весь текст функции HAL_UART_Receive_DMA()? А то тут уже пошли теологические споры и было бы хорошо поставить жирную точку. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
k000858 0 28 марта, 2014 Опубликовано 28 марта, 2014 · Жалоба А не могли бы вы выложить весь текст функции 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; } } причина хардфаулта крылась либо в использовании локальных структур (а размер у них не малый), что негативно сказывалось на стеке, либо в некорректном порядке инициализации. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 119 28 марта, 2014 Опубликовано 28 марта, 2014 · Жалоба на самом деле в самой функции ошибки нет. все работает корректно с передачей вышеописанных переменных. Да, но вот конкретно этот кусочек кода - шедевр 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 заодно). Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
k000858 0 28 марта, 2014 Опубликовано 28 марта, 2014 · Жалоба ну библы новые, может причешут! зато удалось реализовать работу DS18B20 по UART+DMA за пол дня, и даташит открыть пришлось только для того, что бы узнать какой поток/канал DMA активировать для нужного UART'а. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Golikov 0 28 марта, 2014 Опубликовано 28 марта, 2014 · Жалоба ну не за пол дня, а за сутки все таки... тем более вы пишите причина хардфаулта крылась либо в использовании локальных структур (а размер у них не малый), что негативно сказывалось на стеке, либо в некорректном порядке инициализации. либо в чем то еще, и вы не уверены в чем, и то что оно сейчас завелось, не значит что когда в проекте появиться еще что-то оно так же случайно не выключится... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться