STM32給FPGA的外掛FLASH進行升級

STM32給FPGA的外掛FLASH進行升級

      • 一、電路方案設計
      • 二、軟件寫FLASH
      • 三、解決第一次燒錄后FPGA無法啟動的問題

前言:
一個復雜的嵌入式中,如果對某些實時性要求極高的情況下勢必會使用到FPGA來保證,這里面牽扯到給FPGA的程序升級問題,一般采用負責邏輯處理的一個MCU來完成,實際就是對存儲FPGA的這個flash進行讀寫操作。

一、電路方案設計

1、FLASH的(MOSI/MISO/CLK/CS)既要連接FPGA又要連接STM32,所以要設計一個單刀雙置的開關。(注意:FLASH_D2和FLASH_D3是直接接入FPGA的,因為FPGA需要使用flash的四線模式)
在這里插入圖片描述

二、軟件寫FLASH

1、mx25l.c

#include <stdio.h>
#include "mx25l.h"/******************************************************* @brief  SPI寫數據* @param  data 要寫入mx25l的數據 * @retval 返回一個字節
******************************************************/
uint8_t SPI1_WriteByte(uint8_t data)
{	//等待發送完成while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);//發送數據SPI_I2S_SendData(SPI1, data);//等待接收完成while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET);return SPI_I2S_ReceiveData(SPI1);	
}/******************************************************* @brief  SPI讀數據* @param  空* @retval 返回讀取到的字節
******************************************************/
uint8_t SPI1_ReadByte(void)
{return(SPI1_WriteByte(0xff));
}/********************************* @brief  mx25l的寫使能* @param  None* @retval None******************************/
void Write_enable(void)
{//CS=0, 選中芯片FLASH_CS_L();//MCU發送寫使能命令0x06	SPI_SendbyteSPI1_WriteByte(0x06);//CS=1;//釋放芯片FLASH_CS_H();
}/********************************* @brief  mx25l的寫失能* @param  None* @retval None******************************/
void Write_disable(void)
{//CS=0, 選中芯片FLASH_CS_L();//MCU發送寫失能命令0x04	SPI_SendbyteSPI1_WriteByte(0x04);//CS=1;//釋放芯片FLASH_CS_H();
}/***************************************** @brief  讀mx25l狀態寄存器* @param  None* @retval None**************************************/
void Read_ststus(void)
{u8 sta=0;//接收狀態寄存器的值//CS=0;//選中芯片FLASH_CS_L();//MCU發送讀狀態命令	0x05SPI1_WriteByte(0x05);do{sta = SPI1_ReadByte();}while((sta&(1<<0))==1);//CS=1;//釋放芯片FLASH_CS_H();
}
#if 0
u8 SPI_Flash_ReadSR(void)   
{  u8 byte=0;   FLASH_CS_L();                          //使能器件   SPI1_WriteByte(0x05);              //發送讀取狀態寄存器命令    byte=SPI1_ReadByte();         //讀取一個字節  FLASH_CS_H();                          //取消片選     return byte;   
} 
void SPI_Flash_Wait_Busy(void)  
{   while ((SPI_Flash_ReadSR()&0x01)==0x01);   // 等待WIP位清空
} 
#endif/************************************************************************** @brief  寫mx25l狀態寄存器QEbit,防止空板第一次下載程序FPGA無法啟動現象* @param  None* @retval None************************************************************************/
void QEBit_Set(void)
{u8 sta=0; // 接收狀態寄存器的值//寫使能Write_enable();//CS=0;//選中芯片FLASH_CS_L();//MCU發送讀狀態命令	0x05SPI1_WriteByte(0x05);sta = SPI1_ReadByte();//CS=1;//釋放芯片FLASH_CS_H();sta |= 0x40;//CS=0;//選中芯片FLASH_CS_L();//MCU發送寫狀態命令	0x01SPI1_WriteByte(0x01);SPI1_WriteByte(sta);//CS=1;//釋放芯片FLASH_CS_H();Write_disable();
}/***************************************************** @brief  MCU 寫數據到 mx25l* @param  addr 24位地址* @param  data 要寫入的數據* @retval None* @attention 寫數據之前一定要擦除芯片**************************************************/
void Mx25l_WriteByte(uint32_t addr, uint8_t data)
{	//打開寫使能Write_enable();//CS=0;//選中芯片FLASH_CS_L();//MCU發送頁編程命令  0x02SPI1_WriteByte(0x02);//發送24位地址SPI1_WriteByte((u8)(addr>>16));SPI1_WriteByte((u8)(addr>>8));SPI1_WriteByte((u8)(addr));//MCU發送寫入的數據SPI1_WriteByte(data);//CS=1;//釋放芯片FLASH_CS_H();//讀狀態Read_ststus();
}/***************************************************** @brief  MCU頁寫數據到 mx25l* @param  pBuffer  要寫的數組* @param  addr     24位地址* @param  Nb_bytes 要寫入的數據長度* @retval None* @attention       寫數據之前一定要擦除芯片**************************************************/
void Mx25l_Write_Page(u8* pBuffer, u32 addr, u16 Nb_bytes)
{u16 i;  Write_enable(); //SET WEL FLASH_CS_L(); //使能器件   SPI1_WriteByte(0x02); //發送寫頁命令   SPI1_WriteByte((u8)(addr>>16)); //發送24bit地址    SPI1_WriteByte((u8)(addr>>8));   SPI1_WriteByte((u8)(addr));   for(i=0; i<Nb_bytes; i++){SPI1_WriteByte(pBuffer[i]); //循環寫數  }FLASH_CS_H(); //取消片選 Read_ststus();	//等待寫入結束
} /***************************************************** @brief  MCU 無校驗寫數據到 mx25l* @param  pBuffer  要寫的數組* @param  addr     24位地址* @param  Nb_bytes 要寫入的數據長度* @retval None* @attention       寫數據之前一定要擦除芯片**************************************************/
void Mx25l_Write_NoCheck(u8* pBuffer,u32 addr,u16 Nb_bytes)   
{ 			 		 u16 PageRemain;	   PageRemain = 256 - addr%256; //單頁剩余的字節數		if(Nb_bytes <= PageRemain) { //不大于256個字節Mx25l_Write_Page(pBuffer, addr, Nb_bytes); }else {Mx25l_Write_Page(pBuffer, addr, PageRemain);addr += PageRemain;Mx25l_Write_Page(pBuffer+PageRemain, addr, Nb_bytes-PageRemain);}	    
} /******************************************************** @brief  MCU從 mx25l 讀數據* @param  addr 24位地址* @param  data 存放讀出的數據* @param  size 要讀的字節長度(不要太大,否則RAM承受不了)* @retval None*****************************************************/
void Mx25l_Read_data(u32 addr, u8 *data, u32 size)
{uint32_t i=0;//接收數據的循環變量//CS=0;//選中芯片FLASH_CS_L();//MCU發送讀數據命令  0x03SPI1_WriteByte(0x03);//MCU發送開始讀的地址SPI1_WriteByte((u8)(addr>>16));SPI1_WriteByte((u8)(addr>>8));SPI1_WriteByte((u8)(addr));//MCU接收數據for(i=0; i<size; i++){data[i] = SPI1_ReadByte();}//CS=1;//釋放芯片FLASH_CS_H();  
}/******************************************************************* @brief  Sector Write* @param  nSector 第幾個扇區* @param  pBuffer 數據* @retval None*****************************************************************/
void Mx25l_Write_Sector(uint32_t nSector, uint8_t* pBuffer)
{	int i,j;//扇區號轉為地址nSector *= FLASH_SECTOR_SIZE;//一個扇區需要幾個頁for(j=0; j<FLASH_PAGES_PER_SECTOR; j++){Write_enable();                  //SET WELFLASH_CS_L();SPI1_WriteByte(0x02);SPI1_WriteByte((nSector >> 16) & 0xff);SPI1_WriteByte((nSector >> 8) & 0xff);SPI1_WriteByte(nSector & 0xff);for(i=0; i<FLASH_PAGE_SIZE; i++){		SPI1_WriteByte(pBuffer[i]);}pBuffer += FLASH_PAGE_SIZE;nSector += FLASH_PAGE_SIZE;FLASH_CS_L();Read_ststus();}
}/******************************************************************* @brief  Sector Read* @param  nSector 第幾個扇區* @param  pBuffer 存放數據* @retval None*****************************************************************/
void Mx25l_Read_Sector(uint32_t nSector, u8* pBuffer)
{	uint16_t i;//扇區號轉為地址nSector *= FLASH_SECTOR_SIZE;FLASH_CS_L();SPI1_WriteByte(0x03);SPI1_WriteByte((u8)(nSector >> 16));SPI1_WriteByte((u8)(nSector >> 8));SPI1_WriteByte((u8)(nSector));for(i=0;i<FLASH_SECTOR_SIZE;i++){	pBuffer[i] = SPI1_ReadByte();//usb_printf("%02x, ", pBuffer[i]);}FLASH_CS_L();Read_ststus();
}/******************************** @brief  擦除整個芯片* @param  None* @retval None*****************************/
void Chip_erase(void)
{//printf("chip erase starting...\r\n");Write_enable();//CS=0;//選中芯片FLASH_CS_L();//MCU發送芯片擦除命令  0x60SPI1_WriteByte(0x60);//CS=1;//釋放芯片FLASH_CS_H();//讀狀態Read_ststus();//printf("chip erase complete...\r\n");
}

