
#include "cpuid.h"
#include "crc32.h"

#define	CPUID_BEG	UID_BASE

#define	ID_SEQUE	(4671014970607679160ull)	// 0x40D2C75E1F9A36B8

#define	STM32_CPUID_LEN		12		// stm32 cpuid 长度

// 得到 CPU ID，共16字节
u32 g_cpuIDBeg = CPUID_BEG;

void InitCpuIDBase(u32 base)
{
	g_cpuIDBeg = base;
}

void GetCpuID(CpuId * pId)
{
	int i;
	u8 * pBuf;
	u8 dat;
	u32 addr = (g_cpuIDBeg) / 7;

	if (pId != NULL)
	{
		addr *= 7;
		addr += (g_cpuIDBeg) % 7;
		pBuf = (u8*)(addr);
		for (i = 0; i < STM32_CPUID_LEN; i++)
		{
			dat = *pBuf;
			pId->buff[i] = dat;
			pBuf++;
		}

		// 增加校验作为id延长码
		pId->dword.dword4 = CalcCrc32(pId->buff, STM32_CPUID_LEN);

#if (0)		// 输出信息
		printf("\r\nread cpuid: ");
		for (i = 0; i < CPUID_LEN; i++)
		{
			printf("%02x ", pId->buff[i]);
		}
		printf("\r\n");
#endif

#if (1)	// 信息加密
		{
#define	XMOVE_NUM		1		// 移位次数（1--7），改变后加密信息发生变化
			// 取反，错序，移位
			uint64_t seque = ID_SEQUE;	// 错序表
			u8 idx, temp, first;
			CpuId tmpbuf;

			memcpy(tmpbuf.buff, pId->buff, CPUID_LEN);
			
			// 取反 错序
			for (i = 0; i < CPUID_LEN; i++)
			{
				dat = tmpbuf.buff[i];
				idx = (seque & 0x0F);
				seque >>= 4;
				pId->buff[idx] = ~dat;
			}

			// 移位
			for (idx = 0; idx < XMOVE_NUM; idx++)
			{
				first = pId->buff[0];
				for (i = 1; i <= CPUID_LEN; i++)
				{
					dat = pId->buff[i-1];
					dat >>= 1;
					if (i == CPUID_LEN)
					{
						temp = first;
					}
					else
					{
						temp = pId->buff[i];
					}
					temp <<= 7;
					dat |= temp;
					pId->buff[i-1] = dat;
				}
			}
		}
#endif
	}
}

//----------------------------------

static int g_cricount = 0;

void EnterCritical(void)
{
	if (g_cricount == 0)
	{
		__disable_irq();
	}
	g_cricount++;
}

void ExitCritical(void)
{
	if (g_cricount != 0)
	{
		g_cricount--;
	}

	if (g_cricount == 0)
	{
		__enable_irq();
	}
}

// STM32软件复位
void RestartMcu(void)
{
	printf("restart the mcu...\r\n");

	__disable_irq();

	NVIC_SystemReset();		// 系统复位
}
