STM32FreeRTOS 使用QSPI驱动nandFlash

STM32FreeRTOS 使用QSPI驱动nandFlash

不清楚为什么STM32同时打开3个以上的音频文件时会出现播放问题,所以更换方案。因为SRAM的内存空间过小,用于存储音频文件不适合,所以使用大小为128MByte的nandFlash。

nandFlash使用华邦的W25N01GVZEIG,单片机使用STM32F412ZET6。
在这里插入图片描述
驱动分享:
w25n01g.c

#include "w25n01g.h"
#include "string.h" 

extern QSPI_HandleTypeDef hqspi;

static void my_delay(uint32_t counter){
	while(counter--);
}
uint8_t W25NXX_Init(){
	uint32_t quad_bk1;
	W25NXX_ReadID(& quad_bk1 );
	if( quad_bk1 != 0xefaa21 ) return 0;
	W25NXX_Write_SR(W25NXX_StatusReg1,0x00);
	W25NXX_Write_SR(W25NXX_StatusReg2 , 0x18 );
	return 1;
}

//write enble instruction is neede befor the erase and write 
// set the WEL bit
void W25NXX_Write_Enable(){
	QSPI_CommandTypeDef cmd = {0};
	cmd.Instruction = W25NXX_WriteEnable;
	cmd.InstructionMode = QSPI_INSTRUCTION_1_LINE;
	HAL_QSPI_Command(&hqspi , &cmd , W25NXX_QUAD_TIMEOUT);
}
//W25NXX write prohibited
//Clear WEL bit
void W25NXX_Write_Disable(void)   
{  
	QSPI_CommandTypeDef cmd = {0};
	cmd.Instruction = W25NXX_WriteDisable;
	cmd.InstructionMode = QSPI_INSTRUCTION_1_LINE;
	HAL_QSPI_Command(&hqspi , &cmd , W25NXX_QUAD_TIMEOUT);
} 
//set rest instruction
//befor initialize
void W25NXX_reset(){
	QSPI_CommandTypeDef cmd = {0};
	cmd.Instruction = W25NXX_RESET;
	cmd.InstructionMode = QSPI_INSTRUCTION_1_LINE;
	HAL_QSPI_Command(&hqspi , &cmd , W25NXX_QUAD_TIMEOUT);
	HAL_Delay(50);
}

//Read the status register of W25NXX, W25NXX has 3 status registers
//Status register 1: add = 0xAx
//BIT7 6 5 4 3 2 1 0
//SRP0 BP3 BP2 BP1 BP0 TB WP_E SRP1
//Status register 2: add = 0xBx
//BIT7 6 5 4 3 2 1 0
//OTP-L OTP-E SR1-L BUF (R) (R) (R)
//Status register 3: add = 0xCx
//BIT7 6 5 4 3 2 1 0
//(R) LUT-F ECC1 ECC0 / P-FAIL E-Fail WEL BUSSY
//Return value: status register value
void W25NXX_ReadSR(uint8_t ADD,uint8_t* SR1)   
{  
	uint8_t byte[2]; 
	QSPI_CommandTypeDef cmd = {0};
	cmd.Instruction = W25NXX_ReadStatusReg;
	cmd.InstructionMode = QSPI_INSTRUCTION_1_LINE;
	cmd.AlternateByteMode = QSPI_ALTERNATE_BYTES_1_LINE;
	cmd.AlternateBytesSize = QSPI_ALTERNATE_BYTES_8_BITS;
	cmd.AlternateBytes = ADD ;
	cmd.DataMode = QSPI_DATA_1_LINE;
	cmd.NbData = 1;
	HAL_QSPI_Command(&hqspi , &cmd , W25NXX_QUAD_TIMEOUT);
	HAL_QSPI_Receive(&hqspi , byte , W25NXX_QUAD_TIMEOUT);
	*SR1 = byte[0];
}   
//Write W25NXX status register
void W25NXX_Write_SR(uint8_t ADD,uint8_t sr)   
{ 
	QSPI_CommandTypeDef cmd = {0};
	uint32_t tick_start;
	cmd.Instruction = W25NXX_WriteStatusReg;
	cmd.InstructionMode = QSPI_INSTRUCTION_1_LINE;
	cmd.AlternateByteMode = QSPI_ALTERNATE_BYTES_1_LINE;
	cmd.AlternateBytesSize = QSPI_ALTERNATE_BYTES_16_BITS;
	cmd.AlternateBytes = (uint32_t)((ADD << 8) | sr);
	HAL_QSPI_Command(&hqspi , &cmd , W25NXX_QUAD_TIMEOUT);
	//Wait for the end of writing
	tick_start = HAL_GetTick();
	while( W25NXX_get_BUSSY() ){
		if( HAL_GetTick() - tick_start > W25NXX_TIMOUT ){
			break;
		}
	} 
} 
//return 1 if the BUSSY bit is set
uint8_t W25NXX_get_BUSSY(){
	uint8_t quad_bk1_sr;
	W25NXX_ReadSR(W25NXX_StatusReg3,& quad_bk1_sr );
	return (quad_bk1_sr & 0x01);
}
// read manufacture ID of the chip the ID for  W25N01 is 0xEFAA21 
void W25NXX_ReadID(uint32_t * id1 )
{
	uint8_t temp[6];
	QSPI_CommandTypeDef cmd = {0};
	cmd.Instruction = W25NXX_JedecDeviceID;
	cmd.InstructionMode = QSPI_INSTRUCTION_1_LINE;
	cmd.DummyCycles = 8;
	cmd.DataMode = QSPI_DATA_1_LINE;
	cmd.NbData = 3;
	HAL_QSPI_Command(&hqspi , &cmd , W25NXX_QUAD_TIMEOUT);
	HAL_QSPI_Receive(&hqspi , temp , W25NXX_QUAD_TIMEOUT);
	*id1 =(temp[0]<<16) | (temp[1]<<8) | temp[2];
}    
// read one page up to 2048 bytes
//	NumByteToRead <= 2048
uint16_t W25NXX_Read_Page(uint8_t* pBuffer,uint32_t SectroReadAddr,uint32_t NumByteToRead)   
{ 
	uint32_t address = SectroReadAddr * W25NXX_SectorSize; // byte address
	uint32_t PageAdd = address >> 11;
	uint32_t tick_start;
	if( NumByteToRead == 0 ) return 0;
	if( NumByteToRead > W25N01_PageSize) NumByteToRead = W25N01_PageSize;
	if( NumByteToRead > W25N01_PageSize - (address & 0x7ff ) ) NumByteToRead = W25N01_PageSize - (address & 0x7ff);
	
	QSPI_CommandTypeDef cmd = {0};
	cmd.Instruction = W25NXX_PageRead;
	cmd.InstructionMode = QSPI_INSTRUCTION_1_LINE;
//	cmd.Address =  address >> 11 ; // page address = (address / W25N01_PageSize)
//	cmd.AddressMode = QSPI_ADDRESS_1_LINE;
//	cmd.AddressSize = QSPI_ADDRESS_16_BITS;
	cmd.DummyCycles = 8;
	cmd.DataMode = QSPI_DATA_1_LINE;
	cmd.NbData = 2 ;
	uint8_t buff[2];
	buff[0] = (PageAdd >> 8)& 0xff;
	buff[1] = (PageAdd & 0xff);
	HAL_QSPI_Command(&hqspi , &cmd , W25NXX_QUAD_TIMEOUT);	
	HAL_QSPI_Transmit(&hqspi ,buff , W25NXX_QUAD_TIMEOUT);
	//Wait for the bussy
	tick_start = HAL_GetTick();
	while( W25NXX_get_BUSSY() ){
		if( HAL_GetTick() - tick_start > W25NXX_TIMOUT ){
			return 0;
		}
	}  				 
	cmd.Instruction = W25NXX_FastRead;
	cmd.InstructionMode = QSPI_INSTRUCTION_1_LINE;
	cmd.Address = address &  0x7ff ; // column address = address & ( ( 1 << 11) - 1)
	cmd.AddressMode = QSPI_ADDRESS_1_LINE;
	cmd.AddressSize = QSPI_ADDRESS_16_BITS;
	cmd.DummyCycles = 8;
	cmd.DataMode = QSPI_DATA_4_LINES;
	cmd.NbData = NumByteToRead ;
	HAL_QSPI_Command(&hqspi , &cmd , W25NXX_QUAD_TIMEOUT);
	HAL_QSPI_Receive_DMA(&hqspi , pBuffer);
	//Wait for the end of writing
	tick_start = HAL_GetTick();
	while( W25NXX_get_BUSSY() ){
		if( HAL_GetTick() - tick_start > W25NXX_TIMOUT ){
			return 0;
		}
	} 
//	my_delay(2400); // roughly 5us
	return	NumByteToRead; // To check if the number of bytes read is less than expected. if the address is reaches the end of the page
}  
//SPI writes less than 2048 bytes of data in one page (0~65535)
//Write a maximum of (2048) bytes of data at the specified address
//pBuffer: data storage area
//WriteAddr: The address to start writing (maximum 27bit)
uint16_t W25NXX_Write_Page(uint8_t* pBuffer,uint32_t SectorWriteAddr,uint32_t NumByteToWrite)
{
	uint32_t address = SectorWriteAddr * W25NXX_SectorSize; // byte address
	uint32_t PageAdd = address >> 11;
	uint32_t tick_start;
	
	if( NumByteToWrite == 0 ) return 0;
	if( NumByteToWrite > W25N01_PageSize) NumByteToWrite = W25N01_PageSize;
	if( NumByteToWrite > W25N01_PageSize - (address & ( ( 1 << 11) - 1)) ) NumByteToWrite = W25N01_PageSize - (address & ( ( 1 << 11) - 1));
	
	QSPI_CommandTypeDef cmd = {0};
	cmd.Instruction = W25NXX_PageRead;
	cmd.InstructionMode = QSPI_INSTRUCTION_1_LINE;
//	cmd.Address =  address >> 11 ; // page address = (address / W25N01_PageSize)
//	cmd.AddressMode = QSPI_ADDRESS_1_LINE;
//	cmd.AddressSize = QSPI_ADDRESS_16_BITS;
	cmd.DummyCycles = 8;
	cmd.DataMode = QSPI_DATA_1_LINE;
	cmd.NbData = 2 ;
	uint8_t buff[2];
	buff[0] = (PageAdd >> 8)& 0xff;
	buff[1] = (PageAdd & 0xff);
	HAL_QSPI_Command(&hqspi , &cmd , W25NXX_QUAD_TIMEOUT);	
	HAL_QSPI_Transmit(&hqspi ,buff , W25NXX_QUAD_TIMEOUT);
	//Wait for the bussy
	tick_start = HAL_GetTick();
	while( W25NXX_get_BUSSY() ){
		if( HAL_GetTick() - tick_start > W25NXX_TIMOUT ){
			return 0;
		}
	}
	W25NXX_Write_Enable();	
	cmd.Instruction = W25NXX_LoadRandomProgramData;
	cmd.InstructionMode = QSPI_INSTRUCTION_1_LINE;
	cmd.Address = (address & 0x7ff ); // column address
	cmd.AddressMode = QSPI_ADDRESS_1_LINE;
	cmd.AddressSize = QSPI_ADDRESS_16_BITS;
	cmd.DataMode = QSPI_DATA_4_LINES;
	cmd.NbData = NumByteToWrite ;
	cmd.DummyCycles = 0;
	HAL_QSPI_Command(&hqspi , &cmd , W25NXX_QUAD_TIMEOUT);	
	HAL_QSPI_Transmit(&hqspi , pBuffer , W25NXX_QUAD_TIMEOUT);
	 //Wait for the end of writing
	tick_start = HAL_GetTick();
	while( W25NXX_get_BUSSY() ){
		if( HAL_GetTick() - tick_start > W25NXX_TIMOUT ){
			return 0;
		}
	} 				  
	cmd.Instruction = W25NXX_ProgramExec;
	cmd.InstructionMode = QSPI_INSTRUCTION_1_LINE;
//	cmd.Address = address >> 11;
//	cmd.AddressMode = QSPI_ADDRESS_1_LINE;
//	cmd.AddressSize = QSPI_ADDRESS_16_BITS;
	cmd.Address = 0;
	cmd.AddressMode = QSPI_ADDRESS_NONE;
	cmd.DataMode = QSPI_DATA_1_LINE;
	cmd.NbData = 2;
	cmd.DummyCycles = 8;
	buff[0] = (PageAdd >> 8)& 0xff;
	buff[1] = (PageAdd & 0xff);
	HAL_QSPI_Command(&hqspi , &cmd , W25NXX_QUAD_TIMEOUT);
	HAL_QSPI_Transmit(&hqspi ,buff , W25NXX_QUAD_TIMEOUT);
	//Wait for the end of writing
	tick_start = HAL_GetTick();
	while( W25NXX_get_BUSSY() ){
		if( HAL_GetTick() - tick_start > W25NXX_TIMOUT ){
			return 0;
		}
	} 
//	my_delay(4800); // roughly 10us
	return NumByteToWrite;// To check if the number of bytes written is less than expected. If the address is reaches the end of the page
} 
//Write SPI FLASH
//Write data of the specified length at the specified address
//This function has erase operation!
//pBuffer: data storage area
//SectorWriteAddr: The address of the satrt page to write
//NumByteToWrite: The number of bytes to be written 
void W25NXX_Write(uint8_t* pBuffer,uint32_t SectorWriteAddr,uint32_t NumByteToWrite)   
{    
	uint32_t WriteAdd = SectorWriteAddr,ReadAdd;
	uint32_t EraseAdd , NextBlock;
	uint8_t buff_read[W25N01_PageSize];
	uint16_t PageAddMod;
	uint8_t *pDataRead = pBuffer ;
	uint16_t NumPageToWrite = NumByteToWrite / W25N01_PageSize;
	uint8_t NeedErase = 0;
	uint32_t write_backup_address;
	uint32_t start;
	
	while(NumByteToWrite){
		
		EraseAdd = (uint32_t)( WriteAdd / W25N01_BlockSize ) * W25N01_BlockSize;
		NextBlock = EraseAdd + W25N01_BlockSize;
		write_backup_address = W25N01_LAST_BLOCK;
		
		for(uint16_t i = 0 ; i < NumPageToWrite ; i++){
			if( ( WriteAdd  + i ) == NextBlock ) break; // reached end of the block
			W25NXX_Read_Page(buff_read, WriteAdd  + i , W25N01_PageSize);
			for( uint16_t j = 0 ; j < W25N01_PageSize ; j++){
				if( buff_read[ j ] != 0xff ){
					NeedErase = 1;
					break;
				}
			}
			if( NeedErase == 1) break;
		}
		
		if(NeedErase){
			//uint8_t buff_repalce[ W25N01_EraseSize ] ;
			ReadAdd = EraseAdd;
//			for( uint8_t i = 0 ; i < W25N01_BlockSize ; i++){
//				W25NXX_Read_Page(&buff_repalce[ W25N01_PageSize * i ] , ReadAdd , W25N01_PageSize);
//				ReadAdd++;
//			}
			//W25NXX_Erase_Block256K(write_backup_address);
			start = HAL_GetTick();
			while( W25NXX_Erase_Block128K(write_backup_address) != 1 && HAL_GetTick() - start < 1000);
			for( uint8_t i = 0 ; i < W25N01_BlockSize ; i++){
				W25NXX_Read_Page(buff_read , ReadAdd , W25N01_PageSize);
				ReadAdd++;
				W25NXX_Write_Page( buff_read , write_backup_address , W25N01_PageSize);
				write_backup_address++;
			}
			//W25NXX_Erase_Block256K(EraseAdd);
			start = HAL_GetTick();
			while( W25NXX_Erase_Block128K(EraseAdd) != 1 && HAL_GetTick() - start < 1000);
			write_backup_address = W25N01_LAST_BLOCK;

			for(PageAddMod = 0; PageAddMod < W25N01_BlockSize ; PageAddMod++){
				if( PageAddMod < WriteAdd % W25N01_BlockSize || NumPageToWrite == 0){
					W25NXX_Read_Page(buff_read , write_backup_address , W25N01_PageSize);
					W25NXX_Write_Page( buff_read , EraseAdd , W25N01_PageSize);
				}else{
					W25NXX_Write_Page( pDataRead , WriteAdd , W25N01_PageSize);
					pDataRead += W25N01_PageSize;
					NumByteToWrite -= W25N01_PageSize;
					NumPageToWrite-- ;
					WriteAdd++;
					//if( NumPageToWrite == 0 )  break;
				}
				write_backup_address++;
				EraseAdd++;
			}
			
//			for(PageAddMod = WriteAdd % W25N01_BlockSize; PageAddMod < W25N01_BlockSize ; PageAddMod++){
				memcpy(&buff_repalce[ W25N01_PageSize * PageAddMod ] , pDataRead , W25N01_PageSize);
//				W25NXX_Write_Page( pDataRead , WriteAdd , W25N01_PageSize);
//
//				pDataRead += W25N01_PageSize;
//				NumByteToWrite -= W25N01_PageSize;
//				NumPageToWrite-- ;
//				WriteAdd++;
//				if( NumPageToWrite == 0 )  break;
//			}

//			for( uint8_t i = 0 ; i < W25N01_BlockSize ; i++){
//				W25NXX_Write_Page( &buff_repalce[ W25N01_PageSize * i ] , EraseAdd , W25N01_PageSize);
//				EraseAdd++;
//			}
		}
		else{ // does not need erase
			for(uint16_t i = 0 ; i < W25N01_BlockSize ; i++){
				if( ( WriteAdd  ) == NextBlock ) break; // reached end of the block
				W25NXX_Write_Page( pDataRead , WriteAdd , W25N01_PageSize);
				pDataRead += W25N01_PageSize;
				NumByteToWrite -= W25N01_PageSize;
				NumPageToWrite-- ;
				WriteAdd++;
				if( NumPageToWrite == 0 )  break;
			}
		}
		
		NeedErase = 0;
	}
}
//read an desired amount of bytes
void W25NXX_Read(uint8_t* pBuffer,uint32_t SectorReadAddr,uint32_t NumByteToRead)
{
	uint32_t ReadAdd = SectorReadAddr;
	uint16_t NumPageToRead = NumByteToRead / W25N01_PageSize;
	for(uint16_t i =0 ; i < NumPageToRead ; i++){
		W25NXX_Read_Page( &pBuffer[ W25N01_PageSize * i ] , ReadAdd , W25N01_PageSize);
		ReadAdd ++;
	}	
}

//Erase a one blocks of. 64 * 2048 byte
//block_add: The sector address is set according to the actual capacity
//Minimum time to block a sector: 150ms
uint8_t W25NXX_Erase_Block128K(uint32_t block_add)   
{   
	uint32_t tick_start;
  W25NXX_Write_Enable();	 
	//Wait for end of earase
	tick_start = HAL_GetTick();
	while( W25NXX_get_BUSSY() ){
		if( HAL_GetTick() - tick_start > W25NXX_TIMOUT ){
			return 0;
		}
	}
	QSPI_CommandTypeDef cmd = {0};
	cmd.Instruction = W25NXX_BlockErase;
	cmd.InstructionMode = QSPI_INSTRUCTION_1_LINE;
	cmd.DummyCycles = 8;
	cmd.DataMode = QSPI_DATA_1_LINE;
	cmd.NbData = 2;
//	cmd.Address = block_add;
//	cmd.AddressMode = QSPI_ADDRESS_1_LINE;
//	cmd.AddressSize = QSPI_ADDRESS_16_BITS;
	uint8_t buff[2];
	buff[0] = (block_add >> 8)& 0xff;
	buff[1] = (block_add & 0xff);
	
	HAL_QSPI_Command(&hqspi , &cmd , W25NXX_QUAD_TIMEOUT);
	HAL_QSPI_Transmit(&hqspi ,buff , W25NXX_QUAD_TIMEOUT);
	//Wait for end of earase
	tick_start = HAL_GetTick();
	uint8_t quad_bk1_sr;
	W25NXX_ReadSR(W25NXX_StatusReg3,& quad_bk1_sr );
	while( quad_bk1_sr & 0x01 ){
		W25NXX_ReadSR(W25NXX_StatusReg3,& quad_bk1_sr );
		if( HAL_GetTick() - tick_start > W25NXX_TIMOUT || (quad_bk1_sr & 0x04) ){
			return 0;
		}
	}
	HAL_Delay(1);
	return 1;	
}