2、mx25l.h

#ifndef  _MX25L_H_
#define  _MX25L_H_#include "stm32f10x.h"
#include "stm32f10x_spi.h"#define FLASH_PAGE_SIZE		256
#define FLASH_SECTOR_SIZE	4096
#define FLASH_SECTOR_COUNT	4096
#define FLASH_BLOCK_SIZE	65536
#define FLASH_PAGES_PER_SECTOR	FLASH_SECTOR_SIZE/FLASH_PAGE_SIZE
#define FLASH_CS_H()        GPIO_SetBits(GPIOA, GPIO_Pin_4)
#define FLASH_CS_L()        GPIO_ResetBits(GPIOA, GPIO_Pin_4)
uint8_t SPI1_WriteByte(uint8_t data);
uint8_t SPI1_ReadByte(void);
void Write_enable(void);
void Write_disable(void);
void Read_ststus(void);
void QEBit_Set(void);
void Mx25l_WriteByte(uint32_t addr,uint8_t data);
void Mx25l_Write_Page(u8* pBuffer, u32 addr, u16 Nb_bytes);
void Mx25l_Write_NoCheck(u8* pBuffer,u32 addr,u16 Nb_bytes);
void Mx25l_Read_data(uint32_t addr, uint8_t *data, uint32_t size);
void Mx25l_Write_Sector(uint32_t nSector, uint8_t* pBuffer);
void Mx25l_Read_Sector(uint32_t nSector, u8* pBuffer);
void Chip_erase(void);#endif

