Nosaer 0 29 июня, 2017 Опубликовано 29 июня, 2017 (изменено) · Жалоба Доброго времени суток. Столкнулся со следующей проблемой. В данном случае SPI работает корректно: uint8_t BufReadMR45[3] = {0x03,0x00,0x00}; uint8_t DataReadMR45[5] = {0}; void ReadMR45(void) { HAL_GPIO_WritePin(PortCSMR45, PinCSMR45, GPIO_PIN_RESET); // CS on HAL_Delay(1); HAL_SPI_Transmit(&hspi1, &BufReadMR45[0], 3, 1000); // Отправка данных по SPI HAL_SPI_Receive(&hspi1, &DataReadMR45[0], 1, 1000); // Получение данных по SPI HAL_GPIO_WritePin(GPIOB, GPIO_PIN_1, GPIO_PIN_SET); HAL_GPIO_WritePin(PortCSMR45, PinCSMR45, GPIO_PIN_SET); // CS off HAL_UART_Transmit(&huart1, &DataReadMR45[0], 1, 0x1000); // Отправляю данные по UART ByteMR45_R = ByteMR45_R + 1; } Если я изменю функцию: HAL_SPI_Receive(&hspi1, &DataReadMR45[0], 5, 1000); Чтобы считывать сразу больше 1 байта, программа зависает. Отладчик приводит в HardFault_Handler(void) Процессор STM32F030, до этого работал с серией F4, таких проблем вроде как не было. Изменено 21 ноября, 2022 пользователем haker_fox Уточнил название темы, добавил теги, переместил в нужный раздел. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Kabdim 0 29 июня, 2017 Опубликовано 29 июня, 2017 · Жалоба 80% проблем портирования с M3-M7 на M0/0+ - невыравненный доступ к памяти. Посмотрите на какой инструкции выскакивает хард фолт. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
x893 35 29 июня, 2017 Опубликовано 29 июня, 2017 · Жалоба А что бы отладчиком не пройти по шагам и посмотреть где падает. Выравнивание немного из другой оперы в этом коде. Еще неплохо при отладке поставить DBGMCU_APB1_FZ_DBG_I2C1_SMBUS_TIMEOUT (если конечно I2C1 - но телепатией не владею) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 119 29 июня, 2017 Опубликовано 29 июня, 2017 · Жалоба (если конечно I2C1 - но телепатией не владею)В заголовке вообще-то SPI. Да и функция называется HAL_SPI_Receive() Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
x893 35 29 июня, 2017 Опубликовано 29 июня, 2017 · Жалоба Согласен - лопухнулся с I2C. Но с SPI еще проще отладчиком пройтись. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Nosaer 0 30 июня, 2017 Опубликовано 30 июня, 2017 · Жалоба 80% проблем портирования с M3-M7 на M0/0+ - невыравненный доступ к памяти. Посмотрите на какой инструкции выскакивает хард фолт. Программа не портировалась, а пишется полностью по новой. На приложенном скриншоте, следующим шагом программа уходит в HardFault_Handler(void) У самого знаний не хватает, почему делает так. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
x893 35 30 июня, 2017 Опубликовано 30 июня, 2017 · Жалоба А что стоит в инициализациии SPI ? hspi->Init.DataSize = ??? Читаете 16 битными словами а буфер даете на 5 байт. Программе конечно пофиг - она читает 16 бит и записывает и 2 к указателю прибывит. Кто такое издевательство выдержит ? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Nosaer 0 30 июня, 2017 Опубликовано 30 июня, 2017 · Жалоба /* SPI1 init function */ static void MX_SPI1_Init(void) { hspi1.Instance = SPI1; hspi1.Init.Mode = SPI_MODE_MASTER; hspi1.Init.Direction = SPI_DIRECTION_2LINES; hspi1.Init.DataSize = SPI_DATASIZE_8BIT; hspi1.Init.CLKPolarity = SPI_POLARITY_LOW; hspi1.Init.CLKPhase = SPI_PHASE_1EDGE; hspi1.Init.NSS = SPI_NSS_SOFT; hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_256; hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB; hspi1.Init.TIMode = SPI_TIMODE_DISABLE; hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE; hspi1.Init.CRCPolynomial = 7; hspi1.Init.CRCLength = SPI_CRC_LENGTH_DATASIZE; hspi1.Init.NSSPMode = SPI_NSS_PULSE_ENABLE; if (HAL_SPI_Init(&hspi1) != HAL_OK) { _Error_Handler(__FILE__, __LINE__); } } Проинициалированно на 8 бит, и считываю по 8. Не совсем понял про 16 бит. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 119 30 июня, 2017 Опубликовано 30 июня, 2017 · Жалоба Проинициалированно на 8 бит, и считываю по 8.У STM32F0 немного перемудрили с регистром данных - он 16-битный и если хотите передавать байты - надо их запихивать по два за раз (они назвали это "упаковка"). А когда количество байт нечетное и остается один последний - надо еще и битик управляющий выставить, типа "пихаю последние 8 бит и все". Не совсем понял про 16 бит.Ваш указатель pTxData лежит в R5 и имеет значение 0x20000047. Своим приведением *(uint16_t *) вы принуждаете компилятор использовать команду чтения 16 бит. А поскольку адрес в указател у вас не выровнен на границу двух байт, то вы и получаете исключение из-за невыровненного доступа. Пламенный привет писателям "библиотеки". Чтобы этот код работал на CM0(+), адрес начала вашего буфера должен быть кратен двум. Или же переписать этот код правильно: если ваш компилятор умеет указатели на упакованные данные, надо объявить pTxData указателем на упакованные данные (как-то наподобие uint16_t __packed * pTxData). Или же объявить его указателем на uint8_t, вычитывать с его помощью два байта, вручную собирать их в 16-битное слово и уже это слово запихивать в DR. Я бы использовал второй вариант - объектный код получится такой же, а исходник останется портируемым на другие компиляторы. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Nosaer 0 30 июня, 2017 Опубликовано 30 июня, 2017 · Жалоба У STM32F0 немного перемудрили с регистром данных - он 16-битный и если хотите передавать байты - надо их запихивать по два за раз (они назвали это "упаковка"). А когда количество байт нечетное и остается один последний - надо еще и битик управляющий выставить, типа "пихаю последние 8 бит и все". Ваш указатель pTxData лежит в R5 и имеет значение 0x20000047. Своим приведением *(uint16_t *) вы принуждаете компилятор использовать команду чтения 16 бит. А поскольку адрес в указател у вас не выровнен на границу двух байт, то вы и получаете исключение из-за невыровненного доступа. Пламенный привет писателям "библиотеки". Чтобы этот код работал на CM0(+), адрес начала вашего буфера должен быть кратен двум. Или же переписать этот код правильно: если ваш компилятор умеет указатели на упакованные данные, надо объявить pTxData указателем на упакованные данные (как-то наподобие uint16_t __packed * pTxData). Или же объявить его указателем на uint8_t, вычитывать с его помощью два байта, вручную собирать их в 16-битное слово и уже это слово запихивать в DR. Я бы использовал второй вариант - объектный код получится такой же, а исходник останется портируемым на другие компиляторы. Теперь все понял) Спасибо большое) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
x893 35 30 июня, 2017 Опубликовано 30 июня, 2017 · Жалоба Если посмотреть то перед передачей и приемом есть проверка if ((hspi->Init.DataSize > SPI_DATASIZE_8BIT) || (Size > 1U)) { /* in this case, 16-bit access is performed on Data So, check Data is 16-bit aligned address */ assert_param(IS_SPI_16BIT_ALIGNED_ADDRESS(pData)); } то есть делается проверка что указатель выравнен на 2 при передаче больше 1 байта. Можно это проигнорировать конечно и получить, то что получилось. Обычно компилятор делает сам выравнивание переменных по 4, что бы такого не было. Но всё можно руками поменять. С __packed надо аккуратно обращаться. А запись/чтение по 2 байта там есть при счетчике > 1. Он конечно развесистый, но какой есть. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться