單片機
返回首頁

【STM32】HAL庫調用HAL_SPI_Transmit出現HartFault問題

2021-09-03 來源:eefocus

問題描述:

HAL庫調用硬件SPI發送函數HAL_SPI_Transmit會導致程序進入HartFault


// flash 頁大小(字節)

#define FLASH_SPI_PAGE_SIZE       (256)


static uint8_t write_buffer[FLASH_SPI_PAGE_SIZE + 4];


spi1_write(W25QXX_CHANNEL, (uint8_t *)write_buffer, (length + 4));


/**

 * @brief SPI寫入

 * @param *txBuffer 發送字節集

 * @param txLength 發送長度

 * @return spi發送的長度

 * */

uint32_t spi1_write(SPIChannel channel, uint8_t *txBuffer, uint32_t txLength)

{

  if(channel == W25QXX_CHANNEL)

  {

    W25QXX_CHANNEL_ON;

  }


  HAL_SPI_Transmit(&hspi2, txBuffer, txLength, 500);


  if(channel == W25QXX_CHANNEL)

  {

    W25QXX_CHANNEL_OFF;

  }


  return txLength;

}


原因分析:

Debug發現進入HartFault之前最后一句話是

在這里插入圖片描述

是該揭開它真正面紗的時候了:我們再看出現問題的那條語句:


hspi->Instance->DR = *((uint16_t *)pData);


再看我們數組的定義:uint8_t

出現問

題這條語句把我們定義的uint8_t 數組轉換成了uint16_t 同時進行半字的操作(同時操作兩個byte)。這樣看確實提高了執行效率,但是卻也埋下了隱患。


產生這樣的問題,我們就不得不扯得更遠一點,arm內核對數據的非對齊數據訪問。


Arm對內存的訪問支持字(4byte)、半字(2byte)、字節(1byte)的直接訪問,但是呢他們是有一定的要求的:


存取字時要求地址按字對齊,也就是地址要是4的整數倍,如0x0000、0x0004、0x0008(該地址只是舉例,mcu的地址分配請參考具體手冊的地址映射圖)

存取半字是要求地址按半字對齊,也就是地址是2的倍數,這樣假如通過0x0001、0x0003這樣非2倍數的地址來讀取一個半字就會產生錯誤

存取字節簡單,只要地址不超范圍就可以

這么看來是不是有點清晰了,我們出現錯誤的地方不就是在操作一個半字(uint16占用兩個byte也就是半字),那么進入到了hardfault應該就是操作了非半字對齊的地址。


下面我們將write_buffer地址打印出來:


rtt_printf("0x%08xn",write_buffer);

在這里插入圖片描述

很顯然,這個地址并不是非半字對齊的地址。

解決方案:

將write_buffer定義成uint32_t即四字節對齊即可。

static uint32_t write_buffer[(FLASH_SPI_PAGE_SIZE + 4 )>>2];

在這里插入圖片描述

進入單片機查看更多內容>>
相關視頻
  • TI 新一代 C2000? 微控制器:全方位助力伺服及馬達驅動應用

  • MSP430電容觸摸技術 - 防水Demo演示

  • 直播回放: Microchip Timberwolf? 音頻處理器在線研討會

  • 新唐 8051單片機教程

  • 基于靈動MM32W0系列MCU的指夾血氧儀控制及OTA升級應用方案分享

  • 基于靈動MM32SPIN系列MCU的無感FOC便攜冰箱應用方案分享

    相關電子頭條文章
萝卜大香蕉