三、解決第一次燒錄后FPGA無法啟動的問題

1、這個問題的原因是因為FPGA編譯使用的flash是4線模式,而flash默認是1線模式,所以升級完之后調用QEBit_Set();配飾flash為4線模式。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/86952.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/86952.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/86952.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Python 數據分析與可視化 Day 9 - 缺失值與異常值處理技巧

? 今日目標 熟練處理數據中的缺失值&#xff08;NaN、None&#xff09;學會識別和處理異常值&#xff08;outliers&#xff09;掌握常用的處理方法&#xff1a;填充、刪除、替換、標準差法、箱型圖法等為后續機器學習建模打好數據清洗基礎 &#x1f4da; 一、缺失值處理&…

概述-1-數據庫的相關概念

數據庫的相關概念 用戶通過SQL操作數據庫管理系統&#xff0c;再通過數據庫管理系統操作數據庫以及數據庫中的數據。 數據庫 數據庫是存儲數據的倉庫, 數據是有組織的進行存儲, DataBase簡稱&#xff08;DB&#xff09; 數據庫管理系統 操縱和管理數據庫的大型軟件, DataB…

可視化大屏展示

可視化大屏是一種將大量數據進行整合、分析&#xff0c;并以直觀、形象的可視化方式展示在大屏幕上的信息展示系統。主要組成部分分為2個&#xff1a;硬件設備、軟件系統。 一、大屏價值 1、數據可視化&#xff1a;將復雜的數據轉化為直觀的圖形、圖表和地圖等&#xff0c;使數…