uint8_t W25NXX_ChipErase(void){
	for(uint32_t i=0 ; i < W25N01_BlockNum * W25N01_BlockSize ; i += W25N01_BlockSize){
		//if( W25NXX_Erase_Block128K( i ) == 0) return 0;
		W25NXX_Erase_Block128K(i) ;
	}
	return 1;
}
//Waiting for free
void W25NXX_Wait_Busy(uint8_t blk_no)   
{   
	while( W25NXX_get_BUSSY() &( 1 << blk_no) );   // Wait for the BUSY bit to clear
}   

“w25n01g.h”

#ifndef __W25NXX_H
#define __W25NXX_H
#include "main.h"   

//Instruction list
#define W25NXX_RESET 								0xFF
#define W25NXX_WriteEnable							0x06 
#define W25NXX_WriteDisable							0x04 
#define W25NXX_ReadStatusReg						0x05 
#define W25NXX_WriteStatusReg 				  		0x01
#define W25NXX_StatusReg1 							0xA0
#define W25NXX_StatusReg2 							0xB0
#define W25NXX_StatusReg3 							0xC0
#define W25NXX_LoadProgramData						0x32
#define W25NXX_LoadRandomProgramData				0x34//0x84
#define W25NXX_ProgramExec							0x10
#define W25NXX_PageRead								0x13
#define W25NXX_FastRead								0x6B//0x0B
#define W25NXX_BlockErase							0xD8
#define W25NXX_JedecDeviceID						0x9F 

