凌云物联网实验室ISKBoard(IoT Starter Kits Board)开发板项目源码
guowenxue
2023-04-07 6ddecc5e53def103eec427a61f2de308552735f5
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
/**********************************************************************
*   Copyright: (C)2023 LingYun IoT System Studio
*      Author: GuoWenxue<guowenxue@gmail.com> QQ: 281143292
* Description: ISKBoard Serial Number Hardware Abstract Layer driver
*
*   ChangeLog:
*        Version    Date       Author            Description
*        V1.0.0  2023.04.3    GuoWenxue      Release initial version
***********************************************************************/
 
#include <stdio.h>
#include <string.h>
#include "stm32l4xx_hal.h"
#include "miscdev.h"
#include "devsn.h"
 
//#define CONFIG_TEST_DEVSN_FLASH
 
#ifdef CONFIG_TEST_DEVSN_FLASH
#define FLASH_USER_START_ADDR   ( FLASH_BASE + FLASH_PAGE_SIZE * 62 ) //写Flash的地址,这里从第62页开始
#define FLASH_USER_END_ADDR     ( FLASH_BASE + FLASH_PAGE_SIZE * 64 ) //写Flash的地址,这里以第64页结束
 
#define SN_START_ADDR       FLASH_USER_START_ADDR
 
#else
 
#define OTP_BASEADDR        0x1FFF7000  /* OTP memory base address */
#define OTP_ENDADDR         0x1FFF3FFU  /* OTP memory  address */
#define OTP_BLOCKSIZE       32          /* OTP memory block size is 32 bytes */
#define SN_OTP_BLOCK        15          /* OTP memory get 16 blocks, and SN saved in the 16th block */
#define SN_OTP_ADDR         (OTP_BASEADDR + SN_OTP_BLOCK*OTP_BLOCKSIZE)
 
#define SN_START_ADDR       SN_OTP_ADDR
#endif
 
#define FlashGetChar(addr)  *((char*)(addr))
 
#ifdef CONFIG_TEST_DEVSN_FLASH
static inline uint32_t flash_getpage(uint32_t addr)
{
  uint32_t page = 0;
 
  if (addr < (FLASH_BASE + FLASH_BANK_SIZE)) /* Bank 1 */
  {
    page = (addr - FLASH_BASE) / FLASH_PAGE_SIZE;
  }
  else /* Bank 2 */
  {
    page = (addr - (FLASH_BASE + FLASH_BANK_SIZE)) / FLASH_PAGE_SIZE;
  }
 
  return page;
}
 
void flash_erase(void)
{
    static FLASH_EraseInitTypeDef EraseInitStruct;
    uint32_t FirstPage = 0, NbOfPages = 0, BankNumber = 0,PAGEError = 0;
 
    /* Erase the user Flash area (already defined by FLASH_USER_START_ADDR and FLASH_USER_END_ADDR) */
    HAL_FLASH_Unlock();
 
    /* Clear OPTVERR bit set on virgin samples */
    __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_OPTVERR);
 
    /* Get the 1st page to erase */
    FirstPage = flash_getpage(FLASH_USER_START_ADDR);
    /* Get the number of pages to erase from 1st page */
    NbOfPages = flash_getpage(FLASH_USER_END_ADDR) - FirstPage + 1;
    /* Get the bank */
    BankNumber = FLASH_BANK_1;
    /* Fill EraseInit structure*/
    EraseInitStruct.TypeErase   = FLASH_TYPEERASE_PAGES;
    EraseInitStruct.Banks       = BankNumber;
    EraseInitStruct.Page        = FirstPage;
    EraseInitStruct.NbPages     = NbOfPages;
 
    if (HAL_FLASHEx_Erase(&EraseInitStruct, &PAGEError) != HAL_OK)
    {
        printf("Flash erase failed\r\n");
    }
 
    HAL_FLASH_Lock();
}
#endif
 
 
int read_devsn(char *devsn, int size)
{
    int          i;
 
    if( !devsn || size<DEVSN_LEN )
    {
        printf("%s(): Invalid input arugments\r\n", __func__);
        return -1;
    }
 
    memset(devsn, 0, size);
    for(i=0; i<size; i++)
    {
        devsn[i] = FlashGetChar(SN_START_ADDR+i);
    }
 
    if( !strncmp(devsn, "ISK", 3) )
        return 0;
    else
        return -2;
}
 
int write_devsn(char *devsn, int bytes)
{
    uint8_t      i;
    uint64_t     dword[2] = {0};
    char         buf[DEVSN_LEN+1];
    char        *byte;
 
    if( !devsn || bytes!=DEVSN_LEN || strncmp(devsn, "ISK", 3) )
    {
        printf("%s(): Invalid input arugments\r\n", __func__);
        return -1;
    }
 
    if( !read_devsn(buf, sizeof(buf)) )
    {
        printf("%s(): S/N writen already!\r\n", __func__);
        return 0;
    }
 
    printf("Start write S/N: %s\n", devsn);
 
    /* Convert S/N to 2 double words */
    byte = (char *)dword;
    for(i=0; i<DEVSN_LEN; i++)
    {
        *byte = devsn[i];
        byte++;
    }
 
#ifdef CONFIG_TEST_DEVSN_FLASH
    flash_erase();
#endif
 
    /* Start write SN into flash */
    HAL_FLASH_Unlock();
    for(i=0; i<2; i++)
    {
        if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, SN_START_ADDR+i*8, dword[i]) != HAL_OK)
        {
            printf("%s(): Flash program S/N failed!\r\n", __func__);
            return -2;
        }
    }
    HAL_FLASH_Lock();
 
    return 0;
}