服務器被入侵的常見跡象有哪些?

&#x1f6a8; 服務器被入侵的常見跡象 &#x1f7e2; 一、系統和資源異常 CPU、內存或網絡流量異常飆高 即使沒有業務負載&#xff0c;資源長期占滿。 磁盤空間突然被寫滿 可疑大文件或日志暴漲。 系統負載顯著升高 uptime、top 顯示 load average 異常。 &#x1f7e1;…

日本生活:日語語言學校-日語作文-溝通無國界(5)-題目:我的一天

日本生活&#xff1a;日語語言學校-日語作文-溝通無國界&#xff08;5&#xff09;-題目&#xff1a;我的一天 1-前言2-作文原稿3-作文日語和譯本&#xff08;1&#xff09;日文原文&#xff08;2&#xff09;對應中文&#xff08;3&#xff09;對應英文 4-老師評語5-自我感想&…

前端領域的技術熱點與深度解析

&#x1f525; 一、框架革新&#xff1a;React、Vue、Svelte 的進化方向 React 19 實驗版 Server Components 深化&#xff1a;支持流式渲染與異步狀態管理&#xff0c;SSR 性能提升40%。 并發模式優化&#xff1a;減少渲染阻塞&#xff0c;復雜交互場景延遲降低35%。 Vue 3…

【unity游戲開發——網絡】網絡游戲通信方案——強聯網游戲(Socket長連接)、 弱聯網游戲(HTTP短連接)

注意&#xff1a;考慮到熱更新的內容比較多&#xff0c;我將熱更新的內容分開&#xff0c;并全部整合放在【unity游戲開發——網絡】專欄里&#xff0c;感興趣的小伙伴可以前往逐一查看學習。 文章目錄 一、聯網游戲類型劃分二、核心通信協議對比三、開發選擇指南專欄推薦完結 …

Java-60 深入淺出 分布式服務Paxos 算法優化 如何保證Paxos算法的活性

點一下關注吧&#xff01;&#xff01;&#xff01;非常感謝&#xff01;&#xff01;持續更新&#xff01;&#xff01;&#xff01; &#x1f680; AI篇持續更新中&#xff01;&#xff08;長期更新&#xff09; 目前2025年06月16日更新到&#xff1a; AI煉丹日志-29 - 字節…

一階線性雙曲型偏微分方程組的特征值與通解分析