#define W25NXX_TIMOUT								5
#define W25NXX_QUAD_TIMEOUT 						10
	
#define W25N01_PageSize								(2048 )
#define W25N01_BlockSize							(64)
#define W25N01_BlockNum								(1024)
#define W25N01_LAST_BLOCK							((W25N01_BlockNum - 1) * W25N01_BlockSize)
#define	W25N01_EraseSize							(64*2048) //128KB

#define W25NXX_SectorSize							2048
#define W25NXX_SectorNum							((W25N01_BlockNum * W25N01_BlockSize * W25N01_PageSize)/W25NXX_SectorSize)
#define W25NXX_BlkSecNum							(W25N01_PageSize / W25NXX_SectorSize)
#define W25NXX_EraseSecNum							(W25N01_EraseSize / W25NXX_SectorSize)

uint8_t W25NXX_Init(void);					        //Initialize W25NXX
void W25NXX_ReadID(uint32_t * id1);    		        //Read FLASH ID
void W25NXX_ReadSR(uint8_t ADD,uint8_t* SR1);       //Read status register 
void W25NXX_Write_SR(uint8_t ADD,uint8_t sr);       //Write status register
void W25NXX_Write_Enable(void);                     //Write enable 
void W25NXX_Write_Disable(void);                    //Write protection
void W25NXX_Read(uint8_t* pBuffer,uint32_t SectorReadAddr,uint32_t NumByteToRead);          //Read FLASH
uint16_t W25NXX_Read_Page(uint8_t* pBuffer,uint32_t SectorReadAddr,uint32_t NumByteToRead);
void W25NXX_Write(uint8_t* pBuffer,uint32_t SectorWriteAddr,uint32_t NumByteToWrite);       //Write flash
uint16_t W25NXX_Write_Page(uint8_t* pBuffer,uint32_t SectorWriteAddr,uint32_t NumByteToWrite);
uint8_t W25NXX_Erase_Block128K(uint32_t block_add);	    //Sector erase
void W25NXX_Wait_Busy(uint8_t blk_no);        	        //Waiting for chip to be free from erase or write operation
uint8_t W25NXX_ChipErase(void);		                    //erase the entire chip
uint8_t W25NXX_get_BUSSY(void);                         
#endif

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/904900.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Nature Communications|综述|无线胶囊内窥镜机器人的最新研究进展和未来发展方向(健康监测/柔性传感/可吞服电子)

