C언어,ARM

와치독 타이머, CPU_sleep, Flash write

안녕1999 2020. 7. 31. 22:35
//시간은 CPU클럭등에따라 달라질 수 있다.
#include "stm32f7xx_hal_iwdg.h"
INLINE void WDT_Init(void)
{
	IWDG->KR=IWDG_KEY_ENABLE;
	IWDG->KR=IWDG_KEY_WRITE_ACCESS_ENABLE;
	//IWDG->PR=IWDG_PRESCALER_256;//약9초
	IWDG->PR=IWDG_PRESCALER_128;//약4.5초
	//IWDG->PR=IWDG_PRESCALER_64;//약2.2초
	IWDG->RLR=1000;
	IWDG->KR=IWDG_KEY_RELOAD;
}
#define WDT_reset()		IWDG->KR=IWDG_KEY_RELOAD



//CPU_sleep명령은 인터럽트를 사용하는 경우, main함수 마지막에 넣어준다. 
//CPU가 불필요하게 무한루프를 도는것을 방지하여, 전력소모가 줄어든다.
void CPU_sleep(void)
{
	CLEAR_BIT(SCB->SCR, ((uint32_t)SCB_SCR_SLEEPDEEP_Msk));
	WFI();
}




#include "stm32f7xx_hal.h"
#include "stm32f7xx_hal_flash.h"
#ifndef FLASH_TIMEOUT_VALUE
	#define FLASH_TIMEOUT_VALUE       ((uint32_t)50000U)/* 50 s */
#endif
extern FLASH_ProcessTypeDef pFlash;
void   FLASH_Program_DoubleWord(uint32_t Address, uint64_t Data);
void   FLASH_Program_Word(uint32_t Address, uint32_t Data);
void   FLASH_Program_HalfWord(uint32_t Address, uint16_t Data);
void   FLASH_Program_Byte(uint32_t Address, uint8_t Data);
void   FLASH_SetErrorCode(void);
HAL_StatusTypeDef _FLASH_write(uint32_t Address,void *pdata,int len)
{
	HAL_StatusTypeDef status = HAL_ERROR;

	/* Process Locked */
	__HAL_LOCK(&pFlash);

	/* Check the parameters */
	assert_param(IS_FLASH_TYPEPROGRAM(TypeProgram));

	/* Wait for last operation to be completed */
	status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE);

	if(status == HAL_OK)
	{
		//uint64_t *p64;
		uint32_t *p32;
		uint16_t *p16;
		uint8_t *p8,*p=(uint8_t*)pdata;
		
		/*안됨 p64=(uint64_t*)p;
		while(len>=8)
		{
			FLASH_Program_DoubleWord(Address,*p64);
			p64++;
			Address+=8;
			len-=8;
		}
		p=(byte1*)p64;*/
		
		p32=(uint32_t*)p;
		while(len>=4)
		{
			FLASH_Program_Word(Address,*p32);
			p32++;
			Address+=4;
			len-=4;
		}
		p=(byte1*)p32;
		
		p16=(uint16_t*)p;
		while(len>=2)
		{
			FLASH_Program_HalfWord(Address,*p16);
			p16++;
			Address+=2;
			len-=2;
		}
		p=(byte1*)p16;
		
		p8=(uint8_t*)p;
		while(len>0)
		{
			FLASH_Program_Byte(Address,*p8);
			p8++;
			Address++;
			len--;
		}
		
		/* Wait for last operation to be completed */
		status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE);

		/* If the program operation is completed, disable the PG Bit */
		FLASH->CR &= (~FLASH_CR_PG);
	}

	/* Process Unlocked */
	__HAL_UNLOCK(&pFlash);

	return status;
}
#ifndef FlashSAVE_ADDR
	#define FlashSAVE_ADDR 		((uint32_t)0x080C0000)
#endif
void Flash_Read(uint32_t addr,void *pData,int len)
{
	memcpy(pData,(void*)(FlashSAVE_ADDR+addr),len);
}
int Flash_cmp(uint32_t addr,void *pData,int len)
{
	int r=0,blen;
	byte1 buf[512],*p=(byte1*)pData;
	//DEBUG_puts("Flash_cmp()");
	while(len>0)
	{
		if(len>sizeof(buf))
		{
			blen=sizeof(buf);
		}
		else
		{
			blen=len;
		}
		Flash_Read(addr,buf,blen);
		r=memcmp(buf,p,blen);
		if(r!=0)
		{
			//DEBUG_puts("다름");
			break;
		}
		else
		{
			//DEBUG_puts("동일함");
		}
		len-=blen;
		p+=blen;
	}
	//DEBUG_puts("Flash_cmp()_END");
	return r;
}
void _Flash_Write(void *pData,int len)//모두 삭제된 다음에 저장된다.(부분저장이 안됨)
{
	uint32_t PageError;
	static FLASH_EraseInitTypeDef a;
	a.TypeErase = FLASH_TYPEERASE_SECTORS;
	a.Sector  = FLASH_SECTOR_7;
	a.NbSectors = 1;
	a.VoltageRange=FLASH_VOLTAGE_RANGE_3;
	LED1_ON();
		HAL_FLASH_Unlock();
			HAL_FLASHEx_Erase(&a,&PageError);
			_FLASH_write(FlashSAVE_ADDR,pData,len);
		HAL_FLASH_Lock();
	LED1_OFF();
}
void Flash_Write(void *pData,int len)//모두 삭제된 다음에 저장된다.(부분저장이 안됨)
{
	if(Flash_cmp(0,pData,len)!=0)
	{
		_Flash_Write(pData,len);
	}
	else
	{
		//DEBUG_puts("동일한 내용으로, 저장 skip.");
	}
}