問題3 求系統 U u + A U x = 0 U_u + A U_x = 0 Uu?+AUx?=0 的特征并寫出通解,其中矩陣 A A A 如下: A 1 = ( 3 2 1 0 2 1 0 0 1 ) , A 2 = ( 3 2 1 0 2 1 0 0 ? 1 ) , A_1 = \begin{pmatrix} 3 & 2 & 1 \\ 0 & 2 & 1 \\ 0 & 0 & 1 \end{pmatr…

解鎖AI無限潛能!景聯文科技數據產品矩陣再升級:多語言題庫、海量語料、垂域代碼庫,全面賦能大模型訓練

景聯文科技持續聚焦AI數據需求前沿&#xff0c;全新發布包含中文題庫數據集、英文題庫數據集、算法代碼數據庫、英文語料、中文語料、垂直領域數據、小語種數據在內的七大高質量數據集產品系列。 此次發布的數據集覆蓋廣泛的應用場景&#xff0c;通過嚴格的清洗與結構化處理&am…

OSPF(開放最短路徑優先)

一、ospf簡介 OSPF是基于鏈路狀態的內部網關協議&#xff0c;與距離矢量協議不同&#xff0c;鏈路狀態協議通告的是鏈路狀態而不是路由表。OSPF是用于自治系統&#xff08;AS&#xff09;內部的路由決策,特點有&#xff0c;收斂速度快&#xff0c;安全性好&#xff0c;避免環路…

全面擁抱vue3

Vue 3 性能全面解析&#xff1a;為何性能飛躍提升 Vue 3 在性能方面實現了質的飛躍&#xff0c;相比 Vue 2 在多個維度都有顯著提升。以下是 Vue 3 性能優化的全面解析&#xff1a; 一、核心架構優化 1. 響應式系統重寫&#xff08;Proxy 替代 defineProperty&#xff09; …

C#最佳實踐:考慮為類重寫ToString()方法

C#最佳實踐:考慮為類重寫ToString()方法 在 C# 編程的日常開發中,ToString()方法是一個既基礎又容易被忽視的重要成員。它是System.Object類的虛方法,所有類都繼承自System.Object,這意味著每個類都擁有ToString()方法。然而,默認的ToString()方法往往無法滿足實際需求,…

從0開始學習計算機視覺--Day05--優化

除了得到最小的W之外&#xff0c;如何節省這個探索最優W的過程&#xff0c;也是很重要的一點。假如把這個過程比作從山上的頂點開始下山&#xff0c;把圖中必定游玩的經典比作最優權重&#xff0c;那么節省的過程&#xff0c;就是找到下山的最短路徑的過程。而在下山的過程中&a…

OpenCV計算機視覺實戰(14)——直方圖均衡化

OpenCV計算機視覺實戰&#xff08;14&#xff09;——直方圖均衡化 0. 前言1. CLAHE 自適應均衡1.1 應用場景1.2 實現過程 2. 直方圖反向投影2.1 應用場景2.2 實現過程 3. 基于顏色的目標追蹤小結系列鏈接 0. 前言 在圖像處理與計算機視覺領域&#xff0c;直方圖技術是最直觀且…

基于uniapp的老年皮膚健康管理微信小程序平臺(源碼+論文+部署+安裝+售后)

感興趣的可以先收藏起來&#xff0c;還有大家在畢設選題&#xff0c;項目以及論文編寫等相關問題都可以給我留言咨詢&#xff0c;我會一一回復&#xff0c;希望幫助更多的人。 系統背景 近年來&#xff0c;我國人口老齡化進程不斷加快&#xff0c;據國家統計局數據顯示&#…

MySQL(106)如何設計分片鍵?

設計分片鍵&#xff08;Sharding Key&#xff09;是數據庫分片的核心&#xff0c;它決定了將數據分配到不同分片的方式。一個好的分片鍵應該能夠均衡地分布數據&#xff0c;避免熱點問題&#xff0c;提高查詢性能。下面將詳細介紹如何設計分片鍵&#xff0c;并結合代碼進行說明…

汽車一鍵啟動升級手機控車

汽車一鍵啟動升級手機控車實現手機遠程啟動&#xff0c;不改變原車任何功能且全部免接線。升級后原車遙控器能在有效范圍內啟動車輛。移動管家手機控車一鍵啟動系統用手機遠程控制&#xff0c;完美兼容原車遙控器。支持長安、別克、寶馬、奧迪等眾多系列車型&#xff0c;市場99…

【開源項目】「安卓原生3D開源渲染引擎」:Sceneform?EQR

「安卓原生3D開源渲染引擎」&#xff1a;Sceneform?EQR 渲染引擎 “那一夜凌晨3點&#xff0c;第一次提交 PR 的手在抖……”——我深刻體會這種忐忑與激動。 倉庫地址&#xff1a;(https://github.com/eqgis/Sceneform-EQR)。 一、前言&#xff1a;開源對我意味著什么 DIY 的…

建造者模式 - Flutter中的樂高大師,優雅組裝復雜UI組件!

痛點場景&#xff1a;復雜的對話框配置 假設你需要創建一個多功能對話框&#xff1a; CustomDialog(title: 警告,content: 確定要刪除嗎&#xff1f;,titleStyle: TextStyle(fontSize: 20, color: Colors.red),contentStyle: TextStyle(fontSize: 16),backgroundColor: Color…