浙江大学杨华勇(Huayong Yang)院士和韩冬( Dong Han)特聘研究员团队,在期刊《Nature Communications》上发布了一篇题为“Robotic wireless capsule endoscopy: recent advances and upcoming technologies”的综述论文,博士生曹青(Qing Cao)为论文第一作者。综述内容如…

群控系统服务端开发模式-应用开发-安装及提交仓库

整个应用采用的是现有的流行模式&#xff0c;前后分离。应用架构前端采用vue-element-admin&#xff0c;API接口采用的是thinkphp6&#xff0c;数据库采用的是MySQL5.7.36&#xff0c;而事件处理我采用的是分布式队列rabbitMQ。 首先安装及调整API接口系统业务架构逻辑。根据《…

一文讲明白大模型分布式逻辑(从GPU通信原语到Megatron、Deepspeed)

1. 背景介绍 如果你拿到了两台8卡A100的机器&#xff08;做梦&#xff09;&#xff0c;你的导师让你学习部署并且训练不同尺寸的大模型&#xff0c;并且写一个说明文档。你意识到&#xff0c;你最需要学习的就是关于分布式训练的知识&#xff0c;因为你可是第一次接触这么多卡…

Unreal Engine 5 C++(C#)开发:使用蓝图库实现插件(一)认识和了解Build.cs

目录 引言 一、创建一个C插件TextureReader插件 二、Build.cs文件 三、ModuleRules 四、TextureReader插件的构造 4.1ReadOnlyTargetRules的作用 4.2TextureReaderd的构造调用 4.3设置当前类的预编译头文件的使用模式 4.4PublicIncludePaths.AddRange与PrivateInclude…

揭秘世界技能大赛健康与社会照护项目,对智慧养老专业建设的启示

一、世界技能大赛&#xff08;世赛&#xff09;&#xff1a;职业技能的巅峰对决 被誉为“职业技能奥林匹克”的世界技能大赛是全球最高水平的职业技能竞赛&#xff0c;代表着各行业职业技能发展的国际先进水平。赛事涵盖六大领域&#xff1a;建筑与工程技术、创意艺术与时尚、…

【Unity】鼠标点击获取世界坐标位置:物体移动至鼠标点击的位置

需求说明 鼠标点击3D场景时&#xff0c;可以获取其所在的世界坐标&#xff1b; 鼠标点击3D物体时&#xff0c;可以获取该物体&#xff1b; 鼠标点击3D物体时&#xff0c;可以让玩家移动至该物体&#xff1b; 成果展示 Scene部分 关于仓库栏的设置&#xff0c;物体如何进入…

搭建支持国密GmSSL的Nginx环境

准备 1、服务器准备&#xff1a;本文搭建使用的服务器是CentOS 7.6 2、安装包准备&#xff1a;需要GmSSL、国密Nginx&#xff0c;可通过互联网下载或者从 https://download.csdn.net/download/m0_46665077/89936158 下载国密GmSSL安装包和国密Nginx安装包。 服务器安装依赖包…

AutoDIR: Automatic All-in-One Image Restoration with Latent Diffusion论文阅读笔记

AutoDIR: Automatic All-in-One Image Restoration with Latent Diffusion 论文阅读笔记 这是ECCV2024的论文&#xff0c;作者单位是是港中文和上海AI Lab 文章提出了一个叫AutoDIR的方法&#xff0c;包括两个关键阶段&#xff0c;一个是BIQA&#xff0c;基于vision-language…

如何查看磁盘的类型?(固态硬盘 or 机械硬盘)

按一下电脑的win键 直接打字搜索&#xff1a;【碎片整理和优化驱动器】 &#xff0c; 然后按一下【回车】或者 鼠标点击选择即可 如下位置&#xff1a;【媒体类型】显示的即是&#xff1a;【固态硬盘】or【机械硬盘】

解决pycharm无法添加conda环境的问题【Conda Environment下没有Existing environment】

解决pycharm无法添加conda environment 问题【Conda Environment下不显示Existing environment】 问题&#xff1a; 第一次下载好pycharm准备编写代码&#xff0c;在Anoconda Prompt建立好环境后&#xff0c;打开pycharm导入环境&#xff0c;却发现在【Conda Environment】处…

使用AIM对SAP PO核心指标的自动化巡检监控

一、背景 由于SAP PO系统维护成本较高&#xff0c;各类型异常报错等都需要人员进行时刻监控和响应&#xff0c;遂由AIM平台进行自动化巡检SAP PO的各指标&#xff0c;然后告警通知用户&#xff0c;节省维护成本和提高工作效率 二、核心指标监控 SAP PO失败消息 适用于S…

基于Python的A*算法实现路径规划

目录 一、A*算法 二、算法具体步骤 三、算法基本程序流程 四、算法代码实现 五、运行结果 一、A*算法 A*&#xff08;A-Star&#xff09;算法是P.E.Hart、N.J.Nilsson和B.Raphael等人在1986年综合Dijkstra算法和BFS算法的优点而提出来的一种非常有效的启发式路径搜索算法…

和鲸科技 CEO 范向伟受邀揭牌启动南京大学 2024 级大学生人工智能素养大赛

2024 年 10 月 26 日&#xff0c;南京大学第十九届读书节在仙林校区图书馆举行开幕仪式。中国科学院院士、南京大学校长谈哲敏&#xff0c;校党委常委、副校长索文斌&#xff0c;原副校长、关工委主任闵铁军出席仪式&#xff0c;南京大学相关学院和职能部处负责人&#xff0c;以…

有序序列合并(c语言)

代码实例 int main() {int n 0;int m 0;scanf("%d %d", &n, &m);//n输入第一个升序数组中的元素个数//m输入第二个升序数组中的元素个数//创建数组//arr1为n对应的数组int arr1[1000];//arr2为m对应的数组int arr2[1000];//arr3为数组1与数组2结合后的数组…

Java审计对比工具JaVers使用

最近有个需求&#xff0c;需要将页面的内容生成excel或者word文档&#xff0c;而且每次的修改都需要生成新的版本&#xff0c;同时需要记录每次修改变化的内容。我们会把每次的修改的内容提交赋值给一个java对象&#xff0c;同时存储到数据库一条新数据&#xff0c;对应数据表一…

知识图谱:连接实体与关系的语义网络

知识图谱作为人工智能领域的核心技术之一&#xff0c;是一种通过三元组&#xff08;实体关系属性&#xff09;形式&#xff0c;结构化表达实体间关系的语义网络。这种网络不仅嵌入了丰富的语义和逻辑&#xff0c;还遵循一定的规则&#xff0c;使其成为人类进行推理、预测和分类…

免费PDF页面提取小工具

下载地址 https://download.csdn.net/download/woshichenpi/89922797 使用说明&#xff1a;PDF页面提取工具 1. 启动应用程序 双击程序的启动图标或者通过命令行运行程序。 2. 选择PDF文件 在应用程序窗口中找到“选择PDF”按钮并点击它。在弹出的文件选择对话框中&#x…

法律智能助手:开源NLP系统助力法律文件高效审查与检索

一、系统概述 思通数科AI平台是一款融合了自然语言处理和多标签分类技术的开源智能文档分类工具&#xff0c;特别适用于法律行业。平台采用深度学习的BERT模型来进行特征提取与关系抽取&#xff0c;实现了精准的文档分类和检索。用户可以在线训练和标注数据&#xff0c;使系统…

-XSS-

链接 https://github.com/do0dl3/xss-labs 搭建过程非常容易的 搭建好之后&#xff0c;就可以点击图片开始闯关了 第一关--JS弹窗函数alert() 显示payload的长度是4 level1.php?nametest level1.php?nametest1 发现只要改变name的值就显示什么在页面上 没有什么过滤的 …

Python | Leetcode Python题解之第522题最长特殊序列II

题目&#xff1a; 题解&#xff1a; class Solution:def findLUSlength(self, strs: List[str]) -> int:def is_subseq(s: str, t: str) -> bool:pt_s pt_t 0while pt_s < len(s) and pt_t < len(t):if s[pt_s] t[pt_t]:pt_s 1pt_t 1return pt_s len(s)ans …