调整驱动
This commit is contained in:
parent
e4c3e59332
commit
005cc792a8
|
@ -120,7 +120,8 @@
|
||||||
<SetRegEntry>
|
<SetRegEntry>
|
||||||
<Number>0</Number>
|
<Number>0</Number>
|
||||||
<Key>DLGUARM</Key>
|
<Key>DLGUARM</Key>
|
||||||
</SetRegEntry>
|
<Name>
|
||||||
|
</Name> </SetRegEntry>
|
||||||
<SetRegEntry>
|
<SetRegEntry>
|
||||||
<Number>0</Number>
|
<Number>0</Number>
|
||||||
<Key>JL2CM3</Key>
|
<Key>JL2CM3</Key>
|
||||||
|
@ -179,6 +180,16 @@
|
||||||
<WinNumber>1</WinNumber>
|
<WinNumber>1</WinNumber>
|
||||||
<ItemText>board,0x0A</ItemText>
|
<ItemText>board,0x0A</ItemText>
|
||||||
</Ww>
|
</Ww>
|
||||||
|
<Ww>
|
||||||
|
<count>4</count>
|
||||||
|
<WinNumber>1</WinNumber>
|
||||||
|
<ItemText>0x000020CF,0x0A</ItemText>
|
||||||
|
</Ww>
|
||||||
|
<Ww>
|
||||||
|
<count>5</count>
|
||||||
|
<WinNumber>1</WinNumber>
|
||||||
|
<ItemText>0x0063,0x0A</ItemText>
|
||||||
|
</Ww>
|
||||||
</WatchWindow1>
|
</WatchWindow1>
|
||||||
<MemoryWindow1>
|
<MemoryWindow1>
|
||||||
<Mm>
|
<Mm>
|
||||||
|
@ -230,6 +241,12 @@
|
||||||
<pszMrulep></pszMrulep>
|
<pszMrulep></pszMrulep>
|
||||||
<pSingCmdsp></pSingCmdsp>
|
<pSingCmdsp></pSingCmdsp>
|
||||||
<pMultCmdsp></pMultCmdsp>
|
<pMultCmdsp></pMultCmdsp>
|
||||||
|
<SystemViewers>
|
||||||
|
<Entry>
|
||||||
|
<Name>System Viewer\TIM6</Name>
|
||||||
|
<WinId>35905</WinId>
|
||||||
|
</Entry>
|
||||||
|
</SystemViewers>
|
||||||
<DebugDescription>
|
<DebugDescription>
|
||||||
<Enable>1</Enable>
|
<Enable>1</Enable>
|
||||||
<EnableFlashSeq>1</EnableFlashSeq>
|
<EnableFlashSeq>1</EnableFlashSeq>
|
||||||
|
@ -493,7 +510,7 @@
|
||||||
</Group>
|
</Group>
|
||||||
|
|
||||||
<Group>
|
<Group>
|
||||||
<GroupName>User/lib</GroupName>
|
<GroupName>User/system</GroupName>
|
||||||
<tvExp>0</tvExp>
|
<tvExp>0</tvExp>
|
||||||
<tvExpOptDlg>0</tvExpOptDlg>
|
<tvExpOptDlg>0</tvExpOptDlg>
|
||||||
<cbSel>0</cbSel>
|
<cbSel>0</cbSel>
|
||||||
|
@ -505,8 +522,8 @@
|
||||||
<tvExp>0</tvExp>
|
<tvExp>0</tvExp>
|
||||||
<tvExpOptDlg>0</tvExpOptDlg>
|
<tvExpOptDlg>0</tvExpOptDlg>
|
||||||
<bDave2>0</bDave2>
|
<bDave2>0</bDave2>
|
||||||
<PathWithFileName>..\User\lib\src\aes.c</PathWithFileName>
|
<PathWithFileName>..\User\system\btn.c</PathWithFileName>
|
||||||
<FilenameWithoutPath>aes.c</FilenameWithoutPath>
|
<FilenameWithoutPath>btn.c</FilenameWithoutPath>
|
||||||
<RteFlg>0</RteFlg>
|
<RteFlg>0</RteFlg>
|
||||||
<bShared>0</bShared>
|
<bShared>0</bShared>
|
||||||
</File>
|
</File>
|
||||||
|
@ -517,8 +534,8 @@
|
||||||
<tvExp>0</tvExp>
|
<tvExp>0</tvExp>
|
||||||
<tvExpOptDlg>0</tvExpOptDlg>
|
<tvExpOptDlg>0</tvExpOptDlg>
|
||||||
<bDave2>0</bDave2>
|
<bDave2>0</bDave2>
|
||||||
<PathWithFileName>..\User\lib\src\clist.c</PathWithFileName>
|
<PathWithFileName>..\User\system\delay.c</PathWithFileName>
|
||||||
<FilenameWithoutPath>clist.c</FilenameWithoutPath>
|
<FilenameWithoutPath>delay.c</FilenameWithoutPath>
|
||||||
<RteFlg>0</RteFlg>
|
<RteFlg>0</RteFlg>
|
||||||
<bShared>0</bShared>
|
<bShared>0</bShared>
|
||||||
</File>
|
</File>
|
||||||
|
@ -529,139 +546,139 @@
|
||||||
<tvExp>0</tvExp>
|
<tvExp>0</tvExp>
|
||||||
<tvExpOptDlg>0</tvExpOptDlg>
|
<tvExpOptDlg>0</tvExpOptDlg>
|
||||||
<bDave2>0</bDave2>
|
<bDave2>0</bDave2>
|
||||||
<PathWithFileName>..\User\lib\src\cmac.c</PathWithFileName>
|
<PathWithFileName>..\User\system\sys.c</PathWithFileName>
|
||||||
<FilenameWithoutPath>cmac.c</FilenameWithoutPath>
|
<FilenameWithoutPath>sys.c</FilenameWithoutPath>
|
||||||
<RteFlg>0</RteFlg>
|
|
||||||
<bShared>0</bShared>
|
|
||||||
</File>
|
|
||||||
<File>
|
|
||||||
<GroupNumber>7</GroupNumber>
|
|
||||||
<FileNumber>21</FileNumber>
|
|
||||||
<FileType>1</FileType>
|
|
||||||
<tvExp>0</tvExp>
|
|
||||||
<tvExpOptDlg>0</tvExpOptDlg>
|
|
||||||
<bDave2>0</bDave2>
|
|
||||||
<PathWithFileName>..\User\lib\src\cmd.c</PathWithFileName>
|
|
||||||
<FilenameWithoutPath>cmd.c</FilenameWithoutPath>
|
|
||||||
<RteFlg>0</RteFlg>
|
|
||||||
<bShared>0</bShared>
|
|
||||||
</File>
|
|
||||||
<File>
|
|
||||||
<GroupNumber>7</GroupNumber>
|
|
||||||
<FileNumber>22</FileNumber>
|
|
||||||
<FileType>1</FileType>
|
|
||||||
<tvExp>0</tvExp>
|
|
||||||
<tvExpOptDlg>0</tvExpOptDlg>
|
|
||||||
<bDave2>0</bDave2>
|
|
||||||
<PathWithFileName>..\User\lib\src\data_analysis.c</PathWithFileName>
|
|
||||||
<FilenameWithoutPath>data_analysis.c</FilenameWithoutPath>
|
|
||||||
<RteFlg>0</RteFlg>
|
|
||||||
<bShared>0</bShared>
|
|
||||||
</File>
|
|
||||||
<File>
|
|
||||||
<GroupNumber>7</GroupNumber>
|
|
||||||
<FileNumber>23</FileNumber>
|
|
||||||
<FileType>1</FileType>
|
|
||||||
<tvExp>0</tvExp>
|
|
||||||
<tvExpOptDlg>0</tvExpOptDlg>
|
|
||||||
<bDave2>0</bDave2>
|
|
||||||
<PathWithFileName>..\User\lib\src\debug.c</PathWithFileName>
|
|
||||||
<FilenameWithoutPath>debug.c</FilenameWithoutPath>
|
|
||||||
<RteFlg>0</RteFlg>
|
|
||||||
<bShared>0</bShared>
|
|
||||||
</File>
|
|
||||||
<File>
|
|
||||||
<GroupNumber>7</GroupNumber>
|
|
||||||
<FileNumber>24</FileNumber>
|
|
||||||
<FileType>1</FileType>
|
|
||||||
<tvExp>0</tvExp>
|
|
||||||
<tvExpOptDlg>0</tvExpOptDlg>
|
|
||||||
<bDave2>0</bDave2>
|
|
||||||
<PathWithFileName>..\User\lib\src\filter.c</PathWithFileName>
|
|
||||||
<FilenameWithoutPath>filter.c</FilenameWithoutPath>
|
|
||||||
<RteFlg>0</RteFlg>
|
|
||||||
<bShared>0</bShared>
|
|
||||||
</File>
|
|
||||||
<File>
|
|
||||||
<GroupNumber>7</GroupNumber>
|
|
||||||
<FileNumber>25</FileNumber>
|
|
||||||
<FileType>1</FileType>
|
|
||||||
<tvExp>0</tvExp>
|
|
||||||
<tvExpOptDlg>0</tvExpOptDlg>
|
|
||||||
<bDave2>0</bDave2>
|
|
||||||
<PathWithFileName>..\User\lib\src\lib.c</PathWithFileName>
|
|
||||||
<FilenameWithoutPath>lib.c</FilenameWithoutPath>
|
|
||||||
<RteFlg>0</RteFlg>
|
|
||||||
<bShared>0</bShared>
|
|
||||||
</File>
|
|
||||||
<File>
|
|
||||||
<GroupNumber>7</GroupNumber>
|
|
||||||
<FileNumber>26</FileNumber>
|
|
||||||
<FileType>1</FileType>
|
|
||||||
<tvExp>0</tvExp>
|
|
||||||
<tvExpOptDlg>0</tvExpOptDlg>
|
|
||||||
<bDave2>0</bDave2>
|
|
||||||
<PathWithFileName>..\User\lib\src\malloc.c</PathWithFileName>
|
|
||||||
<FilenameWithoutPath>malloc.c</FilenameWithoutPath>
|
|
||||||
<RteFlg>0</RteFlg>
|
|
||||||
<bShared>0</bShared>
|
|
||||||
</File>
|
|
||||||
<File>
|
|
||||||
<GroupNumber>7</GroupNumber>
|
|
||||||
<FileNumber>27</FileNumber>
|
|
||||||
<FileType>1</FileType>
|
|
||||||
<tvExp>0</tvExp>
|
|
||||||
<tvExpOptDlg>0</tvExpOptDlg>
|
|
||||||
<bDave2>0</bDave2>
|
|
||||||
<PathWithFileName>..\User\lib\src\mlist.c</PathWithFileName>
|
|
||||||
<FilenameWithoutPath>mlist.c</FilenameWithoutPath>
|
|
||||||
<RteFlg>0</RteFlg>
|
|
||||||
<bShared>0</bShared>
|
|
||||||
</File>
|
|
||||||
<File>
|
|
||||||
<GroupNumber>7</GroupNumber>
|
|
||||||
<FileNumber>28</FileNumber>
|
|
||||||
<FileType>1</FileType>
|
|
||||||
<tvExp>0</tvExp>
|
|
||||||
<tvExpOptDlg>0</tvExpOptDlg>
|
|
||||||
<bDave2>0</bDave2>
|
|
||||||
<PathWithFileName>..\User\lib\src\pbuf.c</PathWithFileName>
|
|
||||||
<FilenameWithoutPath>pbuf.c</FilenameWithoutPath>
|
|
||||||
<RteFlg>0</RteFlg>
|
|
||||||
<bShared>0</bShared>
|
|
||||||
</File>
|
|
||||||
<File>
|
|
||||||
<GroupNumber>7</GroupNumber>
|
|
||||||
<FileNumber>29</FileNumber>
|
|
||||||
<FileType>1</FileType>
|
|
||||||
<tvExp>0</tvExp>
|
|
||||||
<tvExpOptDlg>0</tvExpOptDlg>
|
|
||||||
<bDave2>0</bDave2>
|
|
||||||
<PathWithFileName>..\User\lib\src\sqqueue.c</PathWithFileName>
|
|
||||||
<FilenameWithoutPath>sqqueue.c</FilenameWithoutPath>
|
|
||||||
<RteFlg>0</RteFlg>
|
|
||||||
<bShared>0</bShared>
|
|
||||||
</File>
|
|
||||||
<File>
|
|
||||||
<GroupNumber>7</GroupNumber>
|
|
||||||
<FileNumber>30</FileNumber>
|
|
||||||
<FileType>1</FileType>
|
|
||||||
<tvExp>0</tvExp>
|
|
||||||
<tvExpOptDlg>0</tvExpOptDlg>
|
|
||||||
<bDave2>0</bDave2>
|
|
||||||
<PathWithFileName>..\User\lib\flow\flow_core.c</PathWithFileName>
|
|
||||||
<FilenameWithoutPath>flow_core.c</FilenameWithoutPath>
|
|
||||||
<RteFlg>0</RteFlg>
|
<RteFlg>0</RteFlg>
|
||||||
<bShared>0</bShared>
|
<bShared>0</bShared>
|
||||||
</File>
|
</File>
|
||||||
</Group>
|
</Group>
|
||||||
|
|
||||||
<Group>
|
<Group>
|
||||||
<GroupName>User/system</GroupName>
|
<GroupName>User/lib</GroupName>
|
||||||
<tvExp>1</tvExp>
|
<tvExp>0</tvExp>
|
||||||
<tvExpOptDlg>0</tvExpOptDlg>
|
<tvExpOptDlg>0</tvExpOptDlg>
|
||||||
<cbSel>0</cbSel>
|
<cbSel>0</cbSel>
|
||||||
<RteFlg>0</RteFlg>
|
<RteFlg>0</RteFlg>
|
||||||
|
<File>
|
||||||
|
<GroupNumber>8</GroupNumber>
|
||||||
|
<FileNumber>21</FileNumber>
|
||||||
|
<FileType>1</FileType>
|
||||||
|
<tvExp>0</tvExp>
|
||||||
|
<tvExpOptDlg>0</tvExpOptDlg>
|
||||||
|
<bDave2>0</bDave2>
|
||||||
|
<PathWithFileName>..\User\system\lib\src\aes.c</PathWithFileName>
|
||||||
|
<FilenameWithoutPath>aes.c</FilenameWithoutPath>
|
||||||
|
<RteFlg>0</RteFlg>
|
||||||
|
<bShared>0</bShared>
|
||||||
|
</File>
|
||||||
|
<File>
|
||||||
|
<GroupNumber>8</GroupNumber>
|
||||||
|
<FileNumber>22</FileNumber>
|
||||||
|
<FileType>1</FileType>
|
||||||
|
<tvExp>0</tvExp>
|
||||||
|
<tvExpOptDlg>0</tvExpOptDlg>
|
||||||
|
<bDave2>0</bDave2>
|
||||||
|
<PathWithFileName>..\User\system\lib\src\clist.c</PathWithFileName>
|
||||||
|
<FilenameWithoutPath>clist.c</FilenameWithoutPath>
|
||||||
|
<RteFlg>0</RteFlg>
|
||||||
|
<bShared>0</bShared>
|
||||||
|
</File>
|
||||||
|
<File>
|
||||||
|
<GroupNumber>8</GroupNumber>
|
||||||
|
<FileNumber>23</FileNumber>
|
||||||
|
<FileType>1</FileType>
|
||||||
|
<tvExp>0</tvExp>
|
||||||
|
<tvExpOptDlg>0</tvExpOptDlg>
|
||||||
|
<bDave2>0</bDave2>
|
||||||
|
<PathWithFileName>..\User\system\lib\src\cmac.c</PathWithFileName>
|
||||||
|
<FilenameWithoutPath>cmac.c</FilenameWithoutPath>
|
||||||
|
<RteFlg>0</RteFlg>
|
||||||
|
<bShared>0</bShared>
|
||||||
|
</File>
|
||||||
|
<File>
|
||||||
|
<GroupNumber>8</GroupNumber>
|
||||||
|
<FileNumber>24</FileNumber>
|
||||||
|
<FileType>1</FileType>
|
||||||
|
<tvExp>0</tvExp>
|
||||||
|
<tvExpOptDlg>0</tvExpOptDlg>
|
||||||
|
<bDave2>0</bDave2>
|
||||||
|
<PathWithFileName>..\User\system\lib\src\cmd.c</PathWithFileName>
|
||||||
|
<FilenameWithoutPath>cmd.c</FilenameWithoutPath>
|
||||||
|
<RteFlg>0</RteFlg>
|
||||||
|
<bShared>0</bShared>
|
||||||
|
</File>
|
||||||
|
<File>
|
||||||
|
<GroupNumber>8</GroupNumber>
|
||||||
|
<FileNumber>25</FileNumber>
|
||||||
|
<FileType>1</FileType>
|
||||||
|
<tvExp>0</tvExp>
|
||||||
|
<tvExpOptDlg>0</tvExpOptDlg>
|
||||||
|
<bDave2>0</bDave2>
|
||||||
|
<PathWithFileName>..\User\system\lib\src\data_analysis.c</PathWithFileName>
|
||||||
|
<FilenameWithoutPath>data_analysis.c</FilenameWithoutPath>
|
||||||
|
<RteFlg>0</RteFlg>
|
||||||
|
<bShared>0</bShared>
|
||||||
|
</File>
|
||||||
|
<File>
|
||||||
|
<GroupNumber>8</GroupNumber>
|
||||||
|
<FileNumber>26</FileNumber>
|
||||||
|
<FileType>1</FileType>
|
||||||
|
<tvExp>0</tvExp>
|
||||||
|
<tvExpOptDlg>0</tvExpOptDlg>
|
||||||
|
<bDave2>0</bDave2>
|
||||||
|
<PathWithFileName>..\User\system\lib\src\debug.c</PathWithFileName>
|
||||||
|
<FilenameWithoutPath>debug.c</FilenameWithoutPath>
|
||||||
|
<RteFlg>0</RteFlg>
|
||||||
|
<bShared>0</bShared>
|
||||||
|
</File>
|
||||||
|
<File>
|
||||||
|
<GroupNumber>8</GroupNumber>
|
||||||
|
<FileNumber>27</FileNumber>
|
||||||
|
<FileType>1</FileType>
|
||||||
|
<tvExp>0</tvExp>
|
||||||
|
<tvExpOptDlg>0</tvExpOptDlg>
|
||||||
|
<bDave2>0</bDave2>
|
||||||
|
<PathWithFileName>..\User\system\lib\src\filter.c</PathWithFileName>
|
||||||
|
<FilenameWithoutPath>filter.c</FilenameWithoutPath>
|
||||||
|
<RteFlg>0</RteFlg>
|
||||||
|
<bShared>0</bShared>
|
||||||
|
</File>
|
||||||
|
<File>
|
||||||
|
<GroupNumber>8</GroupNumber>
|
||||||
|
<FileNumber>28</FileNumber>
|
||||||
|
<FileType>1</FileType>
|
||||||
|
<tvExp>0</tvExp>
|
||||||
|
<tvExpOptDlg>0</tvExpOptDlg>
|
||||||
|
<bDave2>0</bDave2>
|
||||||
|
<PathWithFileName>..\User\system\lib\src\lib.c</PathWithFileName>
|
||||||
|
<FilenameWithoutPath>lib.c</FilenameWithoutPath>
|
||||||
|
<RteFlg>0</RteFlg>
|
||||||
|
<bShared>0</bShared>
|
||||||
|
</File>
|
||||||
|
<File>
|
||||||
|
<GroupNumber>8</GroupNumber>
|
||||||
|
<FileNumber>29</FileNumber>
|
||||||
|
<FileType>1</FileType>
|
||||||
|
<tvExp>0</tvExp>
|
||||||
|
<tvExpOptDlg>0</tvExpOptDlg>
|
||||||
|
<bDave2>0</bDave2>
|
||||||
|
<PathWithFileName>..\User\system\lib\src\malloc.c</PathWithFileName>
|
||||||
|
<FilenameWithoutPath>malloc.c</FilenameWithoutPath>
|
||||||
|
<RteFlg>0</RteFlg>
|
||||||
|
<bShared>0</bShared>
|
||||||
|
</File>
|
||||||
|
<File>
|
||||||
|
<GroupNumber>8</GroupNumber>
|
||||||
|
<FileNumber>30</FileNumber>
|
||||||
|
<FileType>1</FileType>
|
||||||
|
<tvExp>0</tvExp>
|
||||||
|
<tvExpOptDlg>0</tvExpOptDlg>
|
||||||
|
<bDave2>0</bDave2>
|
||||||
|
<PathWithFileName>..\User\system\lib\src\mlist.c</PathWithFileName>
|
||||||
|
<FilenameWithoutPath>mlist.c</FilenameWithoutPath>
|
||||||
|
<RteFlg>0</RteFlg>
|
||||||
|
<bShared>0</bShared>
|
||||||
|
</File>
|
||||||
<File>
|
<File>
|
||||||
<GroupNumber>8</GroupNumber>
|
<GroupNumber>8</GroupNumber>
|
||||||
<FileNumber>31</FileNumber>
|
<FileNumber>31</FileNumber>
|
||||||
|
@ -669,8 +686,8 @@
|
||||||
<tvExp>0</tvExp>
|
<tvExp>0</tvExp>
|
||||||
<tvExpOptDlg>0</tvExpOptDlg>
|
<tvExpOptDlg>0</tvExpOptDlg>
|
||||||
<bDave2>0</bDave2>
|
<bDave2>0</bDave2>
|
||||||
<PathWithFileName>..\User\system\src\btn.c</PathWithFileName>
|
<PathWithFileName>..\User\system\lib\src\pbuf.c</PathWithFileName>
|
||||||
<FilenameWithoutPath>btn.c</FilenameWithoutPath>
|
<FilenameWithoutPath>pbuf.c</FilenameWithoutPath>
|
||||||
<RteFlg>0</RteFlg>
|
<RteFlg>0</RteFlg>
|
||||||
<bShared>0</bShared>
|
<bShared>0</bShared>
|
||||||
</File>
|
</File>
|
||||||
|
@ -681,8 +698,8 @@
|
||||||
<tvExp>0</tvExp>
|
<tvExp>0</tvExp>
|
||||||
<tvExpOptDlg>0</tvExpOptDlg>
|
<tvExpOptDlg>0</tvExpOptDlg>
|
||||||
<bDave2>0</bDave2>
|
<bDave2>0</bDave2>
|
||||||
<PathWithFileName>..\User\system\src\delay.c</PathWithFileName>
|
<PathWithFileName>..\User\system\lib\src\sqqueue.c</PathWithFileName>
|
||||||
<FilenameWithoutPath>delay.c</FilenameWithoutPath>
|
<FilenameWithoutPath>sqqueue.c</FilenameWithoutPath>
|
||||||
<RteFlg>0</RteFlg>
|
<RteFlg>0</RteFlg>
|
||||||
<bShared>0</bShared>
|
<bShared>0</bShared>
|
||||||
</File>
|
</File>
|
||||||
|
@ -693,8 +710,8 @@
|
||||||
<tvExp>0</tvExp>
|
<tvExp>0</tvExp>
|
||||||
<tvExpOptDlg>0</tvExpOptDlg>
|
<tvExpOptDlg>0</tvExpOptDlg>
|
||||||
<bDave2>0</bDave2>
|
<bDave2>0</bDave2>
|
||||||
<PathWithFileName>..\User\system\src\sys.c</PathWithFileName>
|
<PathWithFileName>..\User\system\lib\src\storage.c</PathWithFileName>
|
||||||
<FilenameWithoutPath>sys.c</FilenameWithoutPath>
|
<FilenameWithoutPath>storage.c</FilenameWithoutPath>
|
||||||
<RteFlg>0</RteFlg>
|
<RteFlg>0</RteFlg>
|
||||||
<bShared>0</bShared>
|
<bShared>0</bShared>
|
||||||
</File>
|
</File>
|
||||||
|
@ -705,8 +722,8 @@
|
||||||
<tvExp>0</tvExp>
|
<tvExp>0</tvExp>
|
||||||
<tvExpOptDlg>0</tvExpOptDlg>
|
<tvExpOptDlg>0</tvExpOptDlg>
|
||||||
<bDave2>0</bDave2>
|
<bDave2>0</bDave2>
|
||||||
<PathWithFileName>..\User\system\bsp\adcs.c</PathWithFileName>
|
<PathWithFileName>..\User\system\lib\src\wl_flash.c</PathWithFileName>
|
||||||
<FilenameWithoutPath>adcs.c</FilenameWithoutPath>
|
<FilenameWithoutPath>wl_flash.c</FilenameWithoutPath>
|
||||||
<RteFlg>0</RteFlg>
|
<RteFlg>0</RteFlg>
|
||||||
<bShared>0</bShared>
|
<bShared>0</bShared>
|
||||||
</File>
|
</File>
|
||||||
|
@ -717,14 +734,46 @@
|
||||||
<tvExp>0</tvExp>
|
<tvExp>0</tvExp>
|
||||||
<tvExpOptDlg>0</tvExpOptDlg>
|
<tvExpOptDlg>0</tvExpOptDlg>
|
||||||
<bDave2>0</bDave2>
|
<bDave2>0</bDave2>
|
||||||
|
<PathWithFileName>..\User\system\lib\flow\flow_core.c</PathWithFileName>
|
||||||
|
<FilenameWithoutPath>flow_core.c</FilenameWithoutPath>
|
||||||
|
<RteFlg>0</RteFlg>
|
||||||
|
<bShared>0</bShared>
|
||||||
|
</File>
|
||||||
|
</Group>
|
||||||
|
|
||||||
|
<Group>
|
||||||
|
<GroupName>User/system/bsp</GroupName>
|
||||||
|
<tvExp>0</tvExp>
|
||||||
|
<tvExpOptDlg>0</tvExpOptDlg>
|
||||||
|
<cbSel>0</cbSel>
|
||||||
|
<RteFlg>0</RteFlg>
|
||||||
|
<File>
|
||||||
|
<GroupNumber>9</GroupNumber>
|
||||||
|
<FileNumber>36</FileNumber>
|
||||||
|
<FileType>1</FileType>
|
||||||
|
<tvExp>0</tvExp>
|
||||||
|
<tvExpOptDlg>0</tvExpOptDlg>
|
||||||
|
<bDave2>0</bDave2>
|
||||||
|
<PathWithFileName>..\User\system\bsp\adcs.c</PathWithFileName>
|
||||||
|
<FilenameWithoutPath>adcs.c</FilenameWithoutPath>
|
||||||
|
<RteFlg>0</RteFlg>
|
||||||
|
<bShared>0</bShared>
|
||||||
|
</File>
|
||||||
|
<File>
|
||||||
|
<GroupNumber>9</GroupNumber>
|
||||||
|
<FileNumber>37</FileNumber>
|
||||||
|
<FileType>1</FileType>
|
||||||
|
<tvExp>0</tvExp>
|
||||||
|
<tvExpOptDlg>0</tvExpOptDlg>
|
||||||
|
<bDave2>0</bDave2>
|
||||||
<PathWithFileName>..\User\system\bsp\bsp.c</PathWithFileName>
|
<PathWithFileName>..\User\system\bsp\bsp.c</PathWithFileName>
|
||||||
<FilenameWithoutPath>bsp.c</FilenameWithoutPath>
|
<FilenameWithoutPath>bsp.c</FilenameWithoutPath>
|
||||||
<RteFlg>0</RteFlg>
|
<RteFlg>0</RteFlg>
|
||||||
<bShared>0</bShared>
|
<bShared>0</bShared>
|
||||||
</File>
|
</File>
|
||||||
<File>
|
<File>
|
||||||
<GroupNumber>8</GroupNumber>
|
<GroupNumber>9</GroupNumber>
|
||||||
<FileNumber>36</FileNumber>
|
<FileNumber>38</FileNumber>
|
||||||
<FileType>1</FileType>
|
<FileType>1</FileType>
|
||||||
<tvExp>0</tvExp>
|
<tvExp>0</tvExp>
|
||||||
<tvExpOptDlg>0</tvExpOptDlg>
|
<tvExpOptDlg>0</tvExpOptDlg>
|
||||||
|
@ -735,77 +784,17 @@
|
||||||
<bShared>0</bShared>
|
<bShared>0</bShared>
|
||||||
</File>
|
</File>
|
||||||
<File>
|
<File>
|
||||||
<GroupNumber>8</GroupNumber>
|
<GroupNumber>9</GroupNumber>
|
||||||
<FileNumber>37</FileNumber>
|
|
||||||
<FileType>1</FileType>
|
|
||||||
<tvExp>0</tvExp>
|
|
||||||
<tvExpOptDlg>0</tvExpOptDlg>
|
|
||||||
<bDave2>0</bDave2>
|
|
||||||
<PathWithFileName>..\User\system\bsp\i2cs.c</PathWithFileName>
|
|
||||||
<FilenameWithoutPath>i2cs.c</FilenameWithoutPath>
|
|
||||||
<RteFlg>0</RteFlg>
|
|
||||||
<bShared>0</bShared>
|
|
||||||
</File>
|
|
||||||
<File>
|
|
||||||
<GroupNumber>8</GroupNumber>
|
|
||||||
<FileNumber>38</FileNumber>
|
|
||||||
<FileType>1</FileType>
|
|
||||||
<tvExp>0</tvExp>
|
|
||||||
<tvExpOptDlg>0</tvExpOptDlg>
|
|
||||||
<bDave2>0</bDave2>
|
|
||||||
<PathWithFileName>..\User\system\bsp\iwdgs.c</PathWithFileName>
|
|
||||||
<FilenameWithoutPath>iwdgs.c</FilenameWithoutPath>
|
|
||||||
<RteFlg>0</RteFlg>
|
|
||||||
<bShared>0</bShared>
|
|
||||||
</File>
|
|
||||||
<File>
|
|
||||||
<GroupNumber>8</GroupNumber>
|
|
||||||
<FileNumber>39</FileNumber>
|
<FileNumber>39</FileNumber>
|
||||||
<FileType>1</FileType>
|
<FileType>1</FileType>
|
||||||
<tvExp>0</tvExp>
|
<tvExp>0</tvExp>
|
||||||
<tvExpOptDlg>0</tvExpOptDlg>
|
<tvExpOptDlg>0</tvExpOptDlg>
|
||||||
<bDave2>0</bDave2>
|
<bDave2>0</bDave2>
|
||||||
<PathWithFileName>..\User\system\bsp\pwms.c</PathWithFileName>
|
|
||||||
<FilenameWithoutPath>pwms.c</FilenameWithoutPath>
|
|
||||||
<RteFlg>0</RteFlg>
|
|
||||||
<bShared>0</bShared>
|
|
||||||
</File>
|
|
||||||
<File>
|
|
||||||
<GroupNumber>8</GroupNumber>
|
|
||||||
<FileNumber>40</FileNumber>
|
|
||||||
<FileType>1</FileType>
|
|
||||||
<tvExp>0</tvExp>
|
|
||||||
<tvExpOptDlg>0</tvExpOptDlg>
|
|
||||||
<bDave2>0</bDave2>
|
|
||||||
<PathWithFileName>..\User\system\bsp\spis.c</PathWithFileName>
|
|
||||||
<FilenameWithoutPath>spis.c</FilenameWithoutPath>
|
|
||||||
<RteFlg>0</RteFlg>
|
|
||||||
<bShared>0</bShared>
|
|
||||||
</File>
|
|
||||||
<File>
|
|
||||||
<GroupNumber>8</GroupNumber>
|
|
||||||
<FileNumber>41</FileNumber>
|
|
||||||
<FileType>1</FileType>
|
|
||||||
<tvExp>0</tvExp>
|
|
||||||
<tvExpOptDlg>0</tvExpOptDlg>
|
|
||||||
<bDave2>0</bDave2>
|
|
||||||
<PathWithFileName>..\User\system\bsp\tims.c</PathWithFileName>
|
<PathWithFileName>..\User\system\bsp\tims.c</PathWithFileName>
|
||||||
<FilenameWithoutPath>tims.c</FilenameWithoutPath>
|
<FilenameWithoutPath>tims.c</FilenameWithoutPath>
|
||||||
<RteFlg>0</RteFlg>
|
<RteFlg>0</RteFlg>
|
||||||
<bShared>0</bShared>
|
<bShared>0</bShared>
|
||||||
</File>
|
</File>
|
||||||
<File>
|
|
||||||
<GroupNumber>8</GroupNumber>
|
|
||||||
<FileNumber>42</FileNumber>
|
|
||||||
<FileType>1</FileType>
|
|
||||||
<tvExp>0</tvExp>
|
|
||||||
<tvExpOptDlg>0</tvExpOptDlg>
|
|
||||||
<bDave2>0</bDave2>
|
|
||||||
<PathWithFileName>..\User\system\bsp\uarts.c</PathWithFileName>
|
|
||||||
<FilenameWithoutPath>uarts.c</FilenameWithoutPath>
|
|
||||||
<RteFlg>0</RteFlg>
|
|
||||||
<bShared>0</bShared>
|
|
||||||
</File>
|
|
||||||
</Group>
|
</Group>
|
||||||
|
|
||||||
<Group>
|
<Group>
|
||||||
|
|
|
@ -54,7 +54,7 @@
|
||||||
<CreateLib>0</CreateLib>
|
<CreateLib>0</CreateLib>
|
||||||
<CreateHexFile>1</CreateHexFile>
|
<CreateHexFile>1</CreateHexFile>
|
||||||
<DebugInformation>1</DebugInformation>
|
<DebugInformation>1</DebugInformation>
|
||||||
<BrowseInformation>1</BrowseInformation>
|
<BrowseInformation>0</BrowseInformation>
|
||||||
<ListingPath></ListingPath>
|
<ListingPath></ListingPath>
|
||||||
<HexFormatSelection>1</HexFormatSelection>
|
<HexFormatSelection>1</HexFormatSelection>
|
||||||
<Merge32K>0</Merge32K>
|
<Merge32K>0</Merge32K>
|
||||||
|
@ -339,7 +339,7 @@
|
||||||
<MiscControls></MiscControls>
|
<MiscControls></MiscControls>
|
||||||
<Define>STM32,USE_FULL_LL_DRIVER,HSE_VALUE=8000000,HSE_STARTUP_TIMEOUT=100,LSE_STARTUP_TIMEOUT=5000,LSE_VALUE=32768,EXTERNAL_CLOCK_VALUE=12288000,HSI_VALUE=16000000,LSI_VALUE=32000,VDD_VALUE=3300,PREFETCH_ENABLE=1,INSTRUCTION_CACHE_ENABLE=1,DATA_CACHE_ENABLE=1,STM32F407xx</Define>
|
<Define>STM32,USE_FULL_LL_DRIVER,HSE_VALUE=8000000,HSE_STARTUP_TIMEOUT=100,LSE_STARTUP_TIMEOUT=5000,LSE_VALUE=32768,EXTERNAL_CLOCK_VALUE=12288000,HSI_VALUE=16000000,LSI_VALUE=32000,VDD_VALUE=3300,PREFETCH_ENABLE=1,INSTRUCTION_CACHE_ENABLE=1,DATA_CACHE_ENABLE=1,STM32F407xx</Define>
|
||||||
<Undefine></Undefine>
|
<Undefine></Undefine>
|
||||||
<IncludePath>../Inc;../Drivers/STM32F4xx_HAL_Driver/Inc;../Drivers/CMSIS/Device/ST/STM32F4xx/Include;../Drivers/CMSIS/Include;../User;../User/application;../User/board;../User/system/inc;../User/system/bsp;../User/lib/inc;../User/lib/flow;../User/lib/control/inc</IncludePath>
|
<IncludePath>../Inc;../Drivers/STM32F4xx_HAL_Driver/Inc;../Drivers/CMSIS/Device/ST/STM32F4xx/Include;../Drivers/CMSIS/Include;../User;../User/application;../User/board;../User/system;../User/system/bsp;../User/system/lib/inc;../User/system/lib/flow;../User/system/lib/control/inc</IncludePath>
|
||||||
</VariousControls>
|
</VariousControls>
|
||||||
</Cads>
|
</Cads>
|
||||||
<Aads>
|
<Aads>
|
||||||
|
@ -801,94 +801,109 @@
|
||||||
</File>
|
</File>
|
||||||
</Files>
|
</Files>
|
||||||
</Group>
|
</Group>
|
||||||
<Group>
|
|
||||||
<GroupName>User/lib</GroupName>
|
|
||||||
<Files>
|
|
||||||
<File>
|
|
||||||
<FileName>aes.c</FileName>
|
|
||||||
<FileType>1</FileType>
|
|
||||||
<FilePath>..\User\lib\src\aes.c</FilePath>
|
|
||||||
</File>
|
|
||||||
<File>
|
|
||||||
<FileName>clist.c</FileName>
|
|
||||||
<FileType>1</FileType>
|
|
||||||
<FilePath>..\User\lib\src\clist.c</FilePath>
|
|
||||||
</File>
|
|
||||||
<File>
|
|
||||||
<FileName>cmac.c</FileName>
|
|
||||||
<FileType>1</FileType>
|
|
||||||
<FilePath>..\User\lib\src\cmac.c</FilePath>
|
|
||||||
</File>
|
|
||||||
<File>
|
|
||||||
<FileName>cmd.c</FileName>
|
|
||||||
<FileType>1</FileType>
|
|
||||||
<FilePath>..\User\lib\src\cmd.c</FilePath>
|
|
||||||
</File>
|
|
||||||
<File>
|
|
||||||
<FileName>data_analysis.c</FileName>
|
|
||||||
<FileType>1</FileType>
|
|
||||||
<FilePath>..\User\lib\src\data_analysis.c</FilePath>
|
|
||||||
</File>
|
|
||||||
<File>
|
|
||||||
<FileName>debug.c</FileName>
|
|
||||||
<FileType>1</FileType>
|
|
||||||
<FilePath>..\User\lib\src\debug.c</FilePath>
|
|
||||||
</File>
|
|
||||||
<File>
|
|
||||||
<FileName>filter.c</FileName>
|
|
||||||
<FileType>1</FileType>
|
|
||||||
<FilePath>..\User\lib\src\filter.c</FilePath>
|
|
||||||
</File>
|
|
||||||
<File>
|
|
||||||
<FileName>lib.c</FileName>
|
|
||||||
<FileType>1</FileType>
|
|
||||||
<FilePath>..\User\lib\src\lib.c</FilePath>
|
|
||||||
</File>
|
|
||||||
<File>
|
|
||||||
<FileName>malloc.c</FileName>
|
|
||||||
<FileType>1</FileType>
|
|
||||||
<FilePath>..\User\lib\src\malloc.c</FilePath>
|
|
||||||
</File>
|
|
||||||
<File>
|
|
||||||
<FileName>mlist.c</FileName>
|
|
||||||
<FileType>1</FileType>
|
|
||||||
<FilePath>..\User\lib\src\mlist.c</FilePath>
|
|
||||||
</File>
|
|
||||||
<File>
|
|
||||||
<FileName>pbuf.c</FileName>
|
|
||||||
<FileType>1</FileType>
|
|
||||||
<FilePath>..\User\lib\src\pbuf.c</FilePath>
|
|
||||||
</File>
|
|
||||||
<File>
|
|
||||||
<FileName>sqqueue.c</FileName>
|
|
||||||
<FileType>1</FileType>
|
|
||||||
<FilePath>..\User\lib\src\sqqueue.c</FilePath>
|
|
||||||
</File>
|
|
||||||
<File>
|
|
||||||
<FileName>flow_core.c</FileName>
|
|
||||||
<FileType>1</FileType>
|
|
||||||
<FilePath>..\User\lib\flow\flow_core.c</FilePath>
|
|
||||||
</File>
|
|
||||||
</Files>
|
|
||||||
</Group>
|
|
||||||
<Group>
|
<Group>
|
||||||
<GroupName>User/system</GroupName>
|
<GroupName>User/system</GroupName>
|
||||||
<Files>
|
<Files>
|
||||||
<File>
|
<File>
|
||||||
<FileName>btn.c</FileName>
|
<FileName>btn.c</FileName>
|
||||||
<FileType>1</FileType>
|
<FileType>1</FileType>
|
||||||
<FilePath>..\User\system\src\btn.c</FilePath>
|
<FilePath>..\User\system\btn.c</FilePath>
|
||||||
</File>
|
</File>
|
||||||
<File>
|
<File>
|
||||||
<FileName>delay.c</FileName>
|
<FileName>delay.c</FileName>
|
||||||
<FileType>1</FileType>
|
<FileType>1</FileType>
|
||||||
<FilePath>..\User\system\src\delay.c</FilePath>
|
<FilePath>..\User\system\delay.c</FilePath>
|
||||||
</File>
|
</File>
|
||||||
<File>
|
<File>
|
||||||
<FileName>sys.c</FileName>
|
<FileName>sys.c</FileName>
|
||||||
<FileType>1</FileType>
|
<FileType>1</FileType>
|
||||||
<FilePath>..\User\system\src\sys.c</FilePath>
|
<FilePath>..\User\system\sys.c</FilePath>
|
||||||
</File>
|
</File>
|
||||||
|
</Files>
|
||||||
|
</Group>
|
||||||
|
<Group>
|
||||||
|
<GroupName>User/lib</GroupName>
|
||||||
|
<Files>
|
||||||
|
<File>
|
||||||
|
<FileName>aes.c</FileName>
|
||||||
|
<FileType>1</FileType>
|
||||||
|
<FilePath>..\User\system\lib\src\aes.c</FilePath>
|
||||||
|
</File>
|
||||||
|
<File>
|
||||||
|
<FileName>clist.c</FileName>
|
||||||
|
<FileType>1</FileType>
|
||||||
|
<FilePath>..\User\system\lib\src\clist.c</FilePath>
|
||||||
|
</File>
|
||||||
|
<File>
|
||||||
|
<FileName>cmac.c</FileName>
|
||||||
|
<FileType>1</FileType>
|
||||||
|
<FilePath>..\User\system\lib\src\cmac.c</FilePath>
|
||||||
|
</File>
|
||||||
|
<File>
|
||||||
|
<FileName>cmd.c</FileName>
|
||||||
|
<FileType>1</FileType>
|
||||||
|
<FilePath>..\User\system\lib\src\cmd.c</FilePath>
|
||||||
|
</File>
|
||||||
|
<File>
|
||||||
|
<FileName>data_analysis.c</FileName>
|
||||||
|
<FileType>1</FileType>
|
||||||
|
<FilePath>..\User\system\lib\src\data_analysis.c</FilePath>
|
||||||
|
</File>
|
||||||
|
<File>
|
||||||
|
<FileName>debug.c</FileName>
|
||||||
|
<FileType>1</FileType>
|
||||||
|
<FilePath>..\User\system\lib\src\debug.c</FilePath>
|
||||||
|
</File>
|
||||||
|
<File>
|
||||||
|
<FileName>filter.c</FileName>
|
||||||
|
<FileType>1</FileType>
|
||||||
|
<FilePath>..\User\system\lib\src\filter.c</FilePath>
|
||||||
|
</File>
|
||||||
|
<File>
|
||||||
|
<FileName>lib.c</FileName>
|
||||||
|
<FileType>1</FileType>
|
||||||
|
<FilePath>..\User\system\lib\src\lib.c</FilePath>
|
||||||
|
</File>
|
||||||
|
<File>
|
||||||
|
<FileName>malloc.c</FileName>
|
||||||
|
<FileType>1</FileType>
|
||||||
|
<FilePath>..\User\system\lib\src\malloc.c</FilePath>
|
||||||
|
</File>
|
||||||
|
<File>
|
||||||
|
<FileName>mlist.c</FileName>
|
||||||
|
<FileType>1</FileType>
|
||||||
|
<FilePath>..\User\system\lib\src\mlist.c</FilePath>
|
||||||
|
</File>
|
||||||
|
<File>
|
||||||
|
<FileName>pbuf.c</FileName>
|
||||||
|
<FileType>1</FileType>
|
||||||
|
<FilePath>..\User\system\lib\src\pbuf.c</FilePath>
|
||||||
|
</File>
|
||||||
|
<File>
|
||||||
|
<FileName>sqqueue.c</FileName>
|
||||||
|
<FileType>1</FileType>
|
||||||
|
<FilePath>..\User\system\lib\src\sqqueue.c</FilePath>
|
||||||
|
</File>
|
||||||
|
<File>
|
||||||
|
<FileName>storage.c</FileName>
|
||||||
|
<FileType>1</FileType>
|
||||||
|
<FilePath>..\User\system\lib\src\storage.c</FilePath>
|
||||||
|
</File>
|
||||||
|
<File>
|
||||||
|
<FileName>wl_flash.c</FileName>
|
||||||
|
<FileType>1</FileType>
|
||||||
|
<FilePath>..\User\system\lib\src\wl_flash.c</FilePath>
|
||||||
|
</File>
|
||||||
|
<File>
|
||||||
|
<FileName>flow_core.c</FileName>
|
||||||
|
<FileType>1</FileType>
|
||||||
|
<FilePath>..\User\system\lib\flow\flow_core.c</FilePath>
|
||||||
|
</File>
|
||||||
|
</Files>
|
||||||
|
</Group>
|
||||||
|
<Group>
|
||||||
|
<GroupName>User/system/bsp</GroupName>
|
||||||
|
<Files>
|
||||||
<File>
|
<File>
|
||||||
<FileName>adcs.c</FileName>
|
<FileName>adcs.c</FileName>
|
||||||
<FileType>1</FileType>
|
<FileType>1</FileType>
|
||||||
|
@ -904,240 +919,11 @@
|
||||||
<FileType>1</FileType>
|
<FileType>1</FileType>
|
||||||
<FilePath>..\User\system\bsp\gpios.c</FilePath>
|
<FilePath>..\User\system\bsp\gpios.c</FilePath>
|
||||||
</File>
|
</File>
|
||||||
<File>
|
|
||||||
<FileName>i2cs.c</FileName>
|
|
||||||
<FileType>1</FileType>
|
|
||||||
<FilePath>..\User\system\bsp\i2cs.c</FilePath>
|
|
||||||
<FileOption>
|
|
||||||
<CommonProperty>
|
|
||||||
<UseCPPCompiler>2</UseCPPCompiler>
|
|
||||||
<RVCTCodeConst>0</RVCTCodeConst>
|
|
||||||
<RVCTZI>0</RVCTZI>
|
|
||||||
<RVCTOtherData>0</RVCTOtherData>
|
|
||||||
<ModuleSelection>0</ModuleSelection>
|
|
||||||
<IncludeInBuild>0</IncludeInBuild>
|
|
||||||
<AlwaysBuild>0</AlwaysBuild>
|
|
||||||
<GenerateAssemblyFile>2</GenerateAssemblyFile>
|
|
||||||
<AssembleAssemblyFile>2</AssembleAssemblyFile>
|
|
||||||
<PublicsOnly>2</PublicsOnly>
|
|
||||||
<StopOnExitCode>11</StopOnExitCode>
|
|
||||||
<CustomArgument></CustomArgument>
|
|
||||||
<IncludeLibraryModules></IncludeLibraryModules>
|
|
||||||
<ComprImg>1</ComprImg>
|
|
||||||
</CommonProperty>
|
|
||||||
<FileArmAds>
|
|
||||||
<Cads>
|
|
||||||
<interw>2</interw>
|
|
||||||
<Optim>0</Optim>
|
|
||||||
<oTime>2</oTime>
|
|
||||||
<SplitLS>2</SplitLS>
|
|
||||||
<OneElfS>2</OneElfS>
|
|
||||||
<Strict>2</Strict>
|
|
||||||
<EnumInt>2</EnumInt>
|
|
||||||
<PlainCh>2</PlainCh>
|
|
||||||
<Ropi>2</Ropi>
|
|
||||||
<Rwpi>2</Rwpi>
|
|
||||||
<wLevel>0</wLevel>
|
|
||||||
<uThumb>2</uThumb>
|
|
||||||
<uSurpInc>2</uSurpInc>
|
|
||||||
<uC99>2</uC99>
|
|
||||||
<uGnu>2</uGnu>
|
|
||||||
<useXO>2</useXO>
|
|
||||||
<v6Lang>0</v6Lang>
|
|
||||||
<v6LangP>0</v6LangP>
|
|
||||||
<vShortEn>2</vShortEn>
|
|
||||||
<vShortWch>2</vShortWch>
|
|
||||||
<v6Lto>2</v6Lto>
|
|
||||||
<v6WtE>2</v6WtE>
|
|
||||||
<v6Rtti>2</v6Rtti>
|
|
||||||
<VariousControls>
|
|
||||||
<MiscControls></MiscControls>
|
|
||||||
<Define></Define>
|
|
||||||
<Undefine></Undefine>
|
|
||||||
<IncludePath></IncludePath>
|
|
||||||
</VariousControls>
|
|
||||||
</Cads>
|
|
||||||
</FileArmAds>
|
|
||||||
</FileOption>
|
|
||||||
</File>
|
|
||||||
<File>
|
|
||||||
<FileName>iwdgs.c</FileName>
|
|
||||||
<FileType>1</FileType>
|
|
||||||
<FilePath>..\User\system\bsp\iwdgs.c</FilePath>
|
|
||||||
</File>
|
|
||||||
<File>
|
|
||||||
<FileName>pwms.c</FileName>
|
|
||||||
<FileType>1</FileType>
|
|
||||||
<FilePath>..\User\system\bsp\pwms.c</FilePath>
|
|
||||||
<FileOption>
|
|
||||||
<CommonProperty>
|
|
||||||
<UseCPPCompiler>2</UseCPPCompiler>
|
|
||||||
<RVCTCodeConst>0</RVCTCodeConst>
|
|
||||||
<RVCTZI>0</RVCTZI>
|
|
||||||
<RVCTOtherData>0</RVCTOtherData>
|
|
||||||
<ModuleSelection>0</ModuleSelection>
|
|
||||||
<IncludeInBuild>0</IncludeInBuild>
|
|
||||||
<AlwaysBuild>0</AlwaysBuild>
|
|
||||||
<GenerateAssemblyFile>2</GenerateAssemblyFile>
|
|
||||||
<AssembleAssemblyFile>2</AssembleAssemblyFile>
|
|
||||||
<PublicsOnly>2</PublicsOnly>
|
|
||||||
<StopOnExitCode>11</StopOnExitCode>
|
|
||||||
<CustomArgument></CustomArgument>
|
|
||||||
<IncludeLibraryModules></IncludeLibraryModules>
|
|
||||||
<ComprImg>1</ComprImg>
|
|
||||||
</CommonProperty>
|
|
||||||
<FileArmAds>
|
|
||||||
<Cads>
|
|
||||||
<interw>2</interw>
|
|
||||||
<Optim>0</Optim>
|
|
||||||
<oTime>2</oTime>
|
|
||||||
<SplitLS>2</SplitLS>
|
|
||||||
<OneElfS>2</OneElfS>
|
|
||||||
<Strict>2</Strict>
|
|
||||||
<EnumInt>2</EnumInt>
|
|
||||||
<PlainCh>2</PlainCh>
|
|
||||||
<Ropi>2</Ropi>
|
|
||||||
<Rwpi>2</Rwpi>
|
|
||||||
<wLevel>0</wLevel>
|
|
||||||
<uThumb>2</uThumb>
|
|
||||||
<uSurpInc>2</uSurpInc>
|
|
||||||
<uC99>2</uC99>
|
|
||||||
<uGnu>2</uGnu>
|
|
||||||
<useXO>2</useXO>
|
|
||||||
<v6Lang>0</v6Lang>
|
|
||||||
<v6LangP>0</v6LangP>
|
|
||||||
<vShortEn>2</vShortEn>
|
|
||||||
<vShortWch>2</vShortWch>
|
|
||||||
<v6Lto>2</v6Lto>
|
|
||||||
<v6WtE>2</v6WtE>
|
|
||||||
<v6Rtti>2</v6Rtti>
|
|
||||||
<VariousControls>
|
|
||||||
<MiscControls></MiscControls>
|
|
||||||
<Define></Define>
|
|
||||||
<Undefine></Undefine>
|
|
||||||
<IncludePath></IncludePath>
|
|
||||||
</VariousControls>
|
|
||||||
</Cads>
|
|
||||||
</FileArmAds>
|
|
||||||
</FileOption>
|
|
||||||
</File>
|
|
||||||
<File>
|
|
||||||
<FileName>spis.c</FileName>
|
|
||||||
<FileType>1</FileType>
|
|
||||||
<FilePath>..\User\system\bsp\spis.c</FilePath>
|
|
||||||
<FileOption>
|
|
||||||
<CommonProperty>
|
|
||||||
<UseCPPCompiler>2</UseCPPCompiler>
|
|
||||||
<RVCTCodeConst>0</RVCTCodeConst>
|
|
||||||
<RVCTZI>0</RVCTZI>
|
|
||||||
<RVCTOtherData>0</RVCTOtherData>
|
|
||||||
<ModuleSelection>0</ModuleSelection>
|
|
||||||
<IncludeInBuild>0</IncludeInBuild>
|
|
||||||
<AlwaysBuild>0</AlwaysBuild>
|
|
||||||
<GenerateAssemblyFile>2</GenerateAssemblyFile>
|
|
||||||
<AssembleAssemblyFile>2</AssembleAssemblyFile>
|
|
||||||
<PublicsOnly>2</PublicsOnly>
|
|
||||||
<StopOnExitCode>11</StopOnExitCode>
|
|
||||||
<CustomArgument></CustomArgument>
|
|
||||||
<IncludeLibraryModules></IncludeLibraryModules>
|
|
||||||
<ComprImg>1</ComprImg>
|
|
||||||
</CommonProperty>
|
|
||||||
<FileArmAds>
|
|
||||||
<Cads>
|
|
||||||
<interw>2</interw>
|
|
||||||
<Optim>0</Optim>
|
|
||||||
<oTime>2</oTime>
|
|
||||||
<SplitLS>2</SplitLS>
|
|
||||||
<OneElfS>2</OneElfS>
|
|
||||||
<Strict>2</Strict>
|
|
||||||
<EnumInt>2</EnumInt>
|
|
||||||
<PlainCh>2</PlainCh>
|
|
||||||
<Ropi>2</Ropi>
|
|
||||||
<Rwpi>2</Rwpi>
|
|
||||||
<wLevel>0</wLevel>
|
|
||||||
<uThumb>2</uThumb>
|
|
||||||
<uSurpInc>2</uSurpInc>
|
|
||||||
<uC99>2</uC99>
|
|
||||||
<uGnu>2</uGnu>
|
|
||||||
<useXO>2</useXO>
|
|
||||||
<v6Lang>0</v6Lang>
|
|
||||||
<v6LangP>0</v6LangP>
|
|
||||||
<vShortEn>2</vShortEn>
|
|
||||||
<vShortWch>2</vShortWch>
|
|
||||||
<v6Lto>2</v6Lto>
|
|
||||||
<v6WtE>2</v6WtE>
|
|
||||||
<v6Rtti>2</v6Rtti>
|
|
||||||
<VariousControls>
|
|
||||||
<MiscControls></MiscControls>
|
|
||||||
<Define></Define>
|
|
||||||
<Undefine></Undefine>
|
|
||||||
<IncludePath></IncludePath>
|
|
||||||
</VariousControls>
|
|
||||||
</Cads>
|
|
||||||
</FileArmAds>
|
|
||||||
</FileOption>
|
|
||||||
</File>
|
|
||||||
<File>
|
<File>
|
||||||
<FileName>tims.c</FileName>
|
<FileName>tims.c</FileName>
|
||||||
<FileType>1</FileType>
|
<FileType>1</FileType>
|
||||||
<FilePath>..\User\system\bsp\tims.c</FilePath>
|
<FilePath>..\User\system\bsp\tims.c</FilePath>
|
||||||
</File>
|
</File>
|
||||||
<File>
|
|
||||||
<FileName>uarts.c</FileName>
|
|
||||||
<FileType>1</FileType>
|
|
||||||
<FilePath>..\User\system\bsp\uarts.c</FilePath>
|
|
||||||
<FileOption>
|
|
||||||
<CommonProperty>
|
|
||||||
<UseCPPCompiler>2</UseCPPCompiler>
|
|
||||||
<RVCTCodeConst>0</RVCTCodeConst>
|
|
||||||
<RVCTZI>0</RVCTZI>
|
|
||||||
<RVCTOtherData>0</RVCTOtherData>
|
|
||||||
<ModuleSelection>0</ModuleSelection>
|
|
||||||
<IncludeInBuild>0</IncludeInBuild>
|
|
||||||
<AlwaysBuild>0</AlwaysBuild>
|
|
||||||
<GenerateAssemblyFile>2</GenerateAssemblyFile>
|
|
||||||
<AssembleAssemblyFile>2</AssembleAssemblyFile>
|
|
||||||
<PublicsOnly>2</PublicsOnly>
|
|
||||||
<StopOnExitCode>11</StopOnExitCode>
|
|
||||||
<CustomArgument></CustomArgument>
|
|
||||||
<IncludeLibraryModules></IncludeLibraryModules>
|
|
||||||
<ComprImg>1</ComprImg>
|
|
||||||
</CommonProperty>
|
|
||||||
<FileArmAds>
|
|
||||||
<Cads>
|
|
||||||
<interw>2</interw>
|
|
||||||
<Optim>0</Optim>
|
|
||||||
<oTime>2</oTime>
|
|
||||||
<SplitLS>2</SplitLS>
|
|
||||||
<OneElfS>2</OneElfS>
|
|
||||||
<Strict>2</Strict>
|
|
||||||
<EnumInt>2</EnumInt>
|
|
||||||
<PlainCh>2</PlainCh>
|
|
||||||
<Ropi>2</Ropi>
|
|
||||||
<Rwpi>2</Rwpi>
|
|
||||||
<wLevel>0</wLevel>
|
|
||||||
<uThumb>2</uThumb>
|
|
||||||
<uSurpInc>2</uSurpInc>
|
|
||||||
<uC99>2</uC99>
|
|
||||||
<uGnu>2</uGnu>
|
|
||||||
<useXO>2</useXO>
|
|
||||||
<v6Lang>0</v6Lang>
|
|
||||||
<v6LangP>0</v6LangP>
|
|
||||||
<vShortEn>2</vShortEn>
|
|
||||||
<vShortWch>2</vShortWch>
|
|
||||||
<v6Lto>2</v6Lto>
|
|
||||||
<v6WtE>2</v6WtE>
|
|
||||||
<v6Rtti>2</v6Rtti>
|
|
||||||
<VariousControls>
|
|
||||||
<MiscControls></MiscControls>
|
|
||||||
<Define></Define>
|
|
||||||
<Undefine></Undefine>
|
|
||||||
<IncludePath></IncludePath>
|
|
||||||
</VariousControls>
|
|
||||||
</Cads>
|
|
||||||
</FileArmAds>
|
|
||||||
</FileOption>
|
|
||||||
</File>
|
|
||||||
</Files>
|
</Files>
|
||||||
</Group>
|
</Group>
|
||||||
<Group>
|
<Group>
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
:020000040800F2
|
:020000040800F2
|
||||||
:10000000F01C0020A1010008990C00085D02000806
|
:10000000F0E50020A1010008AD0C00087D02000809
|
||||||
:10001000950C000817020008D90E00080000000027
|
:10001000A90C000851020008ED0E000800000000C5
|
||||||
:100020000000000000000000000000009F0C00081D
|
:10002000000000000000000000000000B30C000809
|
||||||
:100030005B020008000000009D0C0008A10C0008F5
|
:100030007B02000800000000B10C0008B50C0008AD
|
||||||
:10004000BB010008BB010008BB010008BB010008A0
|
:10004000BB010008BB010008BB010008BB010008A0
|
||||||
:10005000BB010008BB010008BB010008BB01000890
|
:10005000BB010008BB010008BB010008BB01000890
|
||||||
:10006000BB010008BB010008BB010008BB01000880
|
:10006000BB010008BB010008BB010008BB01000880
|
||||||
:10007000BB010008BB010008BB010008BB01000870
|
:10007000BB010008BB010008BB010008BB01000870
|
||||||
:10008000BB010008BB0100080D020008BB0100080D
|
:10008000BB010008BB01000847020008BB010008D3
|
||||||
:10009000BB010008BB010008BB010008BB01000850
|
:10009000BB010008BB010008BB010008BB01000850
|
||||||
:1000A000BB010008BB010008BB010008BB01000840
|
:1000A000BB010008BB010008BB010008BB01000840
|
||||||
:1000B000BB010008BB010008BB010008BB01000830
|
:1000B000BB010008BB010008BB010008BB01000830
|
||||||
|
@ -16,396 +16,407 @@
|
||||||
:1000E000BB010008BB010008BB010008BB01000800
|
:1000E000BB010008BB010008BB010008BB01000800
|
||||||
:1000F000BB010008BB010008BB010008BB010008F0
|
:1000F000BB010008BB010008BB010008BB010008F0
|
||||||
:10010000BB010008BB010008BB010008BB010008DF
|
:10010000BB010008BB010008BB010008BB010008DF
|
||||||
:10011000BB010008BB010008F10D0008BB0100088D
|
:10011000BB010008BB010008050E0008BB01000878
|
||||||
:1001200051020008BB010008BB010008BB01000828
|
:1001200071020008BB010008BB010008BB01000808
|
||||||
:10013000BB010008BB010008BB010008BB010008AF
|
:10013000BB010008BB010008BB010008BB010008AF
|
||||||
:10014000BB010008BB010008BB010008BB0100089F
|
:10014000BB010008BB010008BB010008BB0100089F
|
||||||
:10015000BB010008BB010008BB010008BB0100088F
|
:10015000BB010008BB010008BB010008BB0100088F
|
||||||
:10016000BB010008BB010008BB010008BB0100087F
|
:10016000BB010008BB010008BB010008BB0100087F
|
||||||
:10017000BB010008BB010008BB0100080000000033
|
:10017000BB010008BB010008BB0100080000000033
|
||||||
:10018000BB010008BB010008DFF810D000F02CF81C
|
:10018000BB010008BB010008DFF810D000F02CF81C
|
||||||
:1001900000480047C1150008AFF30080F01C0020A4
|
:1001900000480047D1150008AFF30080F0E50020CB
|
||||||
:1001A0000648804706480047FEE7FEE7FEE7FEE711
|
:1001A0000648804706480047FEE7FEE7FEE7FEE711
|
||||||
:1001B000FEE7FEE7FEE7FEE7FEE7FEE7DD0D0008EF
|
:1001B000FEE7FEE7FEE7FEE7FEE7FEE7F10D0008DB
|
||||||
:1001C00089010008D2B201E000F8012B491EFBD2E0
|
:1001C00089010008D2B201E000F8012B491EFBD2E0
|
||||||
:1001D00070470022F6E710B513460A460446194652
|
:1001D00070470022F6E710B513460A460446194652
|
||||||
:1001E000FFF7F0FF204610BD064C074D06E0E06823
|
:1001E000FFF7F0FF204610BD064C074D06E0E06823
|
||||||
:1001F00040F0010394E8070098471034AC42F6D36E
|
:1001F00040F0010394E8070098471034AC42F6D36E
|
||||||
:10020000FFF7C6FFE01800081019000810B500201D
|
:10020000FFF7C6FF341900085419000830B58C18E0
|
||||||
:1002100000F0CAFE10BD00BFFEE7000030B5024688
|
:1002100010F8012B12F00F0301D110F8013B120965
|
||||||
:100220000B4600BF7AB90220084C616920EA01043C
|
:1002200006D110F8012B03E010F8015B01F8015B27
|
||||||
:1002300001EA000544EA0544044DAC6100BF01E059
|
:100230005B1EF9D101E001F8013B521EFBD1A14246
|
||||||
:1002400000BF00BFFCE700BF012030BD001002402E
|
:10024000E6D3002030BD10B5002000F0B5FE10BD93
|
||||||
:1002500010B5002000F07CFE10BD704700BFFEE727
|
:1002500000BFFEE770B504460D4600BF2CB901F0A3
|
||||||
:100260002DE9F04105460C460026606800B100BF4C
|
:1002600003FB01E000BF00BFFCE700BF012070BD41
|
||||||
:10027000134800F04FF80746124800F04BF80743C8
|
:1002700010B5002000F076FE10BD704700BFFEE70D
|
||||||
:10028000114800F047F80743AFB9606860B1D4E99E
|
:100280002DE9F04105460C460026606800B100BF2C
|
||||||
:1002900000010843A1680843E168084369680B4A04
|
:10029000134800F049F80746124800F045F80743B4
|
||||||
:1002A00011400843686007E0686808490840216811
|
:1002A000114800F041F80743AFB9606860B1D4E984
|
||||||
:1002B0000843686000E001263046BDE8F081000098
|
:1002B00000010843A1680843E168084369680B4AE4
|
||||||
:1002C000002001400021014000220140E010FCFF1D
|
:1002C00011400843686007E06868084908402168F1
|
||||||
:1002D000816821F0010181607047000070B504461B
|
:1002D0000843686000E001263046BDE8F081000078
|
||||||
:1002E0000D460026204600F015F870B9A968286868
|
:1002E000002001400021014000220140E010FCFFFD
|
||||||
:1002F00008436168064A114008436060A06820F422
|
:1002F00070B504460D460026204600F015F870B98A
|
||||||
:10030000006069680843A06000E00126304670BDC7
|
:10030000A968286808436168064A1140084360608C
|
||||||
:10031000FFFEFFFC0146886800F001007047000006
|
:10031000A06820F4006069680843A06000E001263E
|
||||||
:1003200070B504460D460026686800B100BF20463F
|
:10032000304670BDFFFEFFFC0146886800F001000A
|
||||||
:10033000FFF7F0FF00BB686830B1606820F46840E8
|
:100330007047000070B504460D460026686800B19D
|
||||||
:10034000A9680843606003E0606820F4684060606A
|
:1003400000BF2046FFF7F0FF00BB686830B160686F
|
||||||
:10035000286800F07060E968084329690843A168CB
|
:1003500020F46840A9680843606003E0606820F406
|
||||||
:10036000074A11400843A0606868E16A21F47001FF
|
:1003600068406060286800F07060E96808432969A7
|
||||||
:100370000143E16200BF00E00126304670BD00008D
|
:100370000843A168074A11400843A0606868E16A21
|
||||||
:10038000FDFCFFC070B501F440744FF4407595FA60
|
:1003800021F470010143E16200BF00E00126304624
|
||||||
:10039000A5F5B5FA85F5EC4000F12C0505EB8403D5
|
:1003900070BD0000FDFCFFC070B501F440744FF467
|
||||||
:1003A0001C6801F01F061F25B540AC4302F01F0575
|
:1003A000407595FAA5F5B5FA85F5EC4000F12C05F8
|
||||||
:1003B00001F01F06B5402C431C6070BD70B501F004
|
:1003B00005EB84031C6801F01F061F25B540AC4304
|
||||||
:1003C00000744FF0007595FAA5F5B5FA85F5EC4087
|
:1003C00002F01F0501F01F06B5402C431C6070BDF4
|
||||||
:1003D00000F10C0505EB84031C6801F0F8754FF083
|
:1003D00070B501F000744FF0007595FAA5F5B5FA07
|
||||||
:1003E000F87696FAA6F6B6FA86F6F5400726AE40F7
|
:1003E00085F5EC4000F10C0505EB84031C6801F079
|
||||||
:1003F000B44301F0F8754FF0F87696FAA6F6B6FA1F
|
:1003F000F8754FF0F87696FAA6F6B6FA86F6F54056
|
||||||
:1004000086F6F54002FA05F52C431C6070BD426883
|
:100400000726AE40B44301F0F8754FF0F87696FA3F
|
||||||
:1004100022F440020A4342607047426822F44002DC
|
:10041000A6F6B6FA86F6F54002FA05F52C431C60FE
|
||||||
:100420000A4342607047000008B505490968014366
|
:1004200070BD426822F440020A434260704742684D
|
||||||
:10043000034A1160114609680140009100BF08BDE0
|
:1004300022F440020A4342607047000008B50549B3
|
||||||
:1004400030380240F0B502460B46002400211868FF
|
:1004400009680143034A116011460968014000919F
|
||||||
:1004500090FAA0F0B0FA80F48AE00125A54018686F
|
:1004500000BF08BD30380240F0B502460B4600240C
|
||||||
:1004600000EA050100297DD05868012802D05868AB
|
:100460000021186890FAA0F0B0FA80F48AE0012523
|
||||||
:1004700002281CD19868956891FAA1F6B6FA86F61A
|
:10047000A540186800EA050100297DD058680128C8
|
||||||
:1004800077000326BE40B54391FAA1F6B6FA86F688
|
:1004800002D0586802281CD19868956891FAA1F6A4
|
||||||
:10049000760000FA06F63543956000BFD8685568C7
|
:10049000B6FA86F677000326BE40B54391FAA1F678
|
||||||
:1004A0008D4301FB00F63543556000BF00BF18695E
|
:1004A000B6FA86F6760000FA06F63543956000BF88
|
||||||
:1004B000D56891FAA1F6B6FA86F677000326BE4013
|
:1004B000D86855688D4301FB00F63543556000BF91
|
||||||
:1004C000B54391FAA1F6B6FA86F6760000FA06F67A
|
:1004C00000BF1869D56891FAA1F6B6FA86F67700EA
|
||||||
:1004D0003543D56000BF5868022831D191FAA1F0A8
|
:1004D0000326BE40B54391FAA1F6B6FA86F6760039
|
||||||
:1004E000B0FA80F0082814D25869156A91FAA1F67A
|
:1004E00000FA06F63543D56000BF5868022831D1BE
|
||||||
:1004F000B6FA86F6B7000F26BE40B54391FAA1F6CC
|
:1004F00091FAA1F0B0FA80F0082814D25869156A70
|
||||||
:10050000B6FA86F6B60000FA06F63543156200BF65
|
:1005000091FAA1F6B6FA86F6B7000F26BE40B543BB
|
||||||
:1005100016E05869556A0E0A96FAA6F6B6FA86F6F5
|
:1005100091FAA1F6B6FA86F6B60000FA06F6354369
|
||||||
:10052000B7000F26BE40B5430E0A96FAA6F6B6FAF5
|
:10052000156200BF16E05869556A0E0A96FAA6F6DB
|
||||||
:1005300086F6B60000FA06F63543556200BF00BFE6
|
:10053000B6FA86F6B7000F26BE40B5430E0A96FA05
|
||||||
:100540005868156891FAA1F6B6FA86F67700032680
|
:10054000A6F6B6FA86F6B60000FA06F63543556208
|
||||||
:10055000BE40B54391FAA1F6B6FA86F6760000FAE7
|
:1005500000BF00BF5868156891FAA1F6B6FA86F692
|
||||||
:1005600006F600E003E03543156000BF00BF641CE1
|
:1005600077000326BE40B54391FAA1F6B6FA86F6A7
|
||||||
:100570001868E04000287FF470AFF0BD10B5426904
|
:10057000760000FA06F600E003E03543156000BFA0
|
||||||
:1005800021EA020302EA010443EA0443836110BD45
|
:1005800000BF641C1868E04000287FF470AFF0BD25
|
||||||
:1005900002480068401C0149086070474C00002078
|
:1005900010B5426921EA020302EA010443EA044376
|
||||||
:1005A0004FF47A71B0FBF1F2521E4FF0E0235A6122
|
:1005A000836110BD02480068401C01490860704723
|
||||||
:1005B00000229A6105221A6100BF70470149086054
|
:1005B000240000204FF47A71B0FBF1F2521E4FF08C
|
||||||
:1005C000704700000000002010B5024613682C4858
|
:1005C000E0235A6100229A6105221A6100BF704738
|
||||||
:1005D00082420ED0B2F1804F0BD02A48824208D01E
|
:1005D00001490860704700000000002010B5024685
|
||||||
:1005E0002948824205D02948824202D028488242C6
|
:1005E00013682C4882420ED0B2F1804F0BD02A48BB
|
||||||
:1005F00004D123F070004C6840EA04032048824292
|
:1005F000824208D02948824205D02948824202D04E
|
||||||
:1006000020D0B2F1804F1DD01E4882421AD01E4821
|
:100600002848824204D123F070004C6840EA040379
|
||||||
:10061000824217D01D48824214D01D48824211D018
|
:100610002048824220D0B2F1804F1DD01E48824235
|
||||||
:100620001C4882420ED01C4882420BD01B4882429A
|
:100620001AD01E48824217D01D48824214D01D485D
|
||||||
:1006300008D01B48824205D01A48824202D01A488C
|
:10063000824211D01C4882420ED01C4882420BD00C
|
||||||
:10064000824204D123F44070CC6840EA0403136072
|
:100640001B48824208D01B48824205D01A48824289
|
||||||
:100650008868D06200BF0888906200BF0848824264
|
:1006500002D01A48824204D123F44070CC6840EAA8
|
||||||
:1006600002D00B48824203D10869106300BF00BF6B
|
:10066000040313608868D06200BF0888906200BFEE
|
||||||
:1006700000BF506940F00100506100BF002010BD74
|
:100670000848824202D00B48824203D108691063C5
|
||||||
:10068000000001400004004000080040000C004051
|
:1006800000BF00BF00BF506940F00100506100BFD3
|
||||||
:100690000004014000400140004401400048014086
|
:10069000002010BD000001400004004000080040A0
|
||||||
:1006A00000180040001C004000200040014608697E
|
:1006A000000C0040000401400040014000440140B3
|
||||||
:1006B00000F00100704708B54FF0E0210969009192
|
:1006B0000048014000180040001C0040002000409D
|
||||||
:1006C00000BF411C01B1401C06E04FF0E021096968
|
:1006C0000146086900F00100704708B54FF0E021CD
|
||||||
:1006D00001F4803101B1401E0028F6D108BD0000B0
|
:1006D0000969009100BF411C01B1401C06E04FF0C8
|
||||||
:1006E0002DE9F0418EB000200B900C900D9014215C
|
:1006E000E021096901F4803101B1401E0028F6D1F2
|
||||||
:1006F00006A8FFF76EFD002002900390049005907D
|
:1006F00008BD00002DE9F0418EB000200B900C9059
|
||||||
:100700004FF48070874909680143864A1160114699
|
:100700000D90142106A8FFF764FD002002900390CD
|
||||||
:1007100009680140019100BF00BF834800210A46DB
|
:10071000049005904FF48070874909680143864A28
|
||||||
:10072000824B5B5CC35823F0606313437F4C645C73
|
:100720001160114609680140019100BF00BF834874
|
||||||
:10073000035100BF00BF7D4B5B5CC35823F0C00377
|
:1007300000210A46824B5B5CC35823F0606313437D
|
||||||
:1007400013437A4C645C035100BF00BF774B5B5C82
|
:100740007F4C645C035100BF00BF7D4B5B5CC358B2
|
||||||
:10075000C35823F440331343744C645C035100BF0B
|
:1007500023F0C00313437A4C645C035100BF00BF15
|
||||||
:100760008215724B5B5CC35823F4907313436F4C38
|
:10076000774B5B5CC35823F440331343744C645C95
|
||||||
:10077000645C035100BF0A466C4B5B5CC35823F4B6
|
:10077000035100BF8215724B5B5CC35823F4907326
|
||||||
:1007800000731343694C645C035100BF0215674B4F
|
:1007800013436F4C645C035100BF0A466C4B5B5CC7
|
||||||
:100790005B5CC35823F480631343644C645C035173
|
:10079000C35823F400731343694C645C035100BFD6
|
||||||
:1007A00000BFC214614B5B5CC35823F4C0531343B6
|
:1007A0000215674B5B5CC35823F480631343644CAE
|
||||||
:1007B0005E4C645C035100BF92005C4B5B5CC358B1
|
:1007B000645C035100BFC214614B5B5CC35823F4FB
|
||||||
:1007C00023F4C0431343594C645C035100BF00BF82
|
:1007C000C05313435E4C645C035100BF92005C4B0A
|
||||||
:1007D000564A525C0244526922F00402534B5B5C5D
|
:1007D0005B5CC35823F4C0431343594C645C03511E
|
||||||
:1007E00003445A6100BF1221514B1B68C3F302201E
|
:1007E00000BF00BF564A525C0244526922F0040224
|
||||||
:1007F000002425460346C3F1070CBCF1040F02D9BF
|
:1007F000534B5B5C03445A6100BF1221514B1B6891
|
||||||
:100800004FF0040C01E0C3F1070C674603F1040C40
|
:10080000C3F30220002425460346C3F1070CBCF1C4
|
||||||
:10081000BCF1070F02D24FF0000C01E0A3F1030C72
|
:10081000040F02D94FF0040C01E0C3F1070C674646
|
||||||
:1008200066464FF0010C0CFA07FCACF1010C0CEA27
|
:1008200003F1040CBCF1070F02D24FF0000C01E001
|
||||||
:10083000040C0CFA06FC4FF0010808FA06F8A8F1BF
|
:10083000A3F1030C66464FF0010C0CFA07FCACF177
|
||||||
:10084000010808EA05084CEA080200BF002904DB99
|
:10084000010C0CEA040C0CFA06FC4FF0010808FA43
|
||||||
:100850001007030E3748435407E01007040E3448CE
|
:1008500006F8A8F1010808EA05084CEA080200BFFA
|
||||||
:100860000C3001F00F031B1FC45400BF12200028DE
|
:10086000002904DB1007030E3748435407E0100744
|
||||||
:1008700009DB00F01F02012191404209920002F1C0
|
:10087000040E34480C3001F00F031B1FC45400BF9A
|
||||||
:10088000E022C2F8001100BF00200B900C904FF442
|
:100880001220002809DB00F01F02012191404209DB
|
||||||
:1008900080700D900BA92848FFF720FD00200690DE
|
:10089000920002F1E022C2F8001100BF00200B908C
|
||||||
:1008A0004FF48010079000200890022009904FF428
|
:1008A0000C904FF480700D900BA92848FFF720FDA5
|
||||||
:1008B00040700A9006A92048FFF732FD00201E492B
|
:1008B000002006904FF4801007900020089002203E
|
||||||
:1008C000896821F4806101431B4A916000BF4FF4A5
|
:1008C00009904FF440700A9006A92048FFF732FDC6
|
||||||
:1008D000803002900020039002A91848FFF7C0FC66
|
:1008D00000201E49896821F4806101431B4A916010
|
||||||
:1008E000174A4FF400711448FFF74CFD02221449D7
|
:1008E00000BF4FF4803002900020039002A9184806
|
||||||
:1008F0001148FFF763FD4FF400011048FFF787FD33
|
:1008F000FFF7C6FC174A4FF400711448FFF74CFD90
|
||||||
:10090000104A910D0C48FFF73DFD02220D490A489F
|
:10090000022214491148FFF763FD4FF4000110481B
|
||||||
:10091000FFF754FD4FF400010848FFF778FD0EB0D3
|
:10091000FFF787FD104A910D0C48FFF73DFD0222BD
|
||||||
:10092000BDE8F081443802400064024058180008D5
|
:100920000D490A48FFF754FD4FF400010848FFF74E
|
||||||
:100930000CED00E000E400E0002001400023014055
|
:1009300078FD0EB0BDE8F08144380240006402400A
|
||||||
:1009400010002081110050812DE9F8414FF4800002
|
:10094000AC1800080CED00E000E400E000200140DD
|
||||||
:100950002E49096801432D4A11601146096801407A
|
:100950000023014010002081110050812DE9F84151
|
||||||
:10096000009100BF00BF3821294B1B68C3F3022050
|
:100960004FF480002E49096801432D4A1160114659
|
||||||
:10097000002425460346C3F1070CBCF1040F02D93D
|
:1009700009680140009100BF00BF3821294B1B6866
|
||||||
:100980004FF0040C01E0C3F1070C674603F1040CBF
|
:10098000C3F30220002425460346C3F1070CBCF143
|
||||||
:10099000BCF1070F02D24FF0000C01E0A3F1030CF1
|
:10099000040F02D94FF0040C01E0C3F1070C6746C5
|
||||||
:1009A00066464FF0010C0CFA07FCACF1010C0CEAA6
|
:1009A00003F1040CBCF1070F02D24FF0000C01E080
|
||||||
:1009B000040C0CFA06FC4FF0010808FA06F8A8F13E
|
:1009B000A3F1030C66464FF0010C0CFA07FCACF1F6
|
||||||
:1009C000010808EA05084CEA080200BF002904DB18
|
:1009C000010C0CEA040C0CFA06FC4FF0010808FAC2
|
||||||
:1009D0001007030E0F48435407E01007040E0C489D
|
:1009D00006F8A8F1010808EA05084CEA080200BF79
|
||||||
:1009E0000C3001F00F031B1FC45400BF3820002837
|
:1009E000002904DB1007030E0F48435407E01007EB
|
||||||
:1009F00009DB00F01F02012191404209920002F13F
|
:1009F000040E0C480C3001F00F031B1FC45400BF41
|
||||||
:100A0000E022C2F8001100BFBDE8F8813038024092
|
:100A00003820002809DB00F01F0201219140420933
|
||||||
:100A10000CED00E000E400E000B587B0182101A86B
|
:100A1000920002F1E022C2F8001100BFBDE8F881A7
|
||||||
:100A2000FFF7D7FB1020FFF7FFFC4FF48070FFF7B4
|
:100A2000303802400CED00E000E400E000B587B093
|
||||||
:100A3000FBFC0420FFF7F8FC2020FFF7F5FC8020EA
|
:100A3000182101A8FFF7CDFB1020FFF7FFFC4FF4B2
|
||||||
:100A4000FFF7F2FC0120FFF7EFFC0220FFF7ECFCC0
|
:100A40008070FFF7FBFC0420FFF7F8FC2020FFF785
|
||||||
:100A50004020FFF7E9FC0820FFF7E6FC03203A49B5
|
:100A5000F5FC8020FFF7F2FC0120FFF7EFFC0220FD
|
||||||
:100A6000886100BF4FF6FC700190032002900020C7
|
:100A6000FFF7ECFC4020FFF7E9FC0820FFF7E6FC6D
|
||||||
:100A7000059001A93448FFF7E5FC40F6FF700190AE
|
:100A700003203A49886100BF4FF6FC7001900320C3
|
||||||
:100A8000032002900020059001A93048FFF7DAFC0E
|
:100A800002900020059001A93448FFF7E5FC40F6EC
|
||||||
:100A900043F6FF700190032002900020059001A909
|
:100A9000FF700190032002900020059001A93048CA
|
||||||
:100AA0002B48FFF7CFFC4FF6FF7001900320029018
|
:100AA000FFF7DAFC43F6FF7001900320029000206C
|
||||||
:100AB0000020059001A92748FFF7C4FC49F6FF7004
|
:100AB000059001A92B48FFF7CFFC4FF6FF7001907E
|
||||||
:100AC0000190032002900020059001A92248FFF721
|
:100AC000032002900020059001A92748FFF7C4FCED
|
||||||
:100AD000B9FC4FF6FC7001900320029000200590B5
|
:100AD00049F6FF700190032002900020059001A9C3
|
||||||
:100AE00001A91E48FFF7AEFC4FF6FF7001900320EE
|
:100AE0002248FFF7B9FC4FF6FC70019003200290FA
|
||||||
:100AF00002900020059001A91948FFF7A3FC4FF6CA
|
:100AF0000020059001A91E48FFF7AEFC4FF6FF70DD
|
||||||
:100B0000FF700190032002900020059001A9154874
|
:100B00000190032002900020059001A91948FFF7E9
|
||||||
:100B1000FFF798FC4FF6FF70019003200290002031
|
:100B1000A3FC4FF6FF700190032002900020059087
|
||||||
:100B2000059001A91048FFF78DFC032001900120DA
|
:100B200001A91548FFF798FC4FF6FF7001900320CC
|
||||||
:100B300002900220039000200490059001A9024831
|
:100B300002900020059001A91048FFF78DFC0320CA
|
||||||
:100B4000FFF780FC07B000BD00100240002002400B
|
:100B40000190012002900220039000200490059063
|
||||||
:100B5000000802400014024000000240001C024055
|
:100B500001A90248FFF780FC07B000BD0010024069
|
||||||
:100B60000004024000180240000C02402DE9F04150
|
:100B60000020024000080240001402400000024041
|
||||||
:100B700086B0142101A8FFF72CFB10204149096819
|
:100B7000001C02400004024000180240000C024029
|
||||||
:100B80000143404A1160114609680140009100BFCD
|
:100B80002DE9F04186B0142101A8FFF722FB1020C7
|
||||||
:100B900000BF36213C4B1B68C3F30220062400250E
|
:100B9000414909680143404A116011460968014012
|
||||||
:100BA0000346C3F1070CBCF1040F02D94FF0040C4B
|
:100BA000009100BF00BF36213C4B1B68C3F30220FD
|
||||||
:100BB00001E0C3F1070C674603F1040CBCF1070F19
|
:100BB000062400250346C3F1070CBCF1040F02D93B
|
||||||
:100BC00002D24FF0000C01E0A3F1030C66464FF097
|
:100BC0004FF0040C01E0C3F1070C674603F1040C7D
|
||||||
:100BD000010C0CFA07FCACF1010C0CEA040C0CFA49
|
:100BD000BCF1070F02D24FF0000C01E0A3F1030CAF
|
||||||
:100BE00006FC4FF0010808FA06F8A8F1010808EA27
|
:100BE00066464FF0010C0CFA07FCACF1010C0CEA64
|
||||||
:100BF00005084CEA080200BF002904DB1007030EB9
|
:100BF000040C0CFA06FC4FF0010808FA06F8A8F1FC
|
||||||
:100C00002248435407E01007040E1F480C3001F03F
|
:100C0000010808EA05084CEA080200BF002904DBD5
|
||||||
:100C10000F031B1FC45400BF3620002809DB00F05F
|
:100C10001007030E2248435407E01007040E1F4834
|
||||||
:100C20001F02012191404209920002F1E022C2F824
|
:100C20000C3001F00F031B1FC45400BF36200028F6
|
||||||
:100C3000001100BF44F29F10ADF8040000200290A4
|
:100C300009DB00F01F02012191404209920002F1FC
|
||||||
:100C40006320039001A91248FFF7BEFC00BF1048C3
|
:100C4000E022C2F8001100BF42F2CF00ADF804006C
|
||||||
:100C5000006820F080000E49086000BF002049684D
|
:100C5000002002906320039001A91248FFF7BEFC18
|
||||||
:100C600021F0700101430A4A516000BF00BF1046E5
|
:100C600000BF1048006820F080000E49086000BFF7
|
||||||
:100C7000806820F080001146886000BF06B0BDE8A3
|
:100C70000020496821F0700101430A4A516000BF19
|
||||||
:100C8000F0810000403802400CED00E000E400E09C
|
:100C800000BF1046806820F080001146886000BFD9
|
||||||
:100C90000010004000BFFEE700BFFEE7704770474E
|
:100C900006B0BDE8F0810000403802400CED00E0F5
|
||||||
:100CA0007047000070B505204749096821F0070129
|
:100CA00000E400E00010004000BFFEE700BFFEE7E8
|
||||||
:100CB0000143454A116000BF00BF00BF42480068C1
|
:100CB000704770477047000070B5052047490968C4
|
||||||
:100CC00000F007000528F8D14FF480403F4909683B
|
:100CC00021F007010143454A116000BF00BF00BF8A
|
||||||
:100CD00021F4804101433D4A116000BF00BF3C4800
|
:100CD0004248006800F007000528F8D14FF4804032
|
||||||
:100CE000006840F480303A49086000BF00BF00BF90
|
:100CE0003F49096821F4804101433D4A116000BF3A
|
||||||
:100CF00037480068C0F340400028F8D04FF4800027
|
:100CF00000BF3C48006840F480303A49086000BFBB
|
||||||
:100D00000421A822002340EA010444EA8214304D61
|
:100D000000BF00BF37480068C0F340400028F8D05B
|
||||||
:100D10002D1D2D682F4E35402C432D4D2D1D2C6043
|
:100D10004FF480000421A822002340EA010444EAA1
|
||||||
:100D20002C46246824F440341C432C6000BF00BFD0
|
:100D20008214304D2D1D2D682F4E35402C432D4DF6
|
||||||
:100D3000281F006840F08070291F086000BF00BFB6
|
:100D30002D1D2C602C46246824F440341C432C6068
|
||||||
:100D400000BF23480068C0F340600028F8D000BF0F
|
:100D400000BF00BF281F006840F08070291F0860A6
|
||||||
:100D500000BF1E484068C0F380300028F8D0002053
|
:100D500000BF00BF00BF23480068C0F34060002808
|
||||||
:100D60001B490831096821F0F0010143184A083293
|
:100D6000F8D000BF00BF1E484068C0F380300028A4
|
||||||
:100D7000116000BF4FF4A0501146096821F4E05102
|
:100D7000F8D000201B490831096821F0F001014337
|
||||||
:100D80000143116000BF4FF400401146096821F48F
|
:100D8000184A0832116000BF4FF4A050114609689C
|
||||||
:100D900060410143116000BF02201146096821F043
|
:100D900021F4E0510143116000BF4FF400401146BF
|
||||||
:100DA00003010143116000BF00BF00BF08480830C5
|
:100DA000096821F460410143116000BF022011462F
|
||||||
:100DB000006800F00C000828F7D10748FFF7F0FBA7
|
:100DB000096821F003010143116000BF00BF00BFBB
|
||||||
:100DC0000548FFF7FBFB70BD003C0240007000408F
|
:100DC00008480830006800F00C000828F7D10748F0
|
||||||
:100DD000003802400080BFFF007A030A0348006821
|
:100DD000FFF7F0FB0548FFF7FBFB70BD003C02404E
|
||||||
:100DE00040F47000014908607047000088ED00E0A1
|
:100DE00000700040003802400080BFFF007A030A14
|
||||||
:100DF00010B53748FFF75AFC012868D100BF00BF83
|
:100DF0000348006840F47000014908607047000033
|
||||||
:100E000033480069C0F3400060B100BF3048C0689B
|
:100E000088ED00E010B53748FFF75AFC012868D19B
|
||||||
:100E1000C0F3400030B100BF6FF002002C49086100
|
:100E100000BF00BF33480069C0F3400060B100BFAD
|
||||||
:100E200000BF00BF00BF2A480069C0F3800060B166
|
:100E20003048C068C0F3400030B100BF6FF002002E
|
||||||
:100E300000BF2748C068C0F3800030B100BF6FF02A
|
:100E30002C49086100BF00BF00BF2A480069C0F309
|
||||||
:100E400004002349086100BF00BF00BF20480069BB
|
:100E4000800060B100BF2748C068C0F3800030B1A7
|
||||||
:100E5000C0F3C00060B100BF1D48C068C0F3C0004F
|
:100E500000BF6FF004002349086100BF00BF00BF5E
|
||||||
:100E600030B100BF6FF008001949086100BF00BF32
|
:100E600020480069C0F3C00060B100BF1D48C068E1
|
||||||
:100E700000BF17480069C0F3001060B100BF1448FC
|
:100E7000C0F3C00030B100BF6FF00800194908612D
|
||||||
:100E8000C068C0F3001030B100BF6FF0100010490F
|
:100E800000BF00BF00BF17480069C0F3001060B189
|
||||||
:100E9000086100BF00BF0E48FFF708FC01280CD115
|
:100E900000BF1448C068C0F3001030B100BF6FF04D
|
||||||
:100EA00000BF0B48C06800F0010030B100BF6FF018
|
:100EA00010001049086100BF00BF0E48FFF708FCA2
|
||||||
:100EB00001000749086100BF00BF00BFFFF768FBE2
|
:100EB00001280CD100BF0B48C06800F0010030B120
|
||||||
:100EC00000BF04480068401C0249086000BF10BD14
|
:100EC00000BF6FF001000749086100BF00BF00BF0D
|
||||||
:100ED000001000404400002000BFFEE702E008C808
|
:100ED000FFF768FB00BF04480068401C0249086037
|
||||||
:100EE000121F08C1002AFAD170477047002001E0A4
|
:100EE00000BF10BD001000405800002000BFFEE70A
|
||||||
:100EF00001C1121F002AFBD170470000014601F119
|
:100EF00002E008C8121F08C1002AFAD170477047E3
|
||||||
:100F0000100000E0001D02681AB9024A12689042FF
|
:100F0000002001E001C1121F002AFBD17047000040
|
||||||
:100F1000F8D370472400002010B50648046803E0A9
|
:100F1000014601F1100000E0001D02681AB9024A02
|
||||||
:100F20002046FFF7EBFF0446034800688442F7D3EE
|
:100F200012689042F8D370473800002010B5064888
|
||||||
:100F300010BD0000200000202400002010B501E0BA
|
:100F3000046803E02046FFF7EBFF0446034800681F
|
||||||
:100F400000F8011B131EA2F10104A2B2F8D110BDDA
|
:100F40008442F7D310BD0000340000203800002098
|
||||||
:100F500070B5054605EBC500124901EB80040CB1E4
|
:100F500010B501E000F8011B131EA2F10104A2B2BA
|
||||||
:100F6000012100E00021084640F22911FFF756F95F
|
:100F6000F8D110BD70B5054605EBC500114901EB80
|
||||||
:100F700060680168C1F3C02139B160684FF4006155
|
:100F700080040CB1012100E00021084640F2291153
|
||||||
:100F8000816000BF2068FFF7A3F960680168C1F3C2
|
:100F8000FFF768F960680168C1F3C02129B16068A2
|
||||||
:100F9000402129B160684FF40071816000BF00BF3B
|
:100F90004FF40061816000BF00BF60680168C1F369
|
||||||
:100FA00070BD00008018002070B5054605EBC50037
|
:100FA000402129B160684FF40071816000BF00BF2B
|
||||||
:100FB0000D4901EB80040CB1012100E0002108463D
|
:100FB00070BD000080E1002070B5054605EBC5005E
|
||||||
:100FC0004FF4A071FFF72AF920680168C1F34011BE
|
:100FC0000D4901EB80040CB1012100E0002108462D
|
||||||
:100FD00041B16069401C606120686FF020010160D0
|
:100FD0004FF49F71FFF73EF920680168C1F340119B
|
||||||
:100FE00000BF00BF70BD0000801800200146002037
|
:100FE00041B16069401C606120686FF020010160C0
|
||||||
:100FF00001F001020AB1421CD0B201F002020AB1B2
|
:100FF00000BF00BF70BD000080E10020014600205E
|
||||||
:10100000421CD0B201F004020AB1421CD0B201F07D
|
:1010000001F001020AB1421CD0B201F002020AB1A1
|
||||||
:1010100008020AB1421CD0B201F010020AB1421C0F
|
:10101000421CD0B201F004020AB1421CD0B201F06D
|
||||||
:10102000D0B201F020020AB1421CD0B201F040025D
|
:1010200008020AB1421CD0B201F010020AB1421CFF
|
||||||
:101030000AB1421CD0B201F080020AB1421CD0B207
|
:10103000D0B201F020020AB1421CD0B201F040024D
|
||||||
:1010400001F480720AB1421CD0B201F400720AB1FC
|
:101040000AB1421CD0B201F080020AB1421CD0B2F7
|
||||||
:10105000421CD0B201F480620AB1421CD0B201F449
|
:1010500001F480720AB1421CD0B201F400720AB1EC
|
||||||
:1010600000620AB1421CD0B201F480520AB1421CA3
|
:10106000421CD0B201F480620AB1421CD0B201F439
|
||||||
:10107000D0B201F400520AB1421CD0B201F4804255
|
:1010700000620AB1421CD0B201F480520AB1421C93
|
||||||
:101080000AB1421CD0B201F400420AB1421CD0B2F3
|
:10108000D0B201F400520AB1421CD0B201F4804245
|
||||||
:1010900001F480320AB1421CD0B201F400220AB13C
|
:101090000AB1421CD0B201F400420AB1421CD0B2E3
|
||||||
:1010A000421CD0B201F480220AB1421CD0B201F439
|
:1010A00001F480320AB1421CD0B201F400220AB12C
|
||||||
:1010B00000320AB1421CD0B2704700002DE9FF4F48
|
:1010B000421CD0B201F480220AB1421CD0B201F429
|
||||||
:1010C00081B006460F469046DDE90F95032E01DA02
|
:1010C00000320AB1421CD0B2704700002DE9FF4F38
|
||||||
:1010D000012100E0002108461C21FFF79FF80FB115
|
:1010D00081B006460F469046DDE90F95032E01DAF2
|
||||||
:1010E000012100E0002108461D21FFF797F8B8F123
|
:1010E000012100E0002108461C21FFF7B3F80FB1F1
|
||||||
:1010F000000F01D0012100E0002108461E21FFF76A
|
:1010F000012100E0002108461D21FFF7ABF8B8F1FF
|
||||||
:101100008DF8B9F1000F01DD012100E00021084652
|
:10110000000F01D0012100E0002108461E21FFF759
|
||||||
:101110001F21FFF783F806EBC600744901EB80043A
|
:10111000A1F8B9F1000F01DD012100E0002108462E
|
||||||
:10112000242200212046FFF709FF2760C4F804802D
|
:101120001F21FFF797F806EBC600744901EB800416
|
||||||
:101130000498A0600E98E0602561A4F818902846F5
|
:10113000242200212046FFF70BFF2760C4F804801B
|
||||||
:10114000FFF754FFA076A07E00FB09F0A083A08BE0
|
:101140000498A0600E98E0602561A4F818902846E5
|
||||||
:101150004FEA400A5146012000F060FB2062216AFC
|
:10115000FFF754FFA076A07E00FB09F0A083A08BD0
|
||||||
:1011600009B1012100E0002108463221FFF756F8BD
|
:101160004FEA400A5146012000F060FB2062216AEC
|
||||||
:10117000A18B49040A0C0021206AFFF7DFFE201D25
|
:1011700009B1012100E0002108463221FFF76AF899
|
||||||
:1011800007C85B4B5B5CC35823F060631343DFF815
|
:10118000A18B49040A0C0021206AFFF7E1FE201D13
|
||||||
:1011900060C11CF801C040F80C3000BF554AD4E9CA
|
:1011900007C85B4B5B5CC35823F060631343DFF805
|
||||||
:1011A0000101534B5B5CC358DFF84CC103EA0C03ED
|
:1011A00060C11CF801C040F80C3000BF554AD4E9BA
|
||||||
:1011B0001343DFF83CC11CF801C040F80C3000BFFD
|
:1011B0000101534B5B5CC358DFF84CC103EA0C03DD
|
||||||
:1011C0004FF0000BD4E900A0A1684FF0000ECDF85D
|
:1011C0001343DFF83CC11CF801C040F80C3000BFED
|
||||||
:1011D00000E0BBF1000F04D10AF14C0ECDF800E0A5
|
:1011D0004FF0000BD4E900A0A1684FF0000ECDF84D
|
||||||
:1011E00003E0DFF818E1CDF800E0009AD4E901ABA4
|
:1011E00000E0BBF1000F04D10AF14C0ECDF800E095
|
||||||
:1011F000236ADFF8FCE01EF80BE05AF80EE00EF070
|
:1011F00003E0DFF818E1CDF800E0009AD4E901AB94
|
||||||
:10120000C00C00BFBCF1400F0ED1DFF8E4A01AF80B
|
:10120000236ADFF8FCE01EF80BE05AF80EE00EF05F
|
||||||
:1012100001A08244CAF80C20DFF8D4A01AF801A07B
|
:10121000C00C00BFBCF1400F0ED1DFF8E4A01AF8FB
|
||||||
:101220008244CAF808300DE0DFF8C4A01AF801A023
|
:1012200001A08244CAF80C20DFF8D4A01AF801A06B
|
||||||
:101230008244CAF80820DFF8B8A01AF801A0824456
|
:101230008244CAF808300DE0DFF8C4A01AF801A013
|
||||||
:10124000CAF80C3000BFA28BD4E90101284B5B5CCB
|
:101240008244CAF80820DFF8B8A01AF801A0824446
|
||||||
:1012500003445B686FF30F031343DFF894C01CF87B
|
:10125000CAF80C3000BFA28BD4E90101284B5B5CBB
|
||||||
:1012600001C08444CCF8043000BFD4E90101204A15
|
:1012600003445B686FF30F031343DFF894C01CF86B
|
||||||
:10127000525C825842F001021D4B5B5CC25000BFC1
|
:1012700001C08444CCF8043000BFD4E90101204A05
|
||||||
:1012800002212068826822F002020A43826000BFC5
|
:10128000525C825842F001021D4B5B5CC25000BFB1
|
||||||
:101290004FF440712068826822F440720A438260F1
|
:1012900002212068826822F002020A43826000BFB5
|
||||||
:1012A00000BF05F4002028B14FF4000113480838AE
|
:1012A0004FF440712068826822F440720A438260E1
|
||||||
:1012B000FFF7B3F805F4003028B14FF400010F48F0
|
:1012B00000BF05F4002028B14FF40001134808389E
|
||||||
:1012C0000838FFF7AAF80A20FFF7F5F920688168C7
|
:1012C000FFF7B5F805F4003028B14FF400010F48DE
|
||||||
:1012D00041F00101816000BF2068816841F08041D8
|
:1012D0000838FFF7ACF80A20FFF7F7F920688168B3
|
||||||
:1012E000816000BF05B0BDE8F08F000080180020CD
|
:1012E00041F00101816000BF2068816841F08041C8
|
||||||
:1012F000B4180008002D02001F80FCFF08230140E5
|
:1012F000816000BF05B0BDE8F08F000080E10020F4
|
||||||
:101300002DE9F04705468846032D01DA012100E06A
|
:1013000008190008002D02001F80FCFF082301407F
|
||||||
:1013100000210846EE21FEF781FF4FF0000900266C
|
:101310002DE9F04705468846032D01DA012100E05A
|
||||||
:1013200005EBC500104901EB80040CB1012100E080
|
:1013200000210846EE21FEF795FF4FF00009002648
|
||||||
:1013300000210846F221FEF771FF206A00EB480702
|
:1013300005EBC500104901EB80040CB1012100E070
|
||||||
:10134000002006E039880E44411C88B2A17E07EBDC
|
:1013400000210846F221FEF785FF206A00EB4807DE
|
||||||
:101350004107218B8142F5DC208BB6FBF0F01FFAB0
|
:10135000002006E039880E44411C88B2A17E07EBCC
|
||||||
:1013600080F94846BDE8F087801800200C4B1988AA
|
:101360004107218B8142F5DC208BB6FBF0F01FFAA0
|
||||||
:101370009B1C1A88431A00EE903AF8EEE01A531AB2
|
:1013700080F94846BDE8F08780E100200C4B1988D1
|
||||||
:1013800000EE903AF8EEE00A81EEA01ADFED051AC1
|
:101380009B1C1A88431A00EE903AF8EEE01A531AA2
|
||||||
:10139000F3EE0E0A41EE210AB0EE600A704700003B
|
:1013900000EE903AF8EEE00A81EEA01ADFED051AB1
|
||||||
:1013A0002C7AFF1F0000A0420E49098840F6E44253
|
:1013A000F3EE0E0A41EE210AB0EE600A704700002B
|
||||||
:1013B000514340F6FF72B1FBF2F100EE101AB8EEA5
|
:1013B0002C7AFF1F0000A0420E49098840F6E44243
|
||||||
:1013C000400AF0EE400A00EE100AB8EE400A80EE45
|
:1013C000514340F6FF72B1FBF2F100EE101AB8EE95
|
||||||
:1013D000801A9FED050A21EE001ADFED041A81EE56
|
:1013D000400AF0EE400A00EE100AB8EE400A80EE35
|
||||||
:1013E000210A70472A7AFF1F00F07F4500007A44E7
|
:1013E000801A9FED050A21EE001ADFED041A81EE46
|
||||||
:1013F00000200B4908600B49086000BF00BF0A4885
|
:1013F000210A70472A7AFF1F00F07F4500007A44D7
|
||||||
:10140000006840F001000849086000BF00BF0846BE
|
:1014000000200B4908600B49086000BF00BF0A4874
|
||||||
:10141000C06840F00100C86000BF00BF7047000016
|
:10141000006840F001000849086000BF00BF0846AE
|
||||||
:1014200008000020100000200010004010B5034804
|
:10142000C06840F00100C86000BF00BF7047000006
|
||||||
:1014300000F01CF8024800F087F810BD08000020FA
|
:1014300008000020100000200010004010B50348F4
|
||||||
:10144000100000200EB54FF420204FF4C871002288
|
:1014400000F01CF8024800F087F810BD08000020EA
|
||||||
:101450001346CDE900210290024A03490020FFF71C
|
:10145000100000200EB54FF420204FF4C871002278
|
||||||
:101460002DFE0EBD006402400020014038B5044648
|
:101460001346CDE900210290024A03490020FFF70C
|
||||||
:1014700000200090206810B112281DD112E000BF9A
|
:101470002DFE0EBD006402400020014038B5044638
|
||||||
:1014800000F02AF80F4880ED000A00F041F80D48FE
|
:1014800000200090206810B112281DD112E000BF8A
|
||||||
:1014900080ED010A00BF0C480068606000BF1220A8
|
:1014900000F02AF80F4880ED000A00F041F80D48EE
|
||||||
:1014A000206000BF084960680968081A642801D2F2
|
:1014A00080ED010A00BF0C480068606000BF122098
|
||||||
:1014B000002038BD00BFE3E700202060009003203B
|
:1014B000206000BF084960680968081A642801D2E2
|
||||||
:1014C000F7E70000180000204400002001490860F0
|
:1014C000002038BD00BFE3E700202060009003202B
|
||||||
:1014D000704700004800002010B52DED028B9FEDF5
|
:1014D000F7E70000180000205800002001490860CC
|
||||||
:1014E0000A0AB0EE408A00210846FFF709FF0749C3
|
:1014E000704700002000002010B52DED028B9FED0D
|
||||||
:1014F00008800888FFF73AFFB0EE408AB0EE480A4D
|
:1014F0000A0AB0EE408A00210846FFF709FF0749B3
|
||||||
:10150000BDEC028B10BD00000000000004000020B4
|
:1015000008800888FFF73AFFB0EE408AB0EE480A3C
|
||||||
:1015100010B52DED028B9FED0A0AB0EE408A012135
|
:10151000BDEC028B10BD00000000000004000020A4
|
||||||
:101520000020FFF7EDFE074948804888FFF73CFFA1
|
:1015200010B52DED028B9FED0A0AB0EE408A012125
|
||||||
:10153000B0EE408AB0EE480ABDEC028B10BD000050
|
:101530000020FFF7EDFE074948804888FFF73CFF91
|
||||||
:10154000000000000400002038B504460020009090
|
:10154000B0EE408AB0EE480ABDEC028B10BD000040
|
||||||
:10155000206810B1252816D10BE000BF012000F053
|
:10155000000000000400002038B504460020009080
|
||||||
:1015600019F800BF0A480068606000BF25202060AD
|
:10156000206810B1252816D10BE000BF012000F043
|
||||||
:1015700000BF074960680968081A642801D2002082
|
:1015700019F800BF0A480068606000BF252020609D
|
||||||
:1015800038BD00BFEAE70020206000900320F7E7A5
|
:1015800000BF074960680968081A642801D2002072
|
||||||
:101590004400002010B5044614B1012C0AD104E027
|
:1015900038BD00BFEAE70020206000900320F7E795
|
||||||
:1015A00001210648FEF7EAFF05E002210348FEF7A5
|
:1015A0005800002010B5044614B1012C0AD104E003
|
||||||
:1015B000E5FF00E000BF00BF10BD000000100240CA
|
:1015B00001210648FEF7ECFF05E002210348FEF793
|
||||||
:1015C00008B54FF48040444909680143424A11601C
|
:1015C000E7FF00E000BF00BF10BD000000100240B8
|
||||||
:1015D000114609680140009100BF00BF8003111F40
|
:1015D00008B54FF48040444909680143424A11600C
|
||||||
:1015E00009680143121F116011460968014000910A
|
:1015E000114609680140009100BF00BF8003111F30
|
||||||
:1015F00000BF00BF03200246384B19684FF6FF03B7
|
:1015F00009680143121F11601146096801400091FA
|
||||||
:101600001940374B0B4343EA0221344B196000BFAA
|
:1016000000BF00BF03200246384B19684FF6FF03A6
|
||||||
:10161000011F1B68C3F302200F2400250346C3F1FA
|
:101610001940374B0B4343EA0221344B196000BF9A
|
||||||
:10162000070CBCF1040F02D94FF0040C01E0C3F128
|
:10162000011F1B68C3F302200F2400250346C3F1EA
|
||||||
:10163000070C674603F1040CBCF1070F02D24FF010
|
:10163000070CBCF1040F02D94FF0040C01E0C3F118
|
||||||
:10164000000C01E0A3F1030C66464FF0010C0CFA0C
|
:10164000070C674603F1040CBCF1070F02D24FF000
|
||||||
:1016500007FCACF1010C0CEA040C0CFA06FC4FF090
|
:10165000000C01E0A3F1030C66464FF0010C0CFAFC
|
||||||
:10166000010808FA06F8A8F1010808EA05084CEA9A
|
:1016600007FCACF1010C0CEA040C0CFA06FC4FF080
|
||||||
:10167000080200BF002904DB1007030E1948435479
|
:10167000010808FA06F8A8F1010808EA05084CEA8A
|
||||||
:1016800007E01007040E15480C3001F00F031B1F74
|
:10168000080200BF002904DB1007030E1948435469
|
||||||
:10169000C45400BFFFF706FB134800681349B0FBB2
|
:1016900007E01007040E15480C3001F00F031B1F64
|
||||||
:1016A000F1F084B22046FFF711FFFFF7B5F9FFF71D
|
:1016A000C45400BFFFF708FB134800681349B0FBA0
|
||||||
:1016B0004BF9FFF75BFAFFF713F8002000F018F87A
|
:1016B000F1F084B22046FFF711FFFFF7B7F9FFF70B
|
||||||
:1016C000012000F015F8FFF7BDFEFFF791FE01E0E5
|
:1016C0004DF9FFF75DFAFFF715F8002000F018F864
|
||||||
:1016D000FFF7ACFEFCE70000443802400CED00E0F0
|
:1016D000012000F015F8FFF7BDFEFFF791FE01E0D5
|
||||||
:1016E0000000FA0500E400E00000002040420F0086
|
:1016E000FFF7ACFEFCE70000443802400CED00E0E0
|
||||||
:1016F00010B504460C4951F824104A000B4951F822
|
:1016F0000000FA0500E400E00000002040420F0076
|
||||||
:101700002400002100F09EF8094951F824200749DF
|
:1017000010B504460C4951F824104A000B4951F811
|
||||||
:10171000083951F82400002100F094F80121034811
|
:101710002400002100F09EF8094951F824200749CF
|
||||||
:101720000830015510BD00009C180008380000204A
|
:10172000083951F82400002100F094F80121034801
|
||||||
:10173000AC1800082DE9F04704460F460025A946DD
|
:101730000830015510BD0000F01800084C000020D2
|
||||||
:101740002348005D20B922481838016820468847A0
|
:10174000001900082DE9F04704460F460025A94678
|
||||||
:101750001FB94FF0FF30BDE8F0871E4850F8240055
|
:101750002348005D20B92248183801682046884790
|
||||||
:10176000B7FBF0F61B4850F82400B7FBF0F100FB84
|
:101760001FB94FF0FF30BDE8F0871E4850F8240045
|
||||||
:10177000117000B1761C184850F82400451E22E074
|
:10177000B7FBF0F61B4850F82400B7FBF0F100FB74
|
||||||
:101780001348083850F8240030F8150010B909F152
|
:10178000117000B1761C184850F82400451E22E064
|
||||||
:10179000010901E04FF00009B14513D14FF00008F5
|
:101790001348083850F8240030F8150010B909F142
|
||||||
:1017A00009E00B48083850F8240005EB080220F83F
|
:1017A000010901E04FF00009B14513D14FF00008E5
|
||||||
:1017B000126008F10108B045F3D3064850F8240040
|
:1017B00009E00B48083850F8240005EB080220F82F
|
||||||
:1017C0006843C8E76D1E002DDADA4FF0FF30C2E73C
|
:1017C000126008F10108B045F3D3064850F8240030
|
||||||
:1017D00040000020A41800089C18000810B501461D
|
:1017D0006843C8E76D1E002DDADA4FF0FF30C2E72C
|
||||||
:1017E0000023002207E00B4850F8210030F81200D7
|
:1017E00054000020F8180008F018000810B5014651
|
||||||
:1017F00000B15B1C521C084850F821009042F2D8FE
|
:1017F0000023002207E00B4850F8210030F81200C7
|
||||||
:1018000064205843044C54F82140B0FBF4F0C0B2BB
|
:1018000000B15B1C521C084850F821009042F2D8ED
|
||||||
:1018100010BD0000380000209C18000870B5044678
|
:1018100064205843044C54F82140B0FBF4F0C0B2AB
|
||||||
:101820000E4631462046FFF785FF0546681C08B97D
|
:1018200010BD00004C000020F018000870B5044600
|
||||||
:10183000002070BD024850F824002844F9E7000059
|
:101830000E4631462046FFF785FF0546681C08B96D
|
||||||
:101840003000002030B5034601E003F8011B141EF0
|
:10184000002070BD024850F824002844F9E7000049
|
||||||
:10185000A2F10102F9D130BD102840587088A0B81B
|
:101850004400002030B5034601E003F8011B141ECC
|
||||||
:10186000000000000404040000080000000800005C
|
:10186000A2F10102F9D130BD00BF00BF00BF00BF2F
|
||||||
:10187000080000000800020406080A0C0001020328
|
:1018700000BFBFF34F8F00BF00BF00BF0948006823
|
||||||
:101880000405065F6C697374006C69737420616C85
|
:1018800000F4E06008490843001D0649086000BFF5
|
||||||
:101890006C20636F6D6D616E6400000000020000DB
|
:1018900000BF00BFBFF34F8F00BF00BF00BF00BF3E
|
||||||
:1018A0000002000008000000080000000010000016
|
:1018A00000BFFDE70CED00E00000FA0510284058ED
|
||||||
:1018B00000100000102840587088A0B800000000F8
|
:1018B0007088A0B8000000000404040000080000C4
|
||||||
:1018C00004040400000800000008000008000000F4
|
:1018C00000080000080000000800020406080A0CD6
|
||||||
:1018D0000800020406080A0C0001020304050600C1
|
:1018D000000102030405065F6C697374006C697390
|
||||||
:1018E00010190008000000206C000000DC0E000849
|
:1018E0007420616C6C20636F6D6D616E640000002C
|
||||||
:1018F0007C1900086C000020841C0000EC0E00081D
|
:1018F000800C0000000A0000080000000800000042
|
||||||
:101900007C19000800C0012000100000EC0E000847
|
:101900000064000000500000102840587088A0B803
|
||||||
:101910000024F400000000000000000000000000AF
|
:1019100000000000040404000008000000080000AB
|
||||||
:1019200000000000000000000000000000000000B7
|
:10192000080000000800020406080A0C0001020377
|
||||||
:101930000000000000000000F1160008DD1700089C
|
:101930000405060054190008000000207050000043
|
||||||
:101940008000002000C001208010002080140020B2
|
:101940000C020008241A0008705000208095000046
|
||||||
:101950000000000000000000000000000000000087
|
:10195000000F0008043A0024F43E01170008ED17B8
|
||||||
:1019600000000000000000000000000083180008D4
|
:10196000000880500020600AFF2080B4002080CD55
|
||||||
:0C19700089180008C6E533B4190F000800
|
:10197000002001FF01FF01FF01FF01FF01FF01FF47
|
||||||
|
:1019800001FF01FF01FF01FF01FF01FF01FF01FF57
|
||||||
|
:1019900001FF01FF01FF01FF01FF01FF01FF01FF47
|
||||||
|
:1019A00001FF01FF01FF01FF01FF01FF01FF01FF37
|
||||||
|
:1019B00001FF01FF01FF01FF01FF01FF01FF01FF27
|
||||||
|
:1019C00001FF01FF01FF01FF01FF01FF01FF01FF17
|
||||||
|
:1019D00001FF01FF01FF01FF01FF01FF01FF01FF07
|
||||||
|
:1019E00001FF01FF01FF01FF01FF01FF01FF01FFF7
|
||||||
|
:1019F00001FF01FF01FF01FF01FF01FF01FF01FFE7
|
||||||
|
:101A000001FF01FF01FF01FF01FF01FF01FF01FFD6
|
||||||
|
:101A100001AD2FD7180008DD180008C6E533B42D36
|
||||||
|
:041A20000F12080099
|
||||||
:040000050800018965
|
:040000050800018965
|
||||||
:00000001FF
|
:00000001FF
|
||||||
|
|
Binary file not shown.
Binary file not shown.
|
@ -68,8 +68,8 @@
|
||||||
/* Cortex-M4 Processor Interruption and Exception Handlers */
|
/* Cortex-M4 Processor Interruption and Exception Handlers */
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
/**
|
/**
|
||||||
* @brief This function handles Non maskable interrupt.
|
* @brief This function handles Non maskable interrupt.
|
||||||
*/
|
*/
|
||||||
void NMI_Handler(void)
|
void NMI_Handler(void)
|
||||||
{
|
{
|
||||||
/* USER CODE BEGIN NonMaskableInt_IRQn 0 */
|
/* USER CODE BEGIN NonMaskableInt_IRQn 0 */
|
||||||
|
@ -83,8 +83,8 @@ void NMI_Handler(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This function handles Hard fault interrupt.
|
* @brief This function handles Hard fault interrupt.
|
||||||
*/
|
*/
|
||||||
void HardFault_Handler(void)
|
void HardFault_Handler(void)
|
||||||
{
|
{
|
||||||
/* USER CODE BEGIN HardFault_IRQn 0 */
|
/* USER CODE BEGIN HardFault_IRQn 0 */
|
||||||
|
@ -98,8 +98,8 @@ void HardFault_Handler(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This function handles Memory management fault.
|
* @brief This function handles Memory management fault.
|
||||||
*/
|
*/
|
||||||
void MemManage_Handler(void)
|
void MemManage_Handler(void)
|
||||||
{
|
{
|
||||||
/* USER CODE BEGIN MemoryManagement_IRQn 0 */
|
/* USER CODE BEGIN MemoryManagement_IRQn 0 */
|
||||||
|
@ -113,8 +113,8 @@ void MemManage_Handler(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This function handles Pre-fetch fault, memory access fault.
|
* @brief This function handles Pre-fetch fault, memory access fault.
|
||||||
*/
|
*/
|
||||||
void BusFault_Handler(void)
|
void BusFault_Handler(void)
|
||||||
{
|
{
|
||||||
/* USER CODE BEGIN BusFault_IRQn 0 */
|
/* USER CODE BEGIN BusFault_IRQn 0 */
|
||||||
|
@ -128,8 +128,8 @@ void BusFault_Handler(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This function handles Undefined instruction or illegal state.
|
* @brief This function handles Undefined instruction or illegal state.
|
||||||
*/
|
*/
|
||||||
void UsageFault_Handler(void)
|
void UsageFault_Handler(void)
|
||||||
{
|
{
|
||||||
/* USER CODE BEGIN UsageFault_IRQn 0 */
|
/* USER CODE BEGIN UsageFault_IRQn 0 */
|
||||||
|
@ -143,8 +143,8 @@ void UsageFault_Handler(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This function handles System service call via SWI instruction.
|
* @brief This function handles System service call via SWI instruction.
|
||||||
*/
|
*/
|
||||||
void SVC_Handler(void)
|
void SVC_Handler(void)
|
||||||
{
|
{
|
||||||
/* USER CODE BEGIN SVCall_IRQn 0 */
|
/* USER CODE BEGIN SVCall_IRQn 0 */
|
||||||
|
@ -156,8 +156,8 @@ void SVC_Handler(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This function handles Debug monitor.
|
* @brief This function handles Debug monitor.
|
||||||
*/
|
*/
|
||||||
void DebugMon_Handler(void)
|
void DebugMon_Handler(void)
|
||||||
{
|
{
|
||||||
/* USER CODE BEGIN DebugMonitor_IRQn 0 */
|
/* USER CODE BEGIN DebugMonitor_IRQn 0 */
|
||||||
|
@ -169,8 +169,8 @@ void DebugMon_Handler(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This function handles Pendable request for system service.
|
* @brief This function handles Pendable request for system service.
|
||||||
*/
|
*/
|
||||||
void PendSV_Handler(void)
|
void PendSV_Handler(void)
|
||||||
{
|
{
|
||||||
/* USER CODE BEGIN PendSV_IRQn 0 */
|
/* USER CODE BEGIN PendSV_IRQn 0 */
|
||||||
|
@ -182,8 +182,8 @@ void PendSV_Handler(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This function handles System tick timer.
|
* @brief This function handles System tick timer.
|
||||||
*/
|
*/
|
||||||
void SysTick_Handler(void)
|
void SysTick_Handler(void)
|
||||||
{
|
{
|
||||||
/* USER CODE BEGIN SysTick_IRQn 0 */
|
/* USER CODE BEGIN SysTick_IRQn 0 */
|
||||||
|
@ -203,8 +203,8 @@ void SysTick_Handler(void)
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This function handles ADC1, ADC2 and ADC3 global interrupts.
|
* @brief This function handles ADC1, ADC2 and ADC3 global interrupts.
|
||||||
*/
|
*/
|
||||||
void ADC_IRQHandler(void)
|
void ADC_IRQHandler(void)
|
||||||
{
|
{
|
||||||
/* USER CODE BEGIN ADC_IRQn 0 */
|
/* USER CODE BEGIN ADC_IRQn 0 */
|
||||||
|
@ -217,8 +217,8 @@ void ADC_IRQHandler(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This function handles TIM6 global interrupt, DAC1 and DAC2 underrun error interrupts.
|
* @brief This function handles TIM6 global interrupt, DAC1 and DAC2 underrun error interrupts.
|
||||||
*/
|
*/
|
||||||
void TIM6_DAC_IRQHandler(void)
|
void TIM6_DAC_IRQHandler(void)
|
||||||
{
|
{
|
||||||
/* USER CODE BEGIN TIM6_DAC_IRQn 0 */
|
/* USER CODE BEGIN TIM6_DAC_IRQn 0 */
|
||||||
|
@ -236,8 +236,8 @@ void TIM6_DAC_IRQHandler(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This function handles DMA2 stream0 global interrupt.
|
* @brief This function handles DMA2 stream0 global interrupt.
|
||||||
*/
|
*/
|
||||||
void DMA2_Stream0_IRQHandler(void)
|
void DMA2_Stream0_IRQHandler(void)
|
||||||
{
|
{
|
||||||
/* USER CODE BEGIN DMA2_Stream0_IRQn 0 */
|
/* USER CODE BEGIN DMA2_Stream0_IRQn 0 */
|
||||||
|
|
|
@ -44,7 +44,7 @@ void MX_TIM6_Init(void)
|
||||||
/* USER CODE BEGIN TIM6_Init 1 */
|
/* USER CODE BEGIN TIM6_Init 1 */
|
||||||
|
|
||||||
/* USER CODE END TIM6_Init 1 */
|
/* USER CODE END TIM6_Init 1 */
|
||||||
TIM_InitStruct.Prescaler = 16799;
|
TIM_InitStruct.Prescaler = 8399;
|
||||||
TIM_InitStruct.CounterMode = LL_TIM_COUNTERMODE_UP;
|
TIM_InitStruct.CounterMode = LL_TIM_COUNTERMODE_UP;
|
||||||
TIM_InitStruct.Autoreload = 99;
|
TIM_InitStruct.Autoreload = 99;
|
||||||
LL_TIM_Init(TIM6, &TIM_InitStruct);
|
LL_TIM_Init(TIM6, &TIM_InitStruct);
|
||||||
|
|
|
@ -1,30 +0,0 @@
|
||||||
#ifndef __S_CURVE_H
|
|
||||||
#define __S_CURVE_H
|
|
||||||
#include "lib.h"
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
// 起始频率
|
|
||||||
float32 f0;
|
|
||||||
// 加加速段斜率
|
|
||||||
float32 faa;
|
|
||||||
// 减减速段斜率
|
|
||||||
float32 frr;
|
|
||||||
// 加加速段时间
|
|
||||||
float32 taa;
|
|
||||||
// 匀加速段时间
|
|
||||||
float32 tua;
|
|
||||||
// 减加速段时间
|
|
||||||
float32 tra;
|
|
||||||
// 匀速段时间
|
|
||||||
float32 tuu;
|
|
||||||
// 加减速段时间
|
|
||||||
float32 tar;
|
|
||||||
// 匀减速段时间
|
|
||||||
float32 tur;
|
|
||||||
// 减减速段时间
|
|
||||||
float32 trr;
|
|
||||||
} s_curve_t;
|
|
||||||
|
|
||||||
void s_curve_table_gen(uint16_t tmin, uint16_t tmax);
|
|
||||||
#endif // __S_CURVE_H
|
|
|
@ -1,171 +0,0 @@
|
||||||
#include "s_curve.h"
|
|
||||||
|
|
||||||
// s曲线加速度各段参数定义
|
|
||||||
// 起始速度
|
|
||||||
#define F0 0.0f
|
|
||||||
|
|
||||||
// 加加速度与减减速度
|
|
||||||
#define FAA 0.0f
|
|
||||||
#define FRR 0.0f
|
|
||||||
|
|
||||||
// 加速段三个时间
|
|
||||||
#define TAA 0.1f
|
|
||||||
#define TUA 0.2f
|
|
||||||
#define TRA 0.1f
|
|
||||||
|
|
||||||
// 匀速段
|
|
||||||
#define TUU 5.0f
|
|
||||||
|
|
||||||
// 减速段
|
|
||||||
#define TAR 0.1f
|
|
||||||
#define TUR 0.2f
|
|
||||||
#define TRR 0.1f
|
|
||||||
|
|
||||||
// 表格长度
|
|
||||||
#define S_CURVE_TABLE_LEN 400
|
|
||||||
int16_t s_curve_table[S_CURVE_TABLE_LEN] = {0};
|
|
||||||
|
|
||||||
static int16_t s_curve_func(s_curve_t *s, float32 t, float32 *freq, float32 *acc)
|
|
||||||
{
|
|
||||||
// 辅助常数项
|
|
||||||
float32 A, B, C, D, E, F;
|
|
||||||
// 表达式中间值
|
|
||||||
float32 f3, f4, f5;
|
|
||||||
// 加速段,匀速段,减速段时间
|
|
||||||
float32 Ta, Tu, Tr;
|
|
||||||
// 减加速与加减速段斜率
|
|
||||||
float32 fra, far;
|
|
||||||
// 起始频率与加加速频率,减减速频率
|
|
||||||
float32 f0, faa, frr;
|
|
||||||
float32 taa, tua, tra, tuu, tar, tur, trr;
|
|
||||||
|
|
||||||
// 获取参数
|
|
||||||
faa = s->faa;
|
|
||||||
frr = s->frr;
|
|
||||||
|
|
||||||
taa = s->taa;
|
|
||||||
tua = s->tua;
|
|
||||||
tra = s->tra;
|
|
||||||
tuu = s->tuu;
|
|
||||||
tar = s->tar;
|
|
||||||
tur = s->tur;
|
|
||||||
trr = s->trr;
|
|
||||||
|
|
||||||
f0 = s->f0;
|
|
||||||
|
|
||||||
fra = faa * taa / tra;
|
|
||||||
far = frr * trr / tar;
|
|
||||||
|
|
||||||
Ta = taa + tua + tra;
|
|
||||||
Tu = tuu;
|
|
||||||
Tr = tar + tur + trr;
|
|
||||||
|
|
||||||
A = f0;
|
|
||||||
B = f0 - 0.5 * faa * taa * taa;
|
|
||||||
C = f0 + 0.5 * faa * taa * taa + faa * taa * tua + 0.5 * fra * (taa + tua) * (taa + tua) - fra * Ta * (taa + tua);
|
|
||||||
|
|
||||||
// f1 = f0 + 0.5 * faa * taa * taa;
|
|
||||||
// f2 = f0 + 0.5 * faa * taa * taa + faa * taa * tua;
|
|
||||||
f3 = 0.5 * fra * Ta * Ta + C;
|
|
||||||
|
|
||||||
D = f3 - 0.5 * far * (Ta + Tu) * (Ta + Tu);
|
|
||||||
f4 = -far * 0.5 * (Ta + Tu + tar) * (Ta + Tu + tar) + far * (Ta + Tu) * (Ta + Tu + tar) + D;
|
|
||||||
|
|
||||||
E = f4 + far * tar * (Ta + Tu + tar);
|
|
||||||
f5 = -far * tar * (Ta + Tu + Tr - trr) + E;
|
|
||||||
|
|
||||||
F = f5 + frr * (Ta + Tu + Tr) * (Ta + Tu + Tr - trr) - 0.5 * frr * (Ta + Tu + Tr - trr) * (Ta + Tu + Tr - trr);
|
|
||||||
|
|
||||||
// 如果时间点在全行程规定的时间段内
|
|
||||||
if ((t >= 0) && (t <= Ta + Tu + Tr))
|
|
||||||
{
|
|
||||||
// 加加速段
|
|
||||||
if ((t >= 0) && (t <= taa))
|
|
||||||
{
|
|
||||||
*freq = 0.5 * faa * t * t + A;
|
|
||||||
*acc = faa * t;
|
|
||||||
}
|
|
||||||
// 匀加速段
|
|
||||||
else if ((t >= taa) && (t <= taa + tua))
|
|
||||||
{
|
|
||||||
*freq = faa * taa * t + B;
|
|
||||||
*acc = faa * taa;
|
|
||||||
}
|
|
||||||
// 加减速段
|
|
||||||
else if ((t >= taa + tua) && (t <= taa + tua + tra))
|
|
||||||
{
|
|
||||||
*freq = -0.5 * fra * t * t + fra * Ta * t + C;
|
|
||||||
*acc = -fra * t + fra * Ta;
|
|
||||||
}
|
|
||||||
// 匀速段
|
|
||||||
else if ((t >= Ta) && (t <= Ta + tuu))
|
|
||||||
{
|
|
||||||
*freq = f3;
|
|
||||||
*acc = 0;
|
|
||||||
}
|
|
||||||
// 加减速段
|
|
||||||
else if ((t >= Ta + Tu) && (t <= Ta + Tu + tar))
|
|
||||||
{
|
|
||||||
*freq = -0.5 * far * t * t + far * (Ta + Tu) * t + D;
|
|
||||||
*acc = -far * t + far * (Ta + Tu);
|
|
||||||
}
|
|
||||||
// 匀减速
|
|
||||||
else if ((t >= Ta + Tu + tar) && (t <= Ta + Tu + tar + tur))
|
|
||||||
{
|
|
||||||
*freq = -far * tar * t + E;
|
|
||||||
*acc = -far * tar;
|
|
||||||
}
|
|
||||||
// 减减速
|
|
||||||
else if ((t >= Ta + Tu + Tr - trr) && (t <= Ta + Tu + Tr))
|
|
||||||
{
|
|
||||||
*freq = 0.5 * frr * t * t - frr * (Ta + Tu + Tr) * t + F;
|
|
||||||
*acc = frr * t - frr * (Ta + Tu + Tr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// S型曲线初始化
|
|
||||||
void s_curve_table_gen(uint16_t tmin, uint16_t tmax)
|
|
||||||
{
|
|
||||||
uint16_t i, tint;
|
|
||||||
float32 ti;
|
|
||||||
float32 freq;
|
|
||||||
float32 acc;
|
|
||||||
float32 fi;
|
|
||||||
s_curve_t s;
|
|
||||||
osel_memset((uint8_t *)&s, 0, sizeof(s_curve_t));
|
|
||||||
|
|
||||||
s.f0 = F0;
|
|
||||||
s.taa = TAA;
|
|
||||||
s.tua = TUA;
|
|
||||||
s.tra = TRA;
|
|
||||||
s.tuu = TUU;
|
|
||||||
s.tar = TAR;
|
|
||||||
s.tur = TUR;
|
|
||||||
s.trr = TRR;
|
|
||||||
|
|
||||||
// 根据约束条件求出加加速段与减减速段斜率
|
|
||||||
s.faa = 2.0 / (s.taa * (s.taa + s.tra + 2 * s.tua));
|
|
||||||
s.frr = 2.0 / (s.trr * (s.tar + s.trr + 2 * s.tur));
|
|
||||||
|
|
||||||
for (i = 0; i < S_CURVE_TABLE_LEN; i++)
|
|
||||||
{
|
|
||||||
// 求出每个时间点对应的频率以及加速度
|
|
||||||
fi = i * (TAA + TUA + TRA + TUU + TAR + TUR + TRR) / S_CURVE_TABLE_LEN;
|
|
||||||
s_curve_func(&s, fi, &freq, &acc);
|
|
||||||
|
|
||||||
// 根据最大与最小装载值确定定时器实际值
|
|
||||||
ti = tmax - (tmax - tmin) * freq;
|
|
||||||
// 转换为整数值
|
|
||||||
tint = (uint16_t)ti;
|
|
||||||
|
|
||||||
// 存入s曲线表
|
|
||||||
s_curve_table[i] = tint;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,737 +0,0 @@
|
||||||
/**
|
|
||||||
* @file ssd1306_oled.c
|
|
||||||
* @author xushenghao
|
|
||||||
* @brief SSD1306 OLED display driver
|
|
||||||
* @version 0.1
|
|
||||||
* @note PB13-SCK PB12-SDA
|
|
||||||
*/
|
|
||||||
#include "ssd1306_oled.h"
|
|
||||||
|
|
||||||
#include "ssd1306_oled.h"
|
|
||||||
|
|
||||||
/************************************6*8的点阵************************************/
|
|
||||||
const uint8_t F6x8[][6] =
|
|
||||||
{
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // sp
|
|
||||||
0x00, 0x00, 0x00, 0x2f, 0x00, 0x00, // !
|
|
||||||
0x00, 0x00, 0x07, 0x00, 0x07, 0x00, // "
|
|
||||||
0x00, 0x14, 0x7f, 0x14, 0x7f, 0x14, // #
|
|
||||||
0x00, 0x24, 0x2a, 0x7f, 0x2a, 0x12, // $
|
|
||||||
0x00, 0x62, 0x64, 0x08, 0x13, 0x23, // %
|
|
||||||
0x00, 0x36, 0x49, 0x55, 0x22, 0x50, // &
|
|
||||||
0x00, 0x00, 0x05, 0x03, 0x00, 0x00, // '
|
|
||||||
0x00, 0x00, 0x1c, 0x22, 0x41, 0x00, // (
|
|
||||||
0x00, 0x00, 0x41, 0x22, 0x1c, 0x00, // )
|
|
||||||
0x00, 0x14, 0x08, 0x3E, 0x08, 0x14, // *
|
|
||||||
0x00, 0x08, 0x08, 0x3E, 0x08, 0x08, // +
|
|
||||||
0x00, 0x00, 0x00, 0xA0, 0x60, 0x00, // ,
|
|
||||||
0x00, 0x08, 0x08, 0x08, 0x08, 0x08, // -
|
|
||||||
0x00, 0x00, 0x60, 0x60, 0x00, 0x00, // .
|
|
||||||
0x00, 0x20, 0x10, 0x08, 0x04, 0x02, // /
|
|
||||||
0x00, 0x3E, 0x51, 0x49, 0x45, 0x3E, // 0
|
|
||||||
0x00, 0x00, 0x42, 0x7F, 0x40, 0x00, // 1
|
|
||||||
0x00, 0x42, 0x61, 0x51, 0x49, 0x46, // 2
|
|
||||||
0x00, 0x21, 0x41, 0x45, 0x4B, 0x31, // 3
|
|
||||||
0x00, 0x18, 0x14, 0x12, 0x7F, 0x10, // 4
|
|
||||||
0x00, 0x27, 0x45, 0x45, 0x45, 0x39, // 5
|
|
||||||
0x00, 0x3C, 0x4A, 0x49, 0x49, 0x30, // 6
|
|
||||||
0x00, 0x01, 0x71, 0x09, 0x05, 0x03, // 7
|
|
||||||
0x00, 0x36, 0x49, 0x49, 0x49, 0x36, // 8
|
|
||||||
0x00, 0x06, 0x49, 0x49, 0x29, 0x1E, // 9
|
|
||||||
0x00, 0x00, 0x36, 0x36, 0x00, 0x00, // :
|
|
||||||
0x00, 0x00, 0x56, 0x36, 0x00, 0x00, // ;
|
|
||||||
0x00, 0x08, 0x14, 0x22, 0x41, 0x00, // <
|
|
||||||
0x00, 0x14, 0x14, 0x14, 0x14, 0x14, // =
|
|
||||||
0x00, 0x00, 0x41, 0x22, 0x14, 0x08, // >
|
|
||||||
0x00, 0x02, 0x01, 0x51, 0x09, 0x06, // ?
|
|
||||||
0x00, 0x32, 0x49, 0x59, 0x51, 0x3E, // @
|
|
||||||
0x00, 0x7C, 0x12, 0x11, 0x12, 0x7C, // A
|
|
||||||
0x00, 0x7F, 0x49, 0x49, 0x49, 0x36, // B
|
|
||||||
0x00, 0x3E, 0x41, 0x41, 0x41, 0x22, // C
|
|
||||||
0x00, 0x7F, 0x41, 0x41, 0x22, 0x1C, // D
|
|
||||||
0x00, 0x7F, 0x49, 0x49, 0x49, 0x41, // E
|
|
||||||
0x00, 0x7F, 0x09, 0x09, 0x09, 0x01, // F
|
|
||||||
0x00, 0x3E, 0x41, 0x49, 0x49, 0x7A, // G
|
|
||||||
0x00, 0x7F, 0x08, 0x08, 0x08, 0x7F, // H
|
|
||||||
0x00, 0x00, 0x41, 0x7F, 0x41, 0x00, // I
|
|
||||||
0x00, 0x20, 0x40, 0x41, 0x3F, 0x01, // J
|
|
||||||
0x00, 0x7F, 0x08, 0x14, 0x22, 0x41, // K
|
|
||||||
0x00, 0x7F, 0x40, 0x40, 0x40, 0x40, // L
|
|
||||||
0x00, 0x7F, 0x02, 0x0C, 0x02, 0x7F, // M
|
|
||||||
0x00, 0x7F, 0x04, 0x08, 0x10, 0x7F, // N
|
|
||||||
0x00, 0x3E, 0x41, 0x41, 0x41, 0x3E, // O
|
|
||||||
0x00, 0x7F, 0x09, 0x09, 0x09, 0x06, // P
|
|
||||||
0x00, 0x3E, 0x41, 0x51, 0x21, 0x5E, // Q
|
|
||||||
0x00, 0x7F, 0x09, 0x19, 0x29, 0x46, // R
|
|
||||||
0x00, 0x46, 0x49, 0x49, 0x49, 0x31, // S
|
|
||||||
0x00, 0x01, 0x01, 0x7F, 0x01, 0x01, // T
|
|
||||||
0x00, 0x3F, 0x40, 0x40, 0x40, 0x3F, // U
|
|
||||||
0x00, 0x1F, 0x20, 0x40, 0x20, 0x1F, // V
|
|
||||||
0x00, 0x3F, 0x40, 0x38, 0x40, 0x3F, // W
|
|
||||||
0x00, 0x63, 0x14, 0x08, 0x14, 0x63, // X
|
|
||||||
0x00, 0x07, 0x08, 0x70, 0x08, 0x07, // Y
|
|
||||||
0x00, 0x61, 0x51, 0x49, 0x45, 0x43, // Z
|
|
||||||
0x00, 0x00, 0x7F, 0x41, 0x41, 0x00, // [
|
|
||||||
0x00, 0x55, 0x2A, 0x55, 0x2A, 0x55, // 55
|
|
||||||
0x00, 0x00, 0x41, 0x41, 0x7F, 0x00, // ]
|
|
||||||
0x00, 0x04, 0x02, 0x01, 0x02, 0x04, // ^
|
|
||||||
0x00, 0x40, 0x40, 0x40, 0x40, 0x40, // _
|
|
||||||
0x00, 0x00, 0x01, 0x02, 0x04, 0x00, // '
|
|
||||||
0x00, 0x20, 0x54, 0x54, 0x54, 0x78, // a
|
|
||||||
0x00, 0x7F, 0x48, 0x44, 0x44, 0x38, // b
|
|
||||||
0x00, 0x38, 0x44, 0x44, 0x44, 0x20, // c
|
|
||||||
0x00, 0x38, 0x44, 0x44, 0x48, 0x7F, // d
|
|
||||||
0x00, 0x38, 0x54, 0x54, 0x54, 0x18, // e
|
|
||||||
0x00, 0x08, 0x7E, 0x09, 0x01, 0x02, // f
|
|
||||||
0x00, 0x18, 0xA4, 0xA4, 0xA4, 0x7C, // g
|
|
||||||
0x00, 0x7F, 0x08, 0x04, 0x04, 0x78, // h
|
|
||||||
0x00, 0x00, 0x44, 0x7D, 0x40, 0x00, // i
|
|
||||||
0x00, 0x40, 0x80, 0x84, 0x7D, 0x00, // j
|
|
||||||
0x00, 0x7F, 0x10, 0x28, 0x44, 0x00, // k
|
|
||||||
0x00, 0x00, 0x41, 0x7F, 0x40, 0x00, // l
|
|
||||||
0x00, 0x7C, 0x04, 0x18, 0x04, 0x78, // m
|
|
||||||
0x00, 0x7C, 0x08, 0x04, 0x04, 0x78, // n
|
|
||||||
0x00, 0x38, 0x44, 0x44, 0x44, 0x38, // o
|
|
||||||
0x00, 0xFC, 0x24, 0x24, 0x24, 0x18, // p
|
|
||||||
0x00, 0x18, 0x24, 0x24, 0x18, 0xFC, // q
|
|
||||||
0x00, 0x7C, 0x08, 0x04, 0x04, 0x08, // r
|
|
||||||
0x00, 0x48, 0x54, 0x54, 0x54, 0x20, // s
|
|
||||||
0x00, 0x04, 0x3F, 0x44, 0x40, 0x20, // t
|
|
||||||
0x00, 0x3C, 0x40, 0x40, 0x20, 0x7C, // u
|
|
||||||
0x00, 0x1C, 0x20, 0x40, 0x20, 0x1C, // v
|
|
||||||
0x00, 0x3C, 0x40, 0x30, 0x40, 0x3C, // w
|
|
||||||
0x00, 0x44, 0x28, 0x10, 0x28, 0x44, // x
|
|
||||||
0x00, 0x1C, 0xA0, 0xA0, 0xA0, 0x7C, // y
|
|
||||||
0x00, 0x44, 0x64, 0x54, 0x4C, 0x44, // z
|
|
||||||
0x14, 0x14, 0x14, 0x14, 0x14, 0x14, // horiz lines
|
|
||||||
};
|
|
||||||
/****************************************8*16的点阵************************************/
|
|
||||||
const uint8_t F8X16[] =
|
|
||||||
{
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0
|
|
||||||
0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x30, 0x00, 0x00, 0x00, //! 1
|
|
||||||
0x00, 0x10, 0x0C, 0x06, 0x10, 0x0C, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //" 2
|
|
||||||
0x40, 0xC0, 0x78, 0x40, 0xC0, 0x78, 0x40, 0x00, 0x04, 0x3F, 0x04, 0x04, 0x3F, 0x04, 0x04, 0x00, // # 3
|
|
||||||
0x00, 0x70, 0x88, 0xFC, 0x08, 0x30, 0x00, 0x00, 0x00, 0x18, 0x20, 0xFF, 0x21, 0x1E, 0x00, 0x00, //$ 4
|
|
||||||
0xF0, 0x08, 0xF0, 0x00, 0xE0, 0x18, 0x00, 0x00, 0x00, 0x21, 0x1C, 0x03, 0x1E, 0x21, 0x1E, 0x00, //% 5
|
|
||||||
0x00, 0xF0, 0x08, 0x88, 0x70, 0x00, 0x00, 0x00, 0x1E, 0x21, 0x23, 0x24, 0x19, 0x27, 0x21, 0x10, //& 6
|
|
||||||
0x10, 0x16, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //' 7
|
|
||||||
0x00, 0x00, 0x00, 0xE0, 0x18, 0x04, 0x02, 0x00, 0x00, 0x00, 0x00, 0x07, 0x18, 0x20, 0x40, 0x00, //( 8
|
|
||||||
0x00, 0x02, 0x04, 0x18, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x40, 0x20, 0x18, 0x07, 0x00, 0x00, 0x00, //) 9
|
|
||||||
0x40, 0x40, 0x80, 0xF0, 0x80, 0x40, 0x40, 0x00, 0x02, 0x02, 0x01, 0x0F, 0x01, 0x02, 0x02, 0x00, //* 10
|
|
||||||
0x00, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x1F, 0x01, 0x01, 0x01, 0x00, //+ 11
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xB0, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, //, 12
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, //- 13
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, //. 14
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x80, 0x60, 0x18, 0x04, 0x00, 0x60, 0x18, 0x06, 0x01, 0x00, 0x00, 0x00, /// 15
|
|
||||||
0x00, 0xE0, 0x10, 0x08, 0x08, 0x10, 0xE0, 0x00, 0x00, 0x0F, 0x10, 0x20, 0x20, 0x10, 0x0F, 0x00, // 0 16
|
|
||||||
0x00, 0x10, 0x10, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x20, 0x3F, 0x20, 0x20, 0x00, 0x00, // 1 17
|
|
||||||
0x00, 0x70, 0x08, 0x08, 0x08, 0x88, 0x70, 0x00, 0x00, 0x30, 0x28, 0x24, 0x22, 0x21, 0x30, 0x00, // 2 18
|
|
||||||
0x00, 0x30, 0x08, 0x88, 0x88, 0x48, 0x30, 0x00, 0x00, 0x18, 0x20, 0x20, 0x20, 0x11, 0x0E, 0x00, // 3 19
|
|
||||||
0x00, 0x00, 0xC0, 0x20, 0x10, 0xF8, 0x00, 0x00, 0x00, 0x07, 0x04, 0x24, 0x24, 0x3F, 0x24, 0x00, // 4 20
|
|
||||||
0x00, 0xF8, 0x08, 0x88, 0x88, 0x08, 0x08, 0x00, 0x00, 0x19, 0x21, 0x20, 0x20, 0x11, 0x0E, 0x00, // 5 21
|
|
||||||
0x00, 0xE0, 0x10, 0x88, 0x88, 0x18, 0x00, 0x00, 0x00, 0x0F, 0x11, 0x20, 0x20, 0x11, 0x0E, 0x00, // 6 22
|
|
||||||
0x00, 0x38, 0x08, 0x08, 0xC8, 0x38, 0x08, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x00, // 7 23
|
|
||||||
0x00, 0x70, 0x88, 0x08, 0x08, 0x88, 0x70, 0x00, 0x00, 0x1C, 0x22, 0x21, 0x21, 0x22, 0x1C, 0x00, // 8 24
|
|
||||||
0x00, 0xE0, 0x10, 0x08, 0x08, 0x10, 0xE0, 0x00, 0x00, 0x00, 0x31, 0x22, 0x22, 0x11, 0x0F, 0x00, // 9 25
|
|
||||||
0x00, 0x00, 0x00, 0xC0, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, //: 26
|
|
||||||
0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x60, 0x00, 0x00, 0x00, 0x00, //; 27
|
|
||||||
0x00, 0x00, 0x80, 0x40, 0x20, 0x10, 0x08, 0x00, 0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x00, //< 28
|
|
||||||
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x00, //= 29
|
|
||||||
0x00, 0x08, 0x10, 0x20, 0x40, 0x80, 0x00, 0x00, 0x00, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01, 0x00, //> 30
|
|
||||||
0x00, 0x70, 0x48, 0x08, 0x08, 0x08, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x30, 0x36, 0x01, 0x00, 0x00, //? 31
|
|
||||||
0xC0, 0x30, 0xC8, 0x28, 0xE8, 0x10, 0xE0, 0x00, 0x07, 0x18, 0x27, 0x24, 0x23, 0x14, 0x0B, 0x00, //@ 32
|
|
||||||
0x00, 0x00, 0xC0, 0x38, 0xE0, 0x00, 0x00, 0x00, 0x20, 0x3C, 0x23, 0x02, 0x02, 0x27, 0x38, 0x20, // A 33
|
|
||||||
0x08, 0xF8, 0x88, 0x88, 0x88, 0x70, 0x00, 0x00, 0x20, 0x3F, 0x20, 0x20, 0x20, 0x11, 0x0E, 0x00, // B 34
|
|
||||||
0xC0, 0x30, 0x08, 0x08, 0x08, 0x08, 0x38, 0x00, 0x07, 0x18, 0x20, 0x20, 0x20, 0x10, 0x08, 0x00, // C 35
|
|
||||||
0x08, 0xF8, 0x08, 0x08, 0x08, 0x10, 0xE0, 0x00, 0x20, 0x3F, 0x20, 0x20, 0x20, 0x10, 0x0F, 0x00, // D 36
|
|
||||||
0x08, 0xF8, 0x88, 0x88, 0xE8, 0x08, 0x10, 0x00, 0x20, 0x3F, 0x20, 0x20, 0x23, 0x20, 0x18, 0x00, // E 37
|
|
||||||
0x08, 0xF8, 0x88, 0x88, 0xE8, 0x08, 0x10, 0x00, 0x20, 0x3F, 0x20, 0x00, 0x03, 0x00, 0x00, 0x00, // F 38
|
|
||||||
0xC0, 0x30, 0x08, 0x08, 0x08, 0x38, 0x00, 0x00, 0x07, 0x18, 0x20, 0x20, 0x22, 0x1E, 0x02, 0x00, // G 39
|
|
||||||
0x08, 0xF8, 0x08, 0x00, 0x00, 0x08, 0xF8, 0x08, 0x20, 0x3F, 0x21, 0x01, 0x01, 0x21, 0x3F, 0x20, // H 40
|
|
||||||
0x00, 0x08, 0x08, 0xF8, 0x08, 0x08, 0x00, 0x00, 0x00, 0x20, 0x20, 0x3F, 0x20, 0x20, 0x00, 0x00, // I 41
|
|
||||||
0x00, 0x00, 0x08, 0x08, 0xF8, 0x08, 0x08, 0x00, 0xC0, 0x80, 0x80, 0x80, 0x7F, 0x00, 0x00, 0x00, // J 42
|
|
||||||
0x08, 0xF8, 0x88, 0xC0, 0x28, 0x18, 0x08, 0x00, 0x20, 0x3F, 0x20, 0x01, 0x26, 0x38, 0x20, 0x00, // K 43
|
|
||||||
0x08, 0xF8, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x3F, 0x20, 0x20, 0x20, 0x20, 0x30, 0x00, // L 44
|
|
||||||
0x08, 0xF8, 0xF8, 0x00, 0xF8, 0xF8, 0x08, 0x00, 0x20, 0x3F, 0x00, 0x3F, 0x00, 0x3F, 0x20, 0x00, // M 45
|
|
||||||
0x08, 0xF8, 0x30, 0xC0, 0x00, 0x08, 0xF8, 0x08, 0x20, 0x3F, 0x20, 0x00, 0x07, 0x18, 0x3F, 0x00, // N 46
|
|
||||||
0xE0, 0x10, 0x08, 0x08, 0x08, 0x10, 0xE0, 0x00, 0x0F, 0x10, 0x20, 0x20, 0x20, 0x10, 0x0F, 0x00, // O 47
|
|
||||||
0x08, 0xF8, 0x08, 0x08, 0x08, 0x08, 0xF0, 0x00, 0x20, 0x3F, 0x21, 0x01, 0x01, 0x01, 0x00, 0x00, // P 48
|
|
||||||
0xE0, 0x10, 0x08, 0x08, 0x08, 0x10, 0xE0, 0x00, 0x0F, 0x18, 0x24, 0x24, 0x38, 0x50, 0x4F, 0x00, // Q 49
|
|
||||||
0x08, 0xF8, 0x88, 0x88, 0x88, 0x88, 0x70, 0x00, 0x20, 0x3F, 0x20, 0x00, 0x03, 0x0C, 0x30, 0x20, // R 50
|
|
||||||
0x00, 0x70, 0x88, 0x08, 0x08, 0x08, 0x38, 0x00, 0x00, 0x38, 0x20, 0x21, 0x21, 0x22, 0x1C, 0x00, // S 51
|
|
||||||
0x18, 0x08, 0x08, 0xF8, 0x08, 0x08, 0x18, 0x00, 0x00, 0x00, 0x20, 0x3F, 0x20, 0x00, 0x00, 0x00, // T 52
|
|
||||||
0x08, 0xF8, 0x08, 0x00, 0x00, 0x08, 0xF8, 0x08, 0x00, 0x1F, 0x20, 0x20, 0x20, 0x20, 0x1F, 0x00, // U 53
|
|
||||||
0x08, 0x78, 0x88, 0x00, 0x00, 0xC8, 0x38, 0x08, 0x00, 0x00, 0x07, 0x38, 0x0E, 0x01, 0x00, 0x00, // V 54
|
|
||||||
0xF8, 0x08, 0x00, 0xF8, 0x00, 0x08, 0xF8, 0x00, 0x03, 0x3C, 0x07, 0x00, 0x07, 0x3C, 0x03, 0x00, // W 55
|
|
||||||
0x08, 0x18, 0x68, 0x80, 0x80, 0x68, 0x18, 0x08, 0x20, 0x30, 0x2C, 0x03, 0x03, 0x2C, 0x30, 0x20, // X 56
|
|
||||||
0x08, 0x38, 0xC8, 0x00, 0xC8, 0x38, 0x08, 0x00, 0x00, 0x00, 0x20, 0x3F, 0x20, 0x00, 0x00, 0x00, // Y 57
|
|
||||||
0x10, 0x08, 0x08, 0x08, 0xC8, 0x38, 0x08, 0x00, 0x20, 0x38, 0x26, 0x21, 0x20, 0x20, 0x18, 0x00, // Z 58
|
|
||||||
0x00, 0x00, 0x00, 0xFE, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x40, 0x40, 0x40, 0x00, //[ 59
|
|
||||||
0x00, 0x0C, 0x30, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x06, 0x38, 0xC0, 0x00, //\ 60
|
|
||||||
0x00, 0x02, 0x02, 0x02, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x40, 0x40, 0x40, 0x7F, 0x00, 0x00, 0x00, //] 61
|
|
||||||
0x00, 0x00, 0x04, 0x02, 0x02, 0x02, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //^ 62
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, //_ 63
|
|
||||||
0x00, 0x02, 0x02, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //` 64
|
|
||||||
0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x19, 0x24, 0x22, 0x22, 0x22, 0x3F, 0x20, // a 65
|
|
||||||
0x08, 0xF8, 0x00, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x11, 0x20, 0x20, 0x11, 0x0E, 0x00, // b 66
|
|
||||||
0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x0E, 0x11, 0x20, 0x20, 0x20, 0x11, 0x00, // c 67
|
|
||||||
0x00, 0x00, 0x00, 0x80, 0x80, 0x88, 0xF8, 0x00, 0x00, 0x0E, 0x11, 0x20, 0x20, 0x10, 0x3F, 0x20, // d 68
|
|
||||||
0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x1F, 0x22, 0x22, 0x22, 0x22, 0x13, 0x00, // e 69
|
|
||||||
0x00, 0x80, 0x80, 0xF0, 0x88, 0x88, 0x88, 0x18, 0x00, 0x20, 0x20, 0x3F, 0x20, 0x20, 0x00, 0x00, // f 70
|
|
||||||
0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x6B, 0x94, 0x94, 0x94, 0x93, 0x60, 0x00, // g 71
|
|
||||||
0x08, 0xF8, 0x00, 0x80, 0x80, 0x80, 0x00, 0x00, 0x20, 0x3F, 0x21, 0x00, 0x00, 0x20, 0x3F, 0x20, // h 72
|
|
||||||
0x00, 0x80, 0x98, 0x98, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x20, 0x3F, 0x20, 0x20, 0x00, 0x00, // i 73
|
|
||||||
0x00, 0x00, 0x00, 0x80, 0x98, 0x98, 0x00, 0x00, 0x00, 0xC0, 0x80, 0x80, 0x80, 0x7F, 0x00, 0x00, // j 74
|
|
||||||
0x08, 0xF8, 0x00, 0x00, 0x80, 0x80, 0x80, 0x00, 0x20, 0x3F, 0x24, 0x02, 0x2D, 0x30, 0x20, 0x00, // k 75
|
|
||||||
0x00, 0x08, 0x08, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x20, 0x3F, 0x20, 0x20, 0x00, 0x00, // l 76
|
|
||||||
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x20, 0x3F, 0x20, 0x00, 0x3F, 0x20, 0x00, 0x3F, // m 77
|
|
||||||
0x80, 0x80, 0x00, 0x80, 0x80, 0x80, 0x00, 0x00, 0x20, 0x3F, 0x21, 0x00, 0x00, 0x20, 0x3F, 0x20, // n 78
|
|
||||||
0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x1F, 0x20, 0x20, 0x20, 0x20, 0x1F, 0x00, // o 79
|
|
||||||
0x80, 0x80, 0x00, 0x80, 0x80, 0x00, 0x00, 0x00, 0x80, 0xFF, 0xA1, 0x20, 0x20, 0x11, 0x0E, 0x00, // p 80
|
|
||||||
0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x0E, 0x11, 0x20, 0x20, 0xA0, 0xFF, 0x80, // q 81
|
|
||||||
0x80, 0x80, 0x80, 0x00, 0x80, 0x80, 0x80, 0x00, 0x20, 0x20, 0x3F, 0x21, 0x20, 0x00, 0x01, 0x00, // r 82
|
|
||||||
0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x33, 0x24, 0x24, 0x24, 0x24, 0x19, 0x00, // s 83
|
|
||||||
0x00, 0x80, 0x80, 0xE0, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x20, 0x20, 0x00, 0x00, // t 84
|
|
||||||
0x80, 0x80, 0x00, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x1F, 0x20, 0x20, 0x20, 0x10, 0x3F, 0x20, // u 85
|
|
||||||
0x80, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x80, 0x00, 0x01, 0x0E, 0x30, 0x08, 0x06, 0x01, 0x00, // v 86
|
|
||||||
0x80, 0x80, 0x00, 0x80, 0x00, 0x80, 0x80, 0x80, 0x0F, 0x30, 0x0C, 0x03, 0x0C, 0x30, 0x0F, 0x00, // w 87
|
|
||||||
0x00, 0x80, 0x80, 0x00, 0x80, 0x80, 0x80, 0x00, 0x00, 0x20, 0x31, 0x2E, 0x0E, 0x31, 0x20, 0x00, // x 88
|
|
||||||
0x80, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x81, 0x8E, 0x70, 0x18, 0x06, 0x01, 0x00, // y 89
|
|
||||||
0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x21, 0x30, 0x2C, 0x22, 0x21, 0x30, 0x00, // z 90
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x80, 0x7C, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x40, 0x40, //{ 91
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, //| 92
|
|
||||||
0x00, 0x02, 0x02, 0x7C, 0x80, 0x00, 0x00, 0x00, 0x00, 0x40, 0x40, 0x3F, 0x00, 0x00, 0x00, 0x00, //} 93
|
|
||||||
0x00, 0x06, 0x01, 0x01, 0x02, 0x02, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //~ 94
|
|
||||||
};
|
|
||||||
|
|
||||||
static uint8_t _buffer[SSD1306_WIDTH * SSD1306_HEIGHT / 8]; // 定义屏幕缓冲区
|
|
||||||
|
|
||||||
static void i2c_start(void)
|
|
||||||
{
|
|
||||||
SDA_OUT();
|
|
||||||
GPIO_SET(SSD1306_SDA_PORT, SSD1306_SDA_PIN);
|
|
||||||
GPIO_SET(SSD1306_SCK_PORT, SSD1306_SCK_PIN);
|
|
||||||
delay_us(4);
|
|
||||||
GPIO_RESET(SSD1306_SDA_PORT, SSD1306_SDA_PIN);
|
|
||||||
delay_us(4);
|
|
||||||
GPIO_RESET(SSD1306_SCK_PORT, SSD1306_SCK_PIN);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void i2c_stop(void)
|
|
||||||
{
|
|
||||||
SDA_OUT();
|
|
||||||
GPIO_RESET(SSD1306_SCK_PORT, SSD1306_SCK_PIN);
|
|
||||||
GPIO_RESET(SSD1306_SDA_PORT, SSD1306_SDA_PIN);
|
|
||||||
delay_us(4);
|
|
||||||
GPIO_SET(SSD1306_SCK_PORT, SSD1306_SCK_PIN);
|
|
||||||
GPIO_SET(SSD1306_SDA_PORT, SSD1306_SDA_PIN);
|
|
||||||
delay_us(4);
|
|
||||||
}
|
|
||||||
|
|
||||||
static BOOL i2c_wait_ack(void)
|
|
||||||
{
|
|
||||||
uint8_t count = 0;
|
|
||||||
SDA_IN();
|
|
||||||
GPIO_SET(SSD1306_SDA_PORT, SSD1306_SDA_PIN);
|
|
||||||
delay_us(4);
|
|
||||||
GPIO_SET(SSD1306_SCK_PORT, SSD1306_SCK_PIN);
|
|
||||||
delay_us(4);
|
|
||||||
while (GPIO_READ(SSD1306_SDA_PORT, SSD1306_SDA_PIN))
|
|
||||||
{
|
|
||||||
count++;
|
|
||||||
if (count > 250)
|
|
||||||
{
|
|
||||||
i2c_stop();
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
GPIO_RESET(SSD1306_SCK_PORT, SSD1306_SCK_PIN);
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void i2c_ack(void)
|
|
||||||
{
|
|
||||||
GPIO_RESET(SSD1306_SCK_PORT, SSD1306_SCK_PIN);
|
|
||||||
SDA_OUT();
|
|
||||||
GPIO_RESET(SSD1306_SDA_PORT, SSD1306_SDA_PIN);
|
|
||||||
delay_us(2);
|
|
||||||
GPIO_SET(SSD1306_SCK_PORT, SSD1306_SCK_PIN);
|
|
||||||
delay_us(2);
|
|
||||||
GPIO_RESET(SSD1306_SCK_PORT, SSD1306_SCK_PIN);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void i2c_nack(void)
|
|
||||||
{
|
|
||||||
GPIO_RESET(SSD1306_SCK_PORT, SSD1306_SCK_PIN);
|
|
||||||
SDA_OUT();
|
|
||||||
GPIO_SET(SSD1306_SDA_PORT, SSD1306_SDA_PIN);
|
|
||||||
delay_us(2);
|
|
||||||
GPIO_SET(SSD1306_SCK_PORT, SSD1306_SCK_PIN);
|
|
||||||
delay_us(2);
|
|
||||||
GPIO_RESET(SSD1306_SCK_PORT, SSD1306_SCK_PIN);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t i2c_read_byte(BOOL ack)
|
|
||||||
{
|
|
||||||
uint8_t i = 0, receive = 0;
|
|
||||||
SDA_IN();
|
|
||||||
for (i = 0; i < 8; i++)
|
|
||||||
{
|
|
||||||
GPIO_RESET(SSD1306_SCK_PORT, SSD1306_SCK_PIN);
|
|
||||||
delay_us(2);
|
|
||||||
GPIO_SET(SSD1306_SCK_PORT, SSD1306_SCK_PIN);
|
|
||||||
receive <<= 1;
|
|
||||||
if (GPIO_READ(SSD1306_SDA_PORT, SSD1306_SDA_PIN))
|
|
||||||
{
|
|
||||||
receive++;
|
|
||||||
}
|
|
||||||
delay_us(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!ack)
|
|
||||||
{
|
|
||||||
i2c_nack();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
i2c_ack();
|
|
||||||
}
|
|
||||||
|
|
||||||
return receive;
|
|
||||||
}
|
|
||||||
|
|
||||||
void i2c_write_byte(uint8_t data)
|
|
||||||
{
|
|
||||||
uint8_t i = 0;
|
|
||||||
SDA_OUT();
|
|
||||||
GPIO_RESET(SSD1306_SCK_PORT, SSD1306_SCK_PIN);
|
|
||||||
for (i = 0; i < 8; i++)
|
|
||||||
{
|
|
||||||
// IIC_SDA=(txd&0x80)>>7;
|
|
||||||
if ((data & 0x80) >> 7)
|
|
||||||
GPIO_SET(SSD1306_SDA_PORT, SSD1306_SDA_PIN);
|
|
||||||
else
|
|
||||||
GPIO_RESET(SSD1306_SDA_PORT, SSD1306_SDA_PIN);
|
|
||||||
|
|
||||||
data <<= 1;
|
|
||||||
delay_us(2);
|
|
||||||
GPIO_SET(SSD1306_SCK_PORT, SSD1306_SCK_PIN);
|
|
||||||
delay_us(2);
|
|
||||||
GPIO_RESET(SSD1306_SCK_PORT, SSD1306_SCK_PIN);
|
|
||||||
delay_us(2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void i2c_write_command(uint8_t command)
|
|
||||||
{
|
|
||||||
uint8_t dd[2];
|
|
||||||
dd[0] = SSD1306_CMD_SET_LOW_COLUMN; // Co = 0, D/C# = 0
|
|
||||||
dd[1] = command;
|
|
||||||
i2c_start();
|
|
||||||
i2c_write_byte(SSD1306_I2C_ADDRESS);
|
|
||||||
i2c_wait_ack();
|
|
||||||
|
|
||||||
i2c_write_byte(dd[0]);
|
|
||||||
i2c_wait_ack();
|
|
||||||
|
|
||||||
i2c_write_byte(dd[1]);
|
|
||||||
i2c_wait_ack();
|
|
||||||
i2c_stop();
|
|
||||||
}
|
|
||||||
|
|
||||||
static void i2c_write_data(uint8_t data)
|
|
||||||
{
|
|
||||||
uint8_t dd[2];
|
|
||||||
dd[0] = SSD1306_CMD_SET_START_LINE; // Co = 0, D/C# = 1
|
|
||||||
dd[1] = data;
|
|
||||||
i2c_start();
|
|
||||||
i2c_write_byte(SSD1306_I2C_ADDRESS);
|
|
||||||
i2c_wait_ack();
|
|
||||||
|
|
||||||
i2c_write_byte(dd[0]);
|
|
||||||
i2c_wait_ack();
|
|
||||||
|
|
||||||
i2c_write_byte(dd[1]);
|
|
||||||
i2c_wait_ack();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 设置SSD1306 OLED显示屏上的显示位置
|
|
||||||
*
|
|
||||||
* 该函数用于设置SSD1306 OLED显示屏上的显示位置,通过x和y坐标确定显示位置。
|
|
||||||
*
|
|
||||||
* @param x 要设置的横坐标(0-127)
|
|
||||||
* @param y 要设置的纵坐标(0-7,对应SSD1306 OLED的8个页面)
|
|
||||||
*/
|
|
||||||
void set_position(uint8_t x, uint8_t y)
|
|
||||||
{
|
|
||||||
i2c_write_command(0xb0 + y);
|
|
||||||
i2c_write_command(((x & 0xf0) >> 4) | 0x10);
|
|
||||||
i2c_write_command((x & 0x0f) | 0x01);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ssd1306_test(void)
|
|
||||||
{
|
|
||||||
ssd1306_f8x16_string(0, 0, " TEST");
|
|
||||||
ssd1306_f8x16_number(40, 0, -15.26, 2);
|
|
||||||
ssd1306_f6x8_string_number(0, 3, " @ADC1:", 'V', 24);
|
|
||||||
ssd1306_update_screen();
|
|
||||||
}
|
|
||||||
|
|
||||||
void ssd1306_init(void)
|
|
||||||
{
|
|
||||||
i2c_write_command(SSD1306_CMD_DISPLAY_OFF); // display off
|
|
||||||
i2c_write_command(SSD1306_CMD_MEMORY_MODE); // Set Memory Addressing Mode
|
|
||||||
i2c_write_command(SSD1306_CMD_SET_HIGH_COLUMN); // 00,Horizontal Addressing Mode;01,Vertical Addressing Mode;10,Page Addressing Mode (RESET);11,Invalid
|
|
||||||
i2c_write_command(SSD1306_CMD_COM_SCAN_DEC); // Set COM Output Scan Direction
|
|
||||||
i2c_write_command(SSD1306_CMD_SET_LOW_COLUMN); //---set low column address
|
|
||||||
i2c_write_command(SSD1306_CMD_SET_HIGH_COLUMN); //---set high column address
|
|
||||||
i2c_write_command(SSD1306_CMD_SET_START_LINE); //--set start line address
|
|
||||||
i2c_write_command(SSD1306_CMD_SET_CONTRAST); //--set contrast control register
|
|
||||||
i2c_write_command(0xff); // 亮度调节 0x00~0xff
|
|
||||||
i2c_write_command(0xa1); //--set segment re-map 0 to 127
|
|
||||||
i2c_write_command(SSD1306_CMD_NORMAL_DISPLAY); //--set normal display
|
|
||||||
i2c_write_command(SSD1306_CMD_SET_MULTIPLEX); //--set multiplex ratio(1 to 64)
|
|
||||||
i2c_write_command(0x3f); //
|
|
||||||
i2c_write_command(SSD1306_CMD_DISPLAY_ALL_ON_RESUME); // 0xa4,Output follows RAM content;0xa5,Output ignores RAM content
|
|
||||||
i2c_write_command(SSD1306_CMD_SET_DISPLAY_OFFSET); //-set display offset
|
|
||||||
i2c_write_command(SSD1306_CMD_SET_LOW_COLUMN); //-not offset
|
|
||||||
i2c_write_command(SSD1306_CMD_SET_DISPLAY_CLOCK_DIV); //--set display clock divide ratio/oscillator frequency
|
|
||||||
i2c_write_command(0xf0); //--set divide ratio
|
|
||||||
i2c_write_command(SSD1306_CMD_SET_PRECHARGE); //--set pre-charge period
|
|
||||||
i2c_write_command(SSD1306_CMD_PAGE_ADDR); //
|
|
||||||
i2c_write_command(SSD1306_CMD_SET_COM_PINS); //--set com pins hardware configuration
|
|
||||||
i2c_write_command(0x12);
|
|
||||||
i2c_write_command(SSD1306_CMD_SET_VCOM_DETECT); //--set vcomh
|
|
||||||
i2c_write_command(SSD1306_CMD_MEMORY_MODE); // 0x20,0.77xVcc
|
|
||||||
i2c_write_command(SSD1306_CMD_CHARGE_PUMP); //--set DC-DC enable
|
|
||||||
i2c_write_command(SSD1306_CMD_SET_DC_DC_ENABLE); //
|
|
||||||
i2c_write_command(SSD1306_CMD_DISPLAY_ON); //--turn on oled panel
|
|
||||||
ssd1306_fill(0);
|
|
||||||
|
|
||||||
// ssd1306_test();
|
|
||||||
}
|
|
||||||
|
|
||||||
void ssd1306_display_on(void)
|
|
||||||
{
|
|
||||||
i2c_write_command(SSD1306_CMD_CHARGE_PUMP); // 设置电荷泵
|
|
||||||
i2c_write_command(SSD1306_CMD_SET_DC_DC_ENABLE); // 开启电荷泵
|
|
||||||
i2c_write_command(SSD1306_CMD_DISPLAY_ON); // OLED唤醒
|
|
||||||
}
|
|
||||||
|
|
||||||
void ssd1306_display_off(void)
|
|
||||||
{
|
|
||||||
i2c_write_command(SSD1306_CMD_CHARGE_PUMP); // 设置电荷泵
|
|
||||||
i2c_write_command(SSD1306_CMD_SET_HIGH_COLUMN); // 关闭电荷泵
|
|
||||||
i2c_write_command(SSD1306_CMD_DISPLAY_OFF); // OLED休眠
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 更新SSD1306 OLED显示屏的内容
|
|
||||||
*
|
|
||||||
* 此函数将缓冲区中的数据写入SSD1306 OLED显示屏,从而更新显示内容。
|
|
||||||
*
|
|
||||||
* 首先,通过发送命令设置列地址和页地址,然后将缓冲区中的数据逐行写入显示屏。
|
|
||||||
*
|
|
||||||
* @note 在调用此函数之前,需要将需要显示的数据写入缓冲区。
|
|
||||||
*/
|
|
||||||
void ssd1306_update_screen(void)
|
|
||||||
{
|
|
||||||
for (uint8_t i = 0; i < SSD1306_HEIGHT / 8; i++)
|
|
||||||
{
|
|
||||||
i2c_write_command(0xb0 + i);
|
|
||||||
i2c_write_command(0x01);
|
|
||||||
i2c_write_command(0x10);
|
|
||||||
for (uint8_t j = 0; j < SSD1306_WIDTH; j++)
|
|
||||||
{
|
|
||||||
i2c_write_data(_buffer[j + i * SSD1306_WIDTH]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 填充整个屏幕为指定颜色
|
|
||||||
*
|
|
||||||
* 该函数将 SSD1306 OLED 显示屏的每一个像素点都设置为指定的颜色。
|
|
||||||
*
|
|
||||||
* @param color 颜色值,0x00 表示关闭像素点(黑色),0xFF 表示打开像素点(白色)
|
|
||||||
*/
|
|
||||||
void ssd1306_fill(uint8_t color)
|
|
||||||
{
|
|
||||||
osel_memset(_buffer, color, ARRAY_LEN(_buffer));
|
|
||||||
ssd1306_update_screen();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 清空SSD1306显示屏
|
|
||||||
*
|
|
||||||
* 该函数通过向SSD1306显示屏发送一系列命令来清空显示内容。
|
|
||||||
*
|
|
||||||
* 首先,通过循环遍历每个页面(SSD1306显示屏有8个页面),
|
|
||||||
* 对每个页面执行以下操作:
|
|
||||||
* 1. 发送页面地址命令(0xb0 + y),其中y为当前页面索引。
|
|
||||||
* 2. 发送列地址低位命令(0x01)。
|
|
||||||
* 3. 发送列地址高位命令(0x10),表示从第一列开始。
|
|
||||||
* 4. 循环遍历每一列(SSD1306显示屏的宽度),
|
|
||||||
* 发送数据0x00以清空该列的内容。
|
|
||||||
*/
|
|
||||||
void ssd1306_clear(void)
|
|
||||||
{
|
|
||||||
osel_memset(_buffer, 0, ARRAY_LEN(_buffer));
|
|
||||||
ssd1306_update_screen();
|
|
||||||
}
|
|
||||||
|
|
||||||
void ssd1306_clear_buffer(void)
|
|
||||||
{
|
|
||||||
osel_memset(_buffer, 0, ARRAY_LEN(_buffer));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 在指定区域内绘制BMP
|
|
||||||
*
|
|
||||||
* 在指定坐标区域内绘制一个BMP,使用SSD1306 OLED显示屏
|
|
||||||
* ssd1306_draw_bmp(0, 0, SSD1306_WIDTH, 2);
|
|
||||||
* @param x0 BMP绘制的起始X坐标
|
|
||||||
* @param y0 BMP绘制的起始Y坐标
|
|
||||||
* @param x1 BMP绘制的结束X坐标
|
|
||||||
* @param y1 BMP绘制的结束Y坐标
|
|
||||||
*/
|
|
||||||
void ssd1306_draw_bmp(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1, uint8_t *bmp)
|
|
||||||
{
|
|
||||||
uint8_t j = 0;
|
|
||||||
uint8_t x, y;
|
|
||||||
osel_memset(_buffer, 0, ARRAY_LEN(_buffer));
|
|
||||||
if (y1 % 8 == 0)
|
|
||||||
y = y1 / 8;
|
|
||||||
else
|
|
||||||
y = y1 / 8 + 1;
|
|
||||||
for (y = y0; y < y1; y++)
|
|
||||||
{
|
|
||||||
set_position(x0, y);
|
|
||||||
for (x = x0; x < x1; x++)
|
|
||||||
{
|
|
||||||
i2c_write_data(bmp[j++]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 在SSD1306 OLED显示屏上显示字符串
|
|
||||||
*
|
|
||||||
* 在SSD1306 OLED显示屏上以6x8像素的字体显示给定的字符串。
|
|
||||||
*
|
|
||||||
* @param x 显示字符串的起始x坐标
|
|
||||||
* @param y 显示字符串的起始y坐标
|
|
||||||
* @param str 要显示的字符串
|
|
||||||
*/
|
|
||||||
void ssd1306_f6x8_string(uint8_t x, uint8_t y, const uint8_t *ch)
|
|
||||||
{
|
|
||||||
uint8_t c = 0, i = 0, j = 0;
|
|
||||||
while (ch[j] != '\0')
|
|
||||||
{
|
|
||||||
c = ch[j] - 32;
|
|
||||||
if (x > 126)
|
|
||||||
{
|
|
||||||
x = 0;
|
|
||||||
y++;
|
|
||||||
}
|
|
||||||
for (i = 0; i < 6; i++)
|
|
||||||
_buffer[(y * SSD1306_WIDTH) + x + i] = F6x8[c][i];
|
|
||||||
x += 6;
|
|
||||||
j++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 在SSD1306 OLED屏幕上显示字符串和数字
|
|
||||||
*
|
|
||||||
* 该函数用于在SSD1306 OLED屏幕上显示字符串和数字。首先显示一个字符串,
|
|
||||||
* 然后显示一个浮点数。字符串和数字按照指定的位置和单位显示。
|
|
||||||
*
|
|
||||||
* @param x 起始位置的x坐标
|
|
||||||
* @param y 起始位置的y坐标
|
|
||||||
* @param ch 要显示的字符串
|
|
||||||
* @param unit 数字的单位,例如'm'表示米
|
|
||||||
* @param num 要显示的浮点数
|
|
||||||
*/
|
|
||||||
void ssd1306_f6x8_string_number(uint8_t x, uint8_t y, const uint8_t *ch, uint8_t unit, float32 num)
|
|
||||||
{
|
|
||||||
uint8_t c = 0, i = 0, j = 0;
|
|
||||||
int8_t a, number[7] = {0, 0, 0, -2, 0, 0, 0};
|
|
||||||
uint32_t d;
|
|
||||||
while (ch[j] != '\0')
|
|
||||||
{
|
|
||||||
c = ch[j] - 32;
|
|
||||||
if (x > 126)
|
|
||||||
{
|
|
||||||
x = 0;
|
|
||||||
y++;
|
|
||||||
}
|
|
||||||
for (i = 0; i < 6; i++)
|
|
||||||
_buffer[(y * SSD1306_WIDTH) + x + i] = F6x8[c][i];
|
|
||||||
x += 6;
|
|
||||||
j++;
|
|
||||||
}
|
|
||||||
d = 1000 * num;
|
|
||||||
for (a = 0; a < 3; a++)
|
|
||||||
{
|
|
||||||
number[6 - a] = d % 10;
|
|
||||||
d = d / 10;
|
|
||||||
}
|
|
||||||
for (a = 4; a < 7; a++)
|
|
||||||
{
|
|
||||||
number[6 - a] = d % 10;
|
|
||||||
d = d / 10;
|
|
||||||
}
|
|
||||||
if (num >= 100)
|
|
||||||
{
|
|
||||||
a = 0;
|
|
||||||
}
|
|
||||||
else if (num >= 10)
|
|
||||||
{
|
|
||||||
a = 1;
|
|
||||||
}
|
|
||||||
else if (num >= 0)
|
|
||||||
{
|
|
||||||
a = 2;
|
|
||||||
}
|
|
||||||
for (; a < 7; a++)
|
|
||||||
{
|
|
||||||
c = number[a] + 16;
|
|
||||||
if (x > 126)
|
|
||||||
{
|
|
||||||
x = 0;
|
|
||||||
y++;
|
|
||||||
}
|
|
||||||
for (i = 0; i < 6; i++)
|
|
||||||
_buffer[(y * SSD1306_WIDTH) + x + i] = F6x8[c][i];
|
|
||||||
x += 6;
|
|
||||||
j++;
|
|
||||||
}
|
|
||||||
for (int h = 0; h < 7; h++)
|
|
||||||
{
|
|
||||||
c = unit - 32;
|
|
||||||
for (i = 0; i < 6; i++)
|
|
||||||
_buffer[(y * SSD1306_WIDTH) + x + i] = F6x8[c][i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 在SSD1306 OLED显示屏上显示8x16大小的字符串
|
|
||||||
*
|
|
||||||
* 该函数使用8x16字体在SSD1306 OLED显示屏上显示指定的字符串。字符串的字符位置由x和y参数指定。
|
|
||||||
*
|
|
||||||
* @param x 显示字符串的起始x坐标
|
|
||||||
* @param y 显示字符串的起始y坐标
|
|
||||||
* @param str 要显示的字符串
|
|
||||||
*/
|
|
||||||
void ssd1306_f8x16_string(uint8_t x, uint8_t y, const uint8_t *ch)
|
|
||||||
{
|
|
||||||
uint8_t c = 0, i = 0, j = 0;
|
|
||||||
while (ch[j] != '\0')
|
|
||||||
{
|
|
||||||
c = ch[j] - 32;
|
|
||||||
if (x > 120)
|
|
||||||
{
|
|
||||||
x = 0;
|
|
||||||
y++;
|
|
||||||
}
|
|
||||||
for (i = 0; i < 8; i++)
|
|
||||||
_buffer[(y * SSD1306_WIDTH) + x + i] = F8X16[c * 16 + i];
|
|
||||||
for (i = 0; i < 8; i++)
|
|
||||||
_buffer[((y + 1) * SSD1306_WIDTH) + x + i] = F8X16[c * 16 + i + 8];
|
|
||||||
x += 8;
|
|
||||||
j++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 在SSD1306 OLED显示屏上以8x16像素字体显示浮点数
|
|
||||||
*
|
|
||||||
* 在指定的坐标位置 (x, y) 上,使用8x16像素大小的字体显示浮点数 num,并显示指定数量的小数点 dot_num。
|
|
||||||
*
|
|
||||||
* @param x 显示位置的x坐标
|
|
||||||
* @param y 显示位置的y坐标
|
|
||||||
* @param num 要显示的浮点数
|
|
||||||
* @param dot_num 要显示的小数点数量
|
|
||||||
*/
|
|
||||||
void ssd1306_f8x16_number(uint8_t x, uint8_t y, float32 num, uint8_t dot_num)
|
|
||||||
{
|
|
||||||
uint8_t ch[9] = {'\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0'};
|
|
||||||
uint8_t c = 0, i = 0, j = 0;
|
|
||||||
if (num < 0)
|
|
||||||
{
|
|
||||||
ch[i++] = '-';
|
|
||||||
num = -num;
|
|
||||||
}
|
|
||||||
if (num > 32000)
|
|
||||||
return;
|
|
||||||
|
|
||||||
c = 8 - i;
|
|
||||||
|
|
||||||
if (num >= 10000)
|
|
||||||
{
|
|
||||||
ch[i++] = num / 10000 + 48;
|
|
||||||
ch[i++] = (int32_t)(num) % 10000 / 1000 + 48;
|
|
||||||
ch[i++] = (int32_t)(num) % 1000 / 100 + 48;
|
|
||||||
ch[i++] = (int32_t)(num) % 100 / 10 + 48;
|
|
||||||
ch[i++] = (int32_t)(num) % 10 + 48;
|
|
||||||
}
|
|
||||||
else if (num >= 1000)
|
|
||||||
{
|
|
||||||
ch[i++] = (int32_t)(num) % 10000 / 1000 + 48;
|
|
||||||
ch[i++] = (int32_t)(num) % 1000 / 100 + 48;
|
|
||||||
ch[i++] = (int32_t)(num) % 100 / 10 + 48;
|
|
||||||
ch[i++] = (int32_t)(num) % 10 + 48;
|
|
||||||
}
|
|
||||||
else if (num >= 100)
|
|
||||||
{
|
|
||||||
ch[i++] = (int32_t)(num) % 1000 / 100 + 48;
|
|
||||||
ch[i++] = (int32_t)(num) % 100 / 10 + 48;
|
|
||||||
ch[i++] = (int32_t)(num) % 10 + 48;
|
|
||||||
}
|
|
||||||
else if (num >= 10)
|
|
||||||
{
|
|
||||||
ch[i++] = (int32_t)(num) % 100 / 10 + 48;
|
|
||||||
ch[i++] = (int32_t)(num) % 10 + 48;
|
|
||||||
}
|
|
||||||
else if (num >= 0)
|
|
||||||
{
|
|
||||||
ch[i++] = (int32_t)(num) % 10 + 48;
|
|
||||||
}
|
|
||||||
if (dot_num > 0 && i < 7)
|
|
||||||
{
|
|
||||||
ch[i++] = '.';
|
|
||||||
num = num - (int32_t)num;
|
|
||||||
|
|
||||||
if (dot_num == 1 && i < 8)
|
|
||||||
{
|
|
||||||
num = num * 10;
|
|
||||||
ch[i++] = (int32_t)(num + 0.5) % 10 + 48;
|
|
||||||
}
|
|
||||||
if (dot_num >= 2 && i < 8)
|
|
||||||
{
|
|
||||||
num = num * 100;
|
|
||||||
ch[i++] = (int32_t)num % 100 / 10 + 48;
|
|
||||||
if (i < 8)
|
|
||||||
ch[i++] = (int32_t)(num + 0.5) % 10 + 48;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
while (ch[j] != '\0')
|
|
||||||
{
|
|
||||||
c = ch[j] - 32;
|
|
||||||
if (x > 120)
|
|
||||||
{
|
|
||||||
x = 0;
|
|
||||||
y++;
|
|
||||||
}
|
|
||||||
for (i = 0; i < 8; i++)
|
|
||||||
_buffer[(y * SSD1306_WIDTH) + x + i] = F8X16[c * 16 + i];
|
|
||||||
for (i = 0; i < 8; i++)
|
|
||||||
_buffer[((y + 1) * SSD1306_WIDTH) + x + i] = F8X16[c * 16 + i + 8];
|
|
||||||
x += 8;
|
|
||||||
j++;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,68 +0,0 @@
|
||||||
#ifndef __SSD1306_OLED_H
|
|
||||||
#define __SSD1306_OLED_H
|
|
||||||
|
|
||||||
#include "main.h"
|
|
||||||
|
|
||||||
// OLED引脚定义
|
|
||||||
#define SSD1306_SDA_PORT OLED_SDA_GPIO_Port
|
|
||||||
#define SSD1306_SDA_PIN OLED_SDA_Pin
|
|
||||||
#define SSD1306_SCK_PORT OLDE_SCK_GPIO_Port
|
|
||||||
#define SSD1306_SCK_PIN OLDE_SCK_Pin
|
|
||||||
|
|
||||||
// I2C地址
|
|
||||||
#define SSD1306_I2C_ADDRESS 0x78
|
|
||||||
// OLED显示参数
|
|
||||||
#define SSD1306_WIDTH 128
|
|
||||||
#define SSD1306_HEIGHT 64
|
|
||||||
|
|
||||||
// OLED命令定义
|
|
||||||
#define SSD1306_CMD_DISPLAY_OFF 0xAE
|
|
||||||
#define SSD1306_CMD_DISPLAY_ON 0xAF
|
|
||||||
#define SSD1306_CMD_SET_CONTRAST 0x81
|
|
||||||
#define SSD1306_CMD_DISPLAY_ALL_ON_RESUME 0xA4
|
|
||||||
#define SSD1306_CMD_DISPLAY_ALL_ON 0xA5
|
|
||||||
#define SSD1306_CMD_NORMAL_DISPLAY 0xA6
|
|
||||||
#define SSD1306_CMD_INVERT_DISPLAY 0xA7
|
|
||||||
#define SSD1306_CMD_SET_DISPLAY_OFFSET 0xD3
|
|
||||||
#define SSD1306_CMD_SET_COM_PINS 0xDA
|
|
||||||
#define SSD1306_CMD_SET_VCOM_DETECT 0xDB
|
|
||||||
#define SSD1306_CMD_SET_DISPLAY_CLOCK_DIV 0xD5
|
|
||||||
#define SSD1306_CMD_SET_PRECHARGE 0xD9
|
|
||||||
#define SSD1306_CMD_SET_MULTIPLEX 0xA8
|
|
||||||
#define SSD1306_CMD_SET_LOW_COLUMN 0x00
|
|
||||||
#define SSD1306_CMD_SET_HIGH_COLUMN 0x10
|
|
||||||
#define SSD1306_CMD_SET_START_LINE 0x40
|
|
||||||
#define SSD1306_CMD_MEMORY_MODE 0x20
|
|
||||||
#define SSD1306_CMD_COLUMN_ADDR 0x21
|
|
||||||
#define SSD1306_CMD_PAGE_ADDR 0x22
|
|
||||||
#define SSD1306_CMD_COM_SCAN_INC 0xC0
|
|
||||||
#define SSD1306_CMD_COM_SCAN_DEC 0xC8
|
|
||||||
#define SSD1306_CMD_SEG_REMAP 0xA0
|
|
||||||
#define SSD1306_CMD_CHARGE_PUMP 0x8D
|
|
||||||
#define SSD1306_CMD_SET_DC_DC_ENABLE 0x14
|
|
||||||
|
|
||||||
#define SDA_OUT() \
|
|
||||||
{ \
|
|
||||||
GPIO_SET_OUTPUT(SSD1306_SDA_PORT, SSD1306_SDA_PIN); \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define SDA_IN() \
|
|
||||||
{ \
|
|
||||||
GPIO_SET_INPUT(SSD1306_SDA_PORT, SSD1306_SDA_PIN); \
|
|
||||||
}
|
|
||||||
|
|
||||||
// 函数声明
|
|
||||||
void ssd1306_init(void);
|
|
||||||
void ssd1306_display_on(void);
|
|
||||||
void ssd1306_display_off(void);
|
|
||||||
void ssd1306_update_screen(void);
|
|
||||||
|
|
||||||
void ssd1306_fill(uint8_t color);
|
|
||||||
void ssd1306_clear(void);
|
|
||||||
void ssd1306_clear_buffer(void);
|
|
||||||
void ssd1306_draw_bmp(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1, uint8_t *bmp);
|
|
||||||
void ssd1306_f6x8_string(uint8_t x, uint8_t y, const uint8_t *ch);
|
|
||||||
void ssd1306_f6x8_string_number(uint8_t x, uint8_t y, const uint8_t *ch, uint8_t unit, float32 num);
|
|
||||||
void ssd1306_f8x16_string(uint8_t x, uint8_t y, const uint8_t *ch);
|
|
||||||
void ssd1306_f8x16_number(uint8_t x, uint8_t y, float32 num, uint8_t dot_num);
|
|
||||||
#endif // __SSD1306_OLED_H
|
|
|
@ -8,8 +8,8 @@
|
||||||
"args": [],
|
"args": [],
|
||||||
"stopAtEntry": false,
|
"stopAtEntry": false,
|
||||||
"externalConsole": true,
|
"externalConsole": true,
|
||||||
"cwd": "e:/work/stm32/epm/User/lib/flow",
|
"cwd": "e:/work/stm32/study/motor_cs103/User/system/lib/driver",
|
||||||
"program": "e:/work/stm32/epm/User/lib/flow/build/Debug/outDebug",
|
"program": "e:/work/stm32/study/motor_cs103/User/system/lib/driver/build/Debug/outDebug",
|
||||||
"MIMode": "gdb",
|
"MIMode": "gdb",
|
||||||
"miDebuggerPath": "gdb",
|
"miDebuggerPath": "gdb",
|
||||||
"setupCommands": [
|
"setupCommands": [
|
|
@ -4,7 +4,7 @@
|
||||||
"C_Cpp_Runner.debuggerPath": "gdb",
|
"C_Cpp_Runner.debuggerPath": "gdb",
|
||||||
"C_Cpp_Runner.cStandard": "",
|
"C_Cpp_Runner.cStandard": "",
|
||||||
"C_Cpp_Runner.cppStandard": "",
|
"C_Cpp_Runner.cppStandard": "",
|
||||||
"C_Cpp_Runner.msvcBatchPath": "C:/Program Files/Microsoft Visual Studio/2022/Community/VC/Auxiliary/Build/vcvarsall.bat",
|
"C_Cpp_Runner.msvcBatchPath": "C:/Program Files/Microsoft Visual Studio/VR_NR/Community/VC/Auxiliary/Build/vcvarsall.bat",
|
||||||
"C_Cpp_Runner.useMsvc": false,
|
"C_Cpp_Runner.useMsvc": false,
|
||||||
"C_Cpp_Runner.warnings": [
|
"C_Cpp_Runner.warnings": [
|
||||||
"-Wall",
|
"-Wall",
|
||||||
|
@ -54,5 +54,7 @@
|
||||||
"C_Cpp_Runner.useUndefinedSanitizer": false,
|
"C_Cpp_Runner.useUndefinedSanitizer": false,
|
||||||
"C_Cpp_Runner.useLeakSanitizer": false,
|
"C_Cpp_Runner.useLeakSanitizer": false,
|
||||||
"C_Cpp_Runner.showCompilationTime": false,
|
"C_Cpp_Runner.showCompilationTime": false,
|
||||||
"C_Cpp_Runner.useLinkTimeOptimization": false
|
"C_Cpp_Runner.useLinkTimeOptimization": false,
|
||||||
|
"C_Cpp_Runner.msvcSecureNoWarnings": false,
|
||||||
|
"C_Cpp.errorSquiggles": "disabled"
|
||||||
}
|
}
|
|
@ -65,27 +65,27 @@ void pvd_irq_handle(void)
|
||||||
*/
|
*/
|
||||||
void disable_debug_interface(void)
|
void disable_debug_interface(void)
|
||||||
{
|
{
|
||||||
// // 使能 SYSCFG 时钟
|
// // 使能 SYSCFG 时钟
|
||||||
// LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_SYSCFG);
|
// LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_SYSCFG);
|
||||||
|
|
||||||
// // 关闭调试接口
|
// // 关闭调试接口
|
||||||
// LL_DBGMCU_DisableDBGStopMode();
|
// LL_DBGMCU_DisableDBGStopMode();
|
||||||
// LL_DBGMCU_DisableDBGStandbyMode();
|
// LL_DBGMCU_DisableDBGStandbyMode();
|
||||||
// LL_DBGMCU_DisableDBGSleepMode();
|
// LL_DBGMCU_DisableDBGSleepMode();
|
||||||
|
|
||||||
// // 关闭 SWD 和 JTAG 接口
|
// // 关闭 SWD 和 JTAG 接口
|
||||||
// LL_GPIO_InitTypeDef GPIO_InitStruct = {0};
|
// LL_GPIO_InitTypeDef GPIO_InitStruct = {0};
|
||||||
|
|
||||||
// // 配置 SWDIO (PA13) 和 SWCLK (PA14) 引脚为普通 GPIO
|
// // 配置 SWDIO (PA13) 和 SWCLK (PA14) 引脚为普通 GPIO
|
||||||
// GPIO_InitStruct.Pin = LL_GPIO_PIN_13 | LL_GPIO_PIN_14;
|
// GPIO_InitStruct.Pin = LL_GPIO_PIN_13 | LL_GPIO_PIN_14;
|
||||||
// GPIO_InitStruct.Mode = LL_GPIO_MODE_ANALOG;
|
// GPIO_InitStruct.Mode = LL_GPIO_MODE_ANALOG;
|
||||||
// GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;
|
// GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;
|
||||||
// LL_GPIO_Init(GPIOA, &GPIO_InitStruct);
|
// LL_GPIO_Init(GPIOA, &GPIO_InitStruct);
|
||||||
|
|
||||||
// // 如果使用的是 JTAG 接口,还需要配置 JTDI (PA15), JTDO (PB3), 和 NJTRST (PB4) 引脚
|
// // 如果使用的是 JTAG 接口,还需要配置 JTDI (PA15), JTDO (PB3), 和 NJTRST (PB4) 引脚
|
||||||
// GPIO_InitStruct.Pin = LL_GPIO_PIN_15;
|
// GPIO_InitStruct.Pin = LL_GPIO_PIN_15;
|
||||||
// LL_GPIO_Init(GPIOA, &GPIO_InitStruct);
|
// LL_GPIO_Init(GPIOA, &GPIO_InitStruct);
|
||||||
|
|
||||||
// GPIO_InitStruct.Pin = LL_GPIO_PIN_3 | LL_GPIO_PIN_4;
|
// GPIO_InitStruct.Pin = LL_GPIO_PIN_3 | LL_GPIO_PIN_4;
|
||||||
// LL_GPIO_Init(GPIOB, &GPIO_InitStruct);
|
// LL_GPIO_Init(GPIOB, &GPIO_InitStruct);
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,14 +11,14 @@
|
||||||
*/
|
*/
|
||||||
#ifndef __BSP_H__
|
#ifndef __BSP_H__
|
||||||
#define __BSP_H__
|
#define __BSP_H__
|
||||||
|
#include "dma.h"
|
||||||
|
|
||||||
#include "gpios.h"
|
#include "gpios.h"
|
||||||
#include "adcs.h"
|
#include "adcs.h"
|
||||||
// #include "dacs.h"
|
// #include "dacs.h"
|
||||||
// #include "dmas.h"
|
|
||||||
#include "tims.h"
|
#include "tims.h"
|
||||||
// #include "pwms.h"
|
// #include "pwms.h"
|
||||||
// #include "uarts.h"
|
#include "uarts.h"
|
||||||
// #include "eeprom.h"
|
// #include "eeprom.h"
|
||||||
// #include "spis.h"
|
// #include "spis.h"
|
||||||
// #include "i2cs.h"
|
// #include "i2cs.h"
|
||||||
|
@ -29,4 +29,5 @@ typedef void (*pvd_irq_handle_cb)(void);
|
||||||
extern void pvd_configuration(uint32_t pwr_level, pvd_irq_handle_cb call); ///< Configures the Programmable Voltage Detector (PVD) module
|
extern void pvd_configuration(uint32_t pwr_level, pvd_irq_handle_cb call); ///< Configures the Programmable Voltage Detector (PVD) module
|
||||||
extern void pvd_irq_handle(void); ///< Handles the PVD interrupt
|
extern void pvd_irq_handle(void); ///< Handles the PVD interrupt
|
||||||
extern void disable_debug_interface(void); ///< Disables the debug interface
|
extern void disable_debug_interface(void); ///< Disables the debug interface
|
||||||
#endif ///< __BSP_H__
|
|
||||||
|
#endif ///< __BSP_H__
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
#ifndef __DMAS_H__
|
#ifndef __DMA_H__
|
||||||
#define __DMAS_H__
|
#define __DMA_H__
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 清除DMA传输完成标志
|
* @brief 清除DMA传输完成标志
|
||||||
|
@ -132,4 +132,4 @@
|
||||||
} \
|
} \
|
||||||
} while (__LINE__ == -1)
|
} while (__LINE__ == -1)
|
||||||
|
|
||||||
#endif // __DMAS_H__
|
#endif // __DMA_H__
|
||||||
|
|
|
@ -44,11 +44,11 @@ static uint8_t _read(gpio_t gpio)
|
||||||
/**
|
/**
|
||||||
* @brief 创建GPIO对象
|
* @brief 创建GPIO对象
|
||||||
* @param {GPIO_TypeDef} *port - GPIO寄存器指针
|
* @param {GPIO_TypeDef} *port - GPIO寄存器指针
|
||||||
* @param {uint32_t} pin - 引脚号
|
* @param {uint16_t} pin - 引脚号
|
||||||
* @return {gpio_t *} - 创建的GPIO对象指针
|
* @return {gpio_t *} - 创建的GPIO对象指针
|
||||||
* @note: 用于创建一个GPIO对象,用于操作特定端口和引脚的GPIO功能。
|
* @note: 用于创建一个GPIO对象,用于操作特定端口和引脚的GPIO功能。
|
||||||
*/
|
*/
|
||||||
gpio_t *gpio_create(GPIO_TypeDef *port, uint32_t pin)
|
gpio_t *gpio_create(GPIO_TypeDef *port, uint16_t pin)
|
||||||
{
|
{
|
||||||
gpio_t *gpio = (gpio_t *)osel_mem_alloc(sizeof(gpio_t));
|
gpio_t *gpio = (gpio_t *)osel_mem_alloc(sizeof(gpio_t));
|
||||||
DBG_ASSERT(gpio != NULL __DBG_LINE);
|
DBG_ASSERT(gpio != NULL __DBG_LINE);
|
||||||
|
|
|
@ -93,7 +93,7 @@
|
||||||
typedef struct GPIO
|
typedef struct GPIO
|
||||||
{
|
{
|
||||||
GPIO_TypeDef *port; ///< The GPIO port.
|
GPIO_TypeDef *port; ///< The GPIO port.
|
||||||
uint32_t pin; ///< The GPIO pin.
|
uint16_t pin; ///< The GPIO pin.
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Set the GPIO pin to high.
|
* @brief Set the GPIO pin to high.
|
||||||
|
@ -132,7 +132,7 @@ typedef struct GPIO
|
||||||
* @param pin The GPIO pin.
|
* @param pin The GPIO pin.
|
||||||
* @return The created GPIO pin.
|
* @return The created GPIO pin.
|
||||||
*/
|
*/
|
||||||
extern gpio_t *gpio_create(GPIO_TypeDef *port, uint32_t pin);
|
extern gpio_t *gpio_create(GPIO_TypeDef *port, uint16_t pin);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Free the memory allocated for a GPIO pin.
|
* @brief Free the memory allocated for a GPIO pin.
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
#include "pwms.h"
|
|
|
@ -39,9 +39,6 @@
|
||||||
LL_TIM_CC_DisableChannel(TIMx, CHx); \
|
LL_TIM_CC_DisableChannel(TIMx, CHx); \
|
||||||
} while (__LINE__ == -1)
|
} while (__LINE__ == -1)
|
||||||
|
|
||||||
#define PWM_GET_ARR(TIMx) LL_TIM_GetAutoReload(TIMx)
|
|
||||||
#define PWM_GET_PSC(TIMx) LL_TIM_GetPrescaler(TIMx)
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Sets the PWM frequency
|
* @brief Sets the PWM frequency
|
||||||
* @param TIMx: TIM instance
|
* @param TIMx: TIM instance
|
||||||
|
@ -90,30 +87,4 @@ static inline uint32_t PWM_GET_FREQ(TIM_TypeDef *TIMx)
|
||||||
return SystemCoreClock / (LL_TIM_GetPrescaler(TIMx) + 1) / (LL_TIM_GetAutoReload(TIMx) + 1);
|
return SystemCoreClock / (LL_TIM_GetPrescaler(TIMx) + 1) / (LL_TIM_GetAutoReload(TIMx) + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 获取指定通道的PWM比较值
|
|
||||||
*
|
|
||||||
* 根据给定的定时器指针和通道编号,获取该通道的PWM比较值。
|
|
||||||
*
|
|
||||||
* @param TIMx 定时器指针,指向一个TIM_TypeDef结构体
|
|
||||||
* @param CHx 通道编号,取值范围为LL_TIM_CHANNEL_CH1到LL_TIM_CHANNEL_CH4
|
|
||||||
*
|
|
||||||
* @return 返回一个uint16_t类型的值,表示指定通道的PWM比较值。如果通道编号无效,则返回0。
|
|
||||||
*/
|
|
||||||
static inline uint16_t PWM_GET_COMPARE(TIM_TypeDef *TIMx, uint32_t CHx)
|
|
||||||
{
|
|
||||||
switch (CHx)
|
|
||||||
{
|
|
||||||
case LL_TIM_CHANNEL_CH1:
|
|
||||||
return LL_TIM_OC_GetCompareCH1(TIMx);
|
|
||||||
case LL_TIM_CHANNEL_CH2:
|
|
||||||
return LL_TIM_OC_GetCompareCH2(TIMx);
|
|
||||||
case LL_TIM_CHANNEL_CH3:
|
|
||||||
return LL_TIM_OC_GetCompareCH3(TIMx);
|
|
||||||
case LL_TIM_CHANNEL_CH4:
|
|
||||||
return LL_TIM_OC_GetCompareCH4(TIMx);
|
|
||||||
default:
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif ///< __PWMS_H__
|
#endif ///< __PWMS_H__
|
||||||
|
|
|
@ -19,6 +19,19 @@ Given Tclk as 84MHz, we need Tout to be 200ms or 200000us. Let's assume PSC is 8
|
||||||
With these calculated values, both ARR and PSC are within the range of 0 to 65535, so we can use this parameter set.
|
With these calculated values, both ARR and PSC are within the range of 0 to 65535, so we can use this parameter set.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#define ENABLE_TIM_COUNT(TIMx) \
|
||||||
|
do \
|
||||||
|
{ \
|
||||||
|
LL_TIM_EnableCounter(TIMx); \
|
||||||
|
} while (__LINE__ == -1);
|
||||||
|
|
||||||
|
#define RESET_TIM_COUNT(TIMx) \
|
||||||
|
do \
|
||||||
|
{ \
|
||||||
|
LL_TIM_DisableCounter(TIMx); \
|
||||||
|
LL_TIM_SetCounter(TIMx, 0); \
|
||||||
|
LL_TIM_EnableCounter(TIMx); \
|
||||||
|
} while (__LINE__ == -1);
|
||||||
/**
|
/**
|
||||||
* @brief Enables the specified TIMx.
|
* @brief Enables the specified TIMx.
|
||||||
* @param TIMx TIM instance.
|
* @param TIMx TIM instance.
|
||||||
|
@ -112,5 +125,4 @@ With these calculated values, both ARR and PSC are within the range of 0 to 6553
|
||||||
* @return 返回定时器周期时间(单位:毫秒)
|
* @return 返回定时器周期时间(单位:毫秒)
|
||||||
*/
|
*/
|
||||||
#define TIM_CYCLE(TIMx) ((LL_TIM_GetAutoReload(TIMx) + 1) * 0.1)
|
#define TIM_CYCLE(TIMx) ((LL_TIM_GetAutoReload(TIMx) + 1) * 0.1)
|
||||||
|
|
||||||
#endif ///< __TIMS_H__
|
#endif ///< __TIMS_H__
|
||||||
|
|
|
@ -104,7 +104,7 @@ void uart_recv_en(uart_t *uart, BOOL rx_err_en)
|
||||||
LL_DMA_DisableChannel(uart->dma, uart->dma_rx_channel);
|
LL_DMA_DisableChannel(uart->dma, uart->dma_rx_channel);
|
||||||
|
|
||||||
// 配置RX DMA
|
// 配置RX DMA
|
||||||
LL_DMA_SetPeriphAddress(uart->dma, uart->dma_rx_channel, LL_USART_DMA_GetRegAddr(uart->huart));
|
LL_DMA_SetPeriphAddress(uart->dma, uart->dma_rx_channel, LL_USART_DMA_GetRegAddr(uart->huart, LL_USART_DMA_REG_DATA_RECEIVE));
|
||||||
LL_DMA_SetMemoryAddress(uart->dma, uart->dma_rx_channel, (uint32_t)uart->rxbuf);
|
LL_DMA_SetMemoryAddress(uart->dma, uart->dma_rx_channel, (uint32_t)uart->rxbuf);
|
||||||
LL_DMA_SetDataLength(uart->dma, uart->dma_rx_channel, uart->rxsize);
|
LL_DMA_SetDataLength(uart->dma, uart->dma_rx_channel, uart->rxsize);
|
||||||
LL_DMA_EnableIT_TC(uart->dma, uart->dma_rx_channel);
|
LL_DMA_EnableIT_TC(uart->dma, uart->dma_rx_channel);
|
||||||
|
@ -113,7 +113,7 @@ void uart_recv_en(uart_t *uart, BOOL rx_err_en)
|
||||||
LL_USART_EnableIT_IDLE(uart->huart);
|
LL_USART_EnableIT_IDLE(uart->huart);
|
||||||
|
|
||||||
// 配置TX DMA
|
// 配置TX DMA
|
||||||
LL_DMA_SetPeriphAddress(uart->dma, uart->dma_tx_channel, LL_USART_DMA_GetRegAddr(uart->huart));
|
LL_DMA_SetPeriphAddress(uart->dma, uart->dma_tx_channel, LL_USART_DMA_GetRegAddr(uart->huart, LL_USART_DMA_REG_DATA_TRANSMIT));
|
||||||
// 配置内存地址
|
// 配置内存地址
|
||||||
LL_DMA_SetMemoryAddress(uart->dma, uart->dma_tx_channel, (uint32_t)uart->txbuf);
|
LL_DMA_SetMemoryAddress(uart->dma, uart->dma_tx_channel, (uint32_t)uart->txbuf);
|
||||||
LL_DMA_EnableIT_TC(uart->dma, uart->dma_tx_channel);
|
LL_DMA_EnableIT_TC(uart->dma, uart->dma_tx_channel);
|
||||||
|
@ -178,7 +178,7 @@ void uart_free(uart_t *uart)
|
||||||
*/
|
*/
|
||||||
void uart_set_baudrate(USART_TypeDef *uart, uint32_t baudrate)
|
void uart_set_baudrate(USART_TypeDef *uart, uint32_t baudrate)
|
||||||
{
|
{
|
||||||
LL_USART_SetBaudRate(uart, SystemCoreClock, LL_USART_OVERSAMPLING_16);
|
LL_USART_SetBaudRate(uart, SystemCoreClock, LL_USART_OVERSAMPLING_16, baudrate);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
* Copyright (c) 2023 by xxx, All Rights Reserved.
|
* Copyright (c) 2023 by xxx, All Rights Reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "../inc/btn.h"
|
#include "btn.h"
|
||||||
|
|
||||||
#define EVENT_CB(ev) \
|
#define EVENT_CB(ev) \
|
||||||
if (handle->cb[ev]) \
|
if (handle->cb[ev]) \
|
|
@ -47,8 +47,8 @@ while(1) {
|
||||||
|
|
||||||
// 根据您的需求修改常量。
|
// 根据您的需求修改常量。
|
||||||
#define TICKS_INTERVAL 10 // 按钮扫描间隔,单位ms
|
#define TICKS_INTERVAL 10 // 按钮扫描间隔,单位ms
|
||||||
#define DEBOUNCE_TICKS 30 / TICKS_INTERVAL // 按键去抖动时间,单位ms
|
#define DEBOUNCE_TICKS 20 / TICKS_INTERVAL // 按键去抖动时间,单位ms
|
||||||
#define SHORT_TICKS (30 / TICKS_INTERVAL) // 短按时间阈值,单位ms
|
#define SHORT_TICKS (100 / TICKS_INTERVAL) // 短按时间阈值,单位ms
|
||||||
#define LONG_TICKS (500 / TICKS_INTERVAL) // 长按时间阈值,单位ms
|
#define LONG_TICKS (500 / TICKS_INTERVAL) // 长按时间阈值,单位ms
|
||||||
|
|
||||||
typedef void (*BtnCallback)(void *);
|
typedef void (*BtnCallback)(void *);
|
|
@ -9,6 +9,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "delay.h"
|
#include "delay.h"
|
||||||
|
|
||||||
// static uint16_t g_fac_ms = 0; // ms延时倍乘数,在os下,代表每个节拍的ms数
|
// static uint16_t g_fac_ms = 0; // ms延时倍乘数,在os下,代表每个节拍的ms数
|
||||||
static uint32_t g_fac_us = 0; /* us延时倍乘数 */
|
static uint32_t g_fac_us = 0; /* us延时倍乘数 */
|
||||||
|
|
||||||
|
@ -79,6 +80,13 @@ void delay_us(uint32_t nus)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void delay_hardware_us(TIM_TypeDef *timer_us, uint32_t us)
|
||||||
|
{
|
||||||
|
RESET_TIM_COUNT(timer_us);
|
||||||
|
while (LL_TIM_GetCounter(timer_us) < us)
|
||||||
|
; // 等待计数器达到指定值
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 延时nms
|
* @brief 延时nms
|
||||||
* @param nms: 要延时的ms数 (0< nms <= 65535)
|
* @param nms: 要延时的ms数 (0< nms <= 65535)
|
|
@ -0,0 +1,23 @@
|
||||||
|
/***
|
||||||
|
* @Author:
|
||||||
|
* @Date: 2023-04-11 18:31:07
|
||||||
|
* @LastEditors: xxx
|
||||||
|
* @LastEditTime: 2023-04-11 18:31:20
|
||||||
|
* @Description:
|
||||||
|
* @email:
|
||||||
|
* @Copyright (c) 2023 by xxx, All Rights Reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __DELAY_H
|
||||||
|
#define __DELAY_H
|
||||||
|
|
||||||
|
#include "sys.h"
|
||||||
|
#include "tims.h"
|
||||||
|
|
||||||
|
void delay_init(uint16_t sysclk); /* 初始化延迟函数 */
|
||||||
|
void delay_ms(uint16_t nms); /* 延时nms */
|
||||||
|
void delay_us(uint32_t nus); /* 延时nus */
|
||||||
|
void delay_hardware_us(TIM_TypeDef *timer_us, uint32_t us); /* 硬件延时nus */
|
||||||
|
void delay_tick(uint32_t ticks); /* 延时ticks */
|
||||||
|
|
||||||
|
#endif
|
|
@ -1,30 +1,34 @@
|
||||||
#include "dac161p997.h"
|
#include "dac161p997.h"
|
||||||
#include "delay.h"
|
#include "delay.h"
|
||||||
|
|
||||||
static dac161p997_t _handle;
|
static dac161p997_t _handle;
|
||||||
|
|
||||||
|
static void _delay_us(uint32_t us)
|
||||||
|
{
|
||||||
|
delay_hardware_us(_handle.timer_us, us);
|
||||||
|
}
|
||||||
|
|
||||||
static void dac161p997_output_0()
|
static void dac161p997_output_0()
|
||||||
{
|
{
|
||||||
_handle.io->set(*_handle.io);
|
_handle.io->set(*_handle.io);
|
||||||
delay_us(DUTY_CYCLE_25);
|
_delay_us(DUTY_CYCLE_25);
|
||||||
_handle.io->reset(*_handle.io);
|
_handle.io->reset(*_handle.io);
|
||||||
delay_us(DUTY_CYCLE_75);
|
_delay_us(DUTY_CYCLE_75);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dac161p997_output_1()
|
static void dac161p997_output_1()
|
||||||
{
|
{
|
||||||
_handle.io->set(*_handle.io);
|
_handle.io->set(*_handle.io);
|
||||||
delay_us(DUTY_CYCLE_75);
|
_delay_us(DUTY_CYCLE_75);
|
||||||
_handle.io->reset(*_handle.io);
|
_handle.io->reset(*_handle.io);
|
||||||
delay_us(DUTY_CYCLE_25);
|
_delay_us(DUTY_CYCLE_25);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dac161p997_output_d()
|
static void dac161p997_output_d()
|
||||||
{
|
{
|
||||||
_handle.io->set(*_handle.io);
|
_handle.io->set(*_handle.io);
|
||||||
delay_us(DUTY_CYCLE_50);
|
_delay_us(DUTY_CYCLE_50);
|
||||||
_handle.io->reset(*_handle.io);
|
_handle.io->reset(*_handle.io);
|
||||||
delay_us(DUTY_CYCLE_50);
|
_delay_us(DUTY_CYCLE_50);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -124,17 +128,8 @@ void dac161p997_swif_write_reg(uint16_t data, uint8_t tag)
|
||||||
*/
|
*/
|
||||||
void dac161p997_output_current(float32 current)
|
void dac161p997_output_current(float32 current)
|
||||||
{
|
{
|
||||||
uint8_t adc = (uint16_t)(current * DAC161P997_CURRENT_SLOPE) >> 8;
|
uint16_t adc = (uint16_t)(current * DAC161P997_CURRENT_SLOPE);
|
||||||
static uint8_t last_adc;
|
dac161p997_swif_write_reg(adc, DACCODE_WRITE);
|
||||||
if (adc == last_adc)
|
|
||||||
{
|
|
||||||
last_adc = adc;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
dac161p997_swif_write_reg(DAC161P997_LCK_REG_UNLOCK, CONFIG_WRITE);
|
|
||||||
dac161p997_swif_write_reg(DAC161P997_ERR_LOW_REG + adc, CONFIG_WRITE);
|
|
||||||
dac161p997_swif_write_reg(DAC161P997_LCK_REG_LOCK, CONFIG_WRITE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -147,15 +142,13 @@ void dac161p997_output_current(float32 current)
|
||||||
* 2. 配置DAC161的错误下限寄存器
|
* 2. 配置DAC161的错误下限寄存器
|
||||||
* 3. 锁定DAC161的配置寄存器
|
* 3. 锁定DAC161的配置寄存器
|
||||||
*/
|
*/
|
||||||
void dac161p997_init()
|
void dac161p997_init(TIM_TypeDef *timer_us)
|
||||||
{
|
{
|
||||||
|
DBG_ASSERT(timer_us != NULL __DBG_LINE);
|
||||||
|
_handle.timer_us = timer_us;
|
||||||
|
ENABLE_TIM_COUNT(_handle.timer_us);
|
||||||
_handle.io = gpio_create(DAC161P997_IO_PORT, DAC161P997_IO_PIN);
|
_handle.io = gpio_create(DAC161P997_IO_PORT, DAC161P997_IO_PIN);
|
||||||
dac161p997_swif_write_reg(DAC161P997_LCK_REG_UNLOCK, CONFIG_WRITE);
|
dac161p997_swif_write_reg(DAC161P997_LCK_REG + DAC161P997_LCK_REG_UNLOCK, CONFIG_WRITE);
|
||||||
dac161p997_swif_write_reg(DAC161P997_CONFIG2_REG +
|
dac161p997_swif_write_reg(DAC161P997_CONFIG2_REG, CONFIG_WRITE);
|
||||||
DAC161P997_CONFIG2_REG_LOOP +
|
dac161p997_swif_write_reg(DAC161P997_LCK_REG + DAC161P997_LCK_REG_LOCK, CONFIG_WRITE);
|
||||||
DAC161P997_CONFIG2_REG_CHANNEL +
|
|
||||||
DAC161P997_CONFIG2_REG_PARITY +
|
|
||||||
DAC161P997_CONFIG2_REG_FRAME,
|
|
||||||
CONFIG_WRITE);
|
|
||||||
dac161p997_swif_write_reg(DAC161P997_LCK_REG_LOCK, CONFIG_WRITE);
|
|
||||||
}
|
}
|
|
@ -60,15 +60,16 @@
|
||||||
#define DACCODE_20mA (0xD555)
|
#define DACCODE_20mA (0xD555)
|
||||||
#define DACCODE_24mA (0xFFFF)
|
#define DACCODE_24mA (0xFFFF)
|
||||||
|
|
||||||
// cycles
|
typedef enum
|
||||||
// #define QUARTER_CYCLES (625)
|
{
|
||||||
// #define HALF_CYCLES (1250)
|
DAC161P997_IDLE_SYM,
|
||||||
// #define THREE_CYCLES (1875)
|
|
||||||
// #define FULL_CYCLES (2500)
|
|
||||||
|
|
||||||
|
} dac161p997_e;
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
|
TIM_TypeDef *timer_us;
|
||||||
gpio_t *io;
|
gpio_t *io;
|
||||||
|
uint8_t count;
|
||||||
} dac161p997_t;
|
} dac161p997_t;
|
||||||
|
|
||||||
void dac161p997_output_0(void);
|
void dac161p997_output_0(void);
|
||||||
|
@ -76,6 +77,7 @@ void dac161p997_output_1(void);
|
||||||
void dac161p997_output_d(void);
|
void dac161p997_output_d(void);
|
||||||
void dac161p997_output_symbol(uint8_t sym);
|
void dac161p997_output_symbol(uint8_t sym);
|
||||||
void dac161p997_swif_write_reg(uint16_t data, uint8_t tag);
|
void dac161p997_swif_write_reg(uint16_t data, uint8_t tag);
|
||||||
|
|
||||||
extern void dac161p997_output_current(float32 current);
|
extern void dac161p997_output_current(float32 current);
|
||||||
extern void dac161p997_init(void);
|
extern void dac161p997_init(TIM_TypeDef *timer_us);
|
||||||
#endif
|
#endif
|
|
@ -11,7 +11,20 @@
|
||||||
#define EEPROM_LC02B_SCL_PORT I2C1_SCL_GPIO_Port
|
#define EEPROM_LC02B_SCL_PORT I2C1_SCL_GPIO_Port
|
||||||
#define EEPROM_LC02B_SCL_PIN I2C1_SCL_Pin
|
#define EEPROM_LC02B_SCL_PIN I2C1_SCL_Pin
|
||||||
|
|
||||||
static i2c_t *eeprom_24lc028bt_i2c;
|
static i2c_t *_eeprom_24lc028bt_i2c;
|
||||||
|
static TIM_TypeDef *_timer_us;
|
||||||
|
|
||||||
|
static void _delay_us(uint32_t us)
|
||||||
|
{
|
||||||
|
if (_timer_us != NULL)
|
||||||
|
{
|
||||||
|
delay_hardware_us(_timer_us, us);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
delay_us(us);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void eeprom_lc02b_test(void)
|
void eeprom_lc02b_test(void)
|
||||||
{
|
{
|
||||||
|
@ -24,7 +37,7 @@ void eeprom_lc02b_test(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
eeprom_lc02b_write(test_address, buf, TEST_SIZE);
|
eeprom_lc02b_write(test_address, buf, TEST_SIZE);
|
||||||
LL_mDelay(10);
|
_delay_us(10000);
|
||||||
osel_memset(buf, 0, ARRAY_LEN(buf));
|
osel_memset(buf, 0, ARRAY_LEN(buf));
|
||||||
eeprom_lc02b_read(test_address, buf, TEST_SIZE);
|
eeprom_lc02b_read(test_address, buf, TEST_SIZE);
|
||||||
|
|
||||||
|
@ -49,13 +62,19 @@ BOOL eeprom_lc02b_status_get(void)
|
||||||
* @return {*}
|
* @return {*}
|
||||||
* @note
|
* @note
|
||||||
*/
|
*/
|
||||||
void eeprom_lc02b_init(void)
|
void eeprom_lc02b_init(TIM_TypeDef *timer_us)
|
||||||
{
|
{
|
||||||
|
if (timer_us != NULL)
|
||||||
|
{
|
||||||
|
_timer_us = timer_us;
|
||||||
|
ENABLE_TIM_COUNT(_timer_us);
|
||||||
|
}
|
||||||
|
|
||||||
i2c_gpio_group_t gpios;
|
i2c_gpio_group_t gpios;
|
||||||
gpios.scl = gpio_create(EEPROM_LC02B_SCL_PORT, EEPROM_LC02B_SCL_PIN);
|
gpios.scl = gpio_create(EEPROM_LC02B_SCL_PORT, EEPROM_LC02B_SCL_PIN);
|
||||||
gpios.sda = gpio_create(EEPROM_LC02B_SDA_PORT, EEPROM_LC02B_SDA_PIN);
|
gpios.sda = gpio_create(EEPROM_LC02B_SDA_PORT, EEPROM_LC02B_SDA_PIN);
|
||||||
|
|
||||||
eeprom_24lc028bt_i2c = i2c_create(gpios, 10);
|
_eeprom_24lc028bt_i2c = i2c_create(gpios, 10);
|
||||||
// eeprom_lc02b_test();
|
// eeprom_lc02b_test();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -80,37 +99,37 @@ void eeprom_lc02b_dinit(void)
|
||||||
void eeprom_lc02b_write(uint32_t write_addr, uint8_t *data, uint16_t length)
|
void eeprom_lc02b_write(uint32_t write_addr, uint8_t *data, uint16_t length)
|
||||||
{
|
{
|
||||||
// 发送开始信号
|
// 发送开始信号
|
||||||
eeprom_24lc028bt_i2c->interface.start(eeprom_24lc028bt_i2c);
|
_eeprom_24lc028bt_i2c->interface.start(_eeprom_24lc028bt_i2c);
|
||||||
// 发送写入地址命令
|
// 发送写入地址命令
|
||||||
eeprom_24lc028bt_i2c->interface.write_byte(eeprom_24lc028bt_i2c, W_ADD_COM);
|
_eeprom_24lc028bt_i2c->interface.write_byte(_eeprom_24lc028bt_i2c, W_ADD_COM);
|
||||||
// 等待写入地址命令响应
|
// 等待写入地址命令响应
|
||||||
eeprom_24lc028bt_i2c->interface.wait_ack(eeprom_24lc028bt_i2c);
|
_eeprom_24lc028bt_i2c->interface.wait_ack(_eeprom_24lc028bt_i2c);
|
||||||
// 发送要写入的地址
|
// 发送要写入的地址
|
||||||
eeprom_24lc028bt_i2c->interface.write_byte(eeprom_24lc028bt_i2c, (uint8_t)write_addr);
|
_eeprom_24lc028bt_i2c->interface.write_byte(_eeprom_24lc028bt_i2c, (uint8_t)write_addr);
|
||||||
eeprom_24lc028bt_i2c->interface.wait_ack(eeprom_24lc028bt_i2c);
|
_eeprom_24lc028bt_i2c->interface.wait_ack(_eeprom_24lc028bt_i2c);
|
||||||
|
|
||||||
// 循环写入数据
|
// 循环写入数据
|
||||||
|
|
||||||
for (uint16_t i = 0; i < length; i++)
|
for (uint16_t i = 0; i < length; i++)
|
||||||
{
|
{
|
||||||
// 写入一个字节数据
|
// 写入一个字节数据
|
||||||
eeprom_24lc028bt_i2c->interface.write_byte(eeprom_24lc028bt_i2c, *data++);
|
_eeprom_24lc028bt_i2c->interface.write_byte(_eeprom_24lc028bt_i2c, *data++);
|
||||||
// 等待响应
|
// 等待响应
|
||||||
eeprom_24lc028bt_i2c->interface.wait_ack(eeprom_24lc028bt_i2c);
|
_eeprom_24lc028bt_i2c->interface.wait_ack(_eeprom_24lc028bt_i2c);
|
||||||
write_addr++;
|
write_addr++;
|
||||||
if (write_addr % PAGE_SIZE == 0)
|
if (write_addr % PAGE_SIZE == 0)
|
||||||
{
|
{
|
||||||
eeprom_24lc028bt_i2c->interface.stop(eeprom_24lc028bt_i2c);
|
_eeprom_24lc028bt_i2c->interface.stop(_eeprom_24lc028bt_i2c);
|
||||||
LL_mDelay(10); // 延时10ms,等待写入完成
|
_delay_us(10000); // 延时10ms,等待写入完成
|
||||||
eeprom_24lc028bt_i2c->interface.start(eeprom_24lc028bt_i2c);
|
_eeprom_24lc028bt_i2c->interface.start(_eeprom_24lc028bt_i2c);
|
||||||
eeprom_24lc028bt_i2c->interface.write_byte(eeprom_24lc028bt_i2c, W_ADD_COM);
|
_eeprom_24lc028bt_i2c->interface.write_byte(_eeprom_24lc028bt_i2c, W_ADD_COM);
|
||||||
eeprom_24lc028bt_i2c->interface.wait_ack(eeprom_24lc028bt_i2c);
|
_eeprom_24lc028bt_i2c->interface.wait_ack(_eeprom_24lc028bt_i2c);
|
||||||
eeprom_24lc028bt_i2c->interface.write_byte(eeprom_24lc028bt_i2c, (uint8_t)write_addr);
|
_eeprom_24lc028bt_i2c->interface.write_byte(_eeprom_24lc028bt_i2c, (uint8_t)write_addr);
|
||||||
eeprom_24lc028bt_i2c->interface.wait_ack(eeprom_24lc028bt_i2c);
|
_eeprom_24lc028bt_i2c->interface.wait_ack(_eeprom_24lc028bt_i2c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 写入完成,停止I2C总线
|
// 写入完成,停止I2C总线
|
||||||
eeprom_24lc028bt_i2c->interface.stop(eeprom_24lc028bt_i2c);
|
_eeprom_24lc028bt_i2c->interface.stop(_eeprom_24lc028bt_i2c);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -124,29 +143,29 @@ void eeprom_lc02b_write(uint32_t write_addr, uint8_t *data, uint16_t length)
|
||||||
void eeprom_lc02b_read(uint32_t read_addr, uint8_t *data, uint16_t length)
|
void eeprom_lc02b_read(uint32_t read_addr, uint8_t *data, uint16_t length)
|
||||||
{
|
{
|
||||||
// 发送开始信号
|
// 发送开始信号
|
||||||
eeprom_24lc028bt_i2c->interface.start(eeprom_24lc028bt_i2c);
|
_eeprom_24lc028bt_i2c->interface.start(_eeprom_24lc028bt_i2c);
|
||||||
// 发送写入地址命令
|
// 发送写入地址命令
|
||||||
eeprom_24lc028bt_i2c->interface.write_byte(eeprom_24lc028bt_i2c, W_ADD_COM);
|
_eeprom_24lc028bt_i2c->interface.write_byte(_eeprom_24lc028bt_i2c, W_ADD_COM);
|
||||||
// 等待写入地址命令响应
|
// 等待写入地址命令响应
|
||||||
eeprom_24lc028bt_i2c->interface.wait_ack(eeprom_24lc028bt_i2c);
|
_eeprom_24lc028bt_i2c->interface.wait_ack(_eeprom_24lc028bt_i2c);
|
||||||
|
|
||||||
// 发送要读取的地址
|
// 发送要读取的地址
|
||||||
eeprom_24lc028bt_i2c->interface.write_byte(eeprom_24lc028bt_i2c, (uint8_t)read_addr);
|
_eeprom_24lc028bt_i2c->interface.write_byte(_eeprom_24lc028bt_i2c, (uint8_t)read_addr);
|
||||||
eeprom_24lc028bt_i2c->interface.wait_ack(eeprom_24lc028bt_i2c);
|
_eeprom_24lc028bt_i2c->interface.wait_ack(_eeprom_24lc028bt_i2c);
|
||||||
|
|
||||||
// 发送开始信号
|
// 发送开始信号
|
||||||
eeprom_24lc028bt_i2c->interface.start(eeprom_24lc028bt_i2c);
|
_eeprom_24lc028bt_i2c->interface.start(_eeprom_24lc028bt_i2c);
|
||||||
// 发送读取地址命令
|
// 发送读取地址命令
|
||||||
eeprom_24lc028bt_i2c->interface.write_byte(eeprom_24lc028bt_i2c, R_ADD_COM);
|
_eeprom_24lc028bt_i2c->interface.write_byte(_eeprom_24lc028bt_i2c, R_ADD_COM);
|
||||||
// 等待读取地址命令响应
|
// 等待读取地址命令响应
|
||||||
eeprom_24lc028bt_i2c->interface.wait_ack(eeprom_24lc028bt_i2c);
|
_eeprom_24lc028bt_i2c->interface.wait_ack(_eeprom_24lc028bt_i2c);
|
||||||
// 循环读取数据
|
// 循环读取数据
|
||||||
for (uint16_t i = 0; i < length - 1; i++)
|
for (uint16_t i = 0; i < length - 1; i++)
|
||||||
{
|
{
|
||||||
// 读取一个字节数据
|
// 读取一个字节数据
|
||||||
*data++ = eeprom_24lc028bt_i2c->interface.read_byte(eeprom_24lc028bt_i2c, TRUE);
|
*data++ = _eeprom_24lc028bt_i2c->interface.read_byte(_eeprom_24lc028bt_i2c, TRUE);
|
||||||
}
|
}
|
||||||
*data++ = eeprom_24lc028bt_i2c->interface.read_byte(eeprom_24lc028bt_i2c, FALSE);
|
*data++ = _eeprom_24lc028bt_i2c->interface.read_byte(_eeprom_24lc028bt_i2c, FALSE);
|
||||||
// 停止I2C总线
|
// 停止I2C总线
|
||||||
eeprom_24lc028bt_i2c->interface.stop(eeprom_24lc028bt_i2c);
|
_eeprom_24lc028bt_i2c->interface.stop(_eeprom_24lc028bt_i2c);
|
||||||
}
|
}
|
|
@ -15,7 +15,7 @@
|
||||||
/**
|
/**
|
||||||
* @brief Initializes the LC02B EEPROM module.
|
* @brief Initializes the LC02B EEPROM module.
|
||||||
*/
|
*/
|
||||||
void eeprom_lc02b_init(void);
|
void eeprom_lc02b_init(TIM_TypeDef *timer_us);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Deinitializes the LC02B EEPROM module.
|
* @brief Deinitializes the LC02B EEPROM module.
|
|
@ -16,6 +16,19 @@
|
||||||
#define RTC_RX8010_SCL_PIN RTC_SCL_Pin
|
#define RTC_RX8010_SCL_PIN RTC_SCL_Pin
|
||||||
|
|
||||||
static i2c_t *rtc;
|
static i2c_t *rtc;
|
||||||
|
static TIM_TypeDef *_timer_us;
|
||||||
|
|
||||||
|
static void _delay_us(uint32_t us)
|
||||||
|
{
|
||||||
|
if (_timer_us != NULL)
|
||||||
|
{
|
||||||
|
delay_hardware_us(_timer_us, us);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
delay_us(us);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* sec, min, hour, week, day, month, year */
|
/* sec, min, hour, week, day, month, year */
|
||||||
// static uint8_t calendar[7] = {0, 0, 0, 1, 29, 2, 98};
|
// static uint8_t calendar[7] = {0, 0, 0, 1, 29, 2, 98};
|
||||||
|
@ -316,7 +329,7 @@ static BOOL rtc_soft_reset(void)
|
||||||
|
|
||||||
if (ret == 0)
|
if (ret == 0)
|
||||||
{
|
{
|
||||||
LL_mDelay(2);
|
_delay_us(2000);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -354,8 +367,14 @@ static BOOL rtc_clock_reginit(void)
|
||||||
* @return {BOOL} TRUE = 成功,FALSE = 失败
|
* @return {BOOL} TRUE = 成功,FALSE = 失败
|
||||||
* @note
|
* @note
|
||||||
*/
|
*/
|
||||||
BOOL rtc_init(void)
|
BOOL rtc_init(TIM_TypeDef *timer_us)
|
||||||
{
|
{
|
||||||
|
if (timer_us != NULL)
|
||||||
|
{
|
||||||
|
_timer_us = timer_us;
|
||||||
|
ENABLE_TIM_COUNT(_timer_us);
|
||||||
|
}
|
||||||
|
|
||||||
i2c_gpio_group_t gpios;
|
i2c_gpio_group_t gpios;
|
||||||
int ret = 1;
|
int ret = 1;
|
||||||
gpios.scl = gpio_create(RTC_RX8010_SCL_PORT, RTC_RX8010_SCL_PIN);
|
gpios.scl = gpio_create(RTC_RX8010_SCL_PORT, RTC_RX8010_SCL_PIN);
|
|
@ -57,7 +57,7 @@ typedef struct
|
||||||
* @brief Initializes the RTC module.
|
* @brief Initializes the RTC module.
|
||||||
* @return TRUE if the initialization is successful, FALSE otherwise.
|
* @return TRUE if the initialization is successful, FALSE otherwise.
|
||||||
*/
|
*/
|
||||||
extern BOOL rtc_init(void);
|
extern BOOL rtc_init(TIM_TypeDef *timer_us);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Deinitializes the RTC module.
|
* @brief Deinitializes the RTC module.
|
|
@ -1,5 +1,6 @@
|
||||||
#include "sht40.h"
|
#include "sht40.h"
|
||||||
#include "i2cs.h"
|
#include "i2cs.h"
|
||||||
|
#include "delay.h"
|
||||||
#define SHT40_SDA_PORT I2C1_SDA_GPIO_Port
|
#define SHT40_SDA_PORT I2C1_SDA_GPIO_Port
|
||||||
#define SHT40_SDA_PIN I2C1_SDA_Pin
|
#define SHT40_SDA_PIN I2C1_SDA_Pin
|
||||||
#define SHT40_SCL_PORT I2C1_SCL_GPIO_Port
|
#define SHT40_SCL_PORT I2C1_SCL_GPIO_Port
|
||||||
|
@ -8,9 +9,22 @@
|
||||||
#define SHT40_I2C_ADDRESS 0x44
|
#define SHT40_I2C_ADDRESS 0x44
|
||||||
#define SHT40_MEASURE_CMD 0xFD // 2*8-bit T-data:8-bit CRC:2*8-bit RH-data: 8-bit CRC
|
#define SHT40_MEASURE_CMD 0xFD // 2*8-bit T-data:8-bit CRC:2*8-bit RH-data: 8-bit CRC
|
||||||
|
|
||||||
static i2c_t *sht40_i2c;
|
static i2c_t *_sht40_i2c;
|
||||||
|
static TIM_TypeDef *_timer_us;
|
||||||
static uint8_t crc8(uint8_t *data, uint8_t len);
|
static uint8_t crc8(uint8_t *data, uint8_t len);
|
||||||
|
|
||||||
|
static void _delay_us(uint32_t us)
|
||||||
|
{
|
||||||
|
if (_timer_us != NULL)
|
||||||
|
{
|
||||||
|
delay_hardware_us(_timer_us, us);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
delay_us(us);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void sht40_test(void)
|
void sht40_test(void)
|
||||||
{
|
{
|
||||||
float32 temperature = 0;
|
float32 temperature = 0;
|
||||||
|
@ -26,14 +40,21 @@ void sht40_test(void)
|
||||||
*
|
*
|
||||||
* 初始化完成后,sht40_i2c 变量将用于后续的 SHT40 传感器通信。
|
* 初始化完成后,sht40_i2c 变量将用于后续的 SHT40 传感器通信。
|
||||||
*/
|
*/
|
||||||
void sht40_init(void)
|
void sht40_init(TIM_TypeDef *timer_us)
|
||||||
{
|
{
|
||||||
|
DBG_ASSERT(timer_us != NULL __DBG_LINE);
|
||||||
|
if (timer_us != NULL)
|
||||||
|
{
|
||||||
|
_timer_us = timer_us;
|
||||||
|
ENABLE_TIM_COUNT(_timer_us);
|
||||||
|
}
|
||||||
|
|
||||||
i2c_gpio_group_t gpios;
|
i2c_gpio_group_t gpios;
|
||||||
gpios.scl = gpio_create(SHT40_SCL_PORT, SHT40_SCL_PIN);
|
gpios.scl = gpio_create(SHT40_SCL_PORT, SHT40_SCL_PIN);
|
||||||
gpios.sda = gpio_create(SHT40_SDA_PORT, SHT40_SDA_PIN);
|
gpios.sda = gpio_create(SHT40_SDA_PORT, SHT40_SDA_PIN);
|
||||||
|
|
||||||
sht40_i2c = i2c_create(gpios, 10);
|
_sht40_i2c = i2c_create(gpios, 10);
|
||||||
DBG_ASSERT(sht40_i2c != NULL __DBG_LINE);
|
DBG_ASSERT(_sht40_i2c != NULL __DBG_LINE);
|
||||||
|
|
||||||
// sht40_test(); // 测试 SHT40
|
// sht40_test(); // 测试 SHT40
|
||||||
}
|
}
|
||||||
|
@ -65,32 +86,32 @@ BOOL sht40_read(float32 *temperature, float32 *humidity)
|
||||||
|
|
||||||
osel_memset(data, 0, ARRAY_LEN(data));
|
osel_memset(data, 0, ARRAY_LEN(data));
|
||||||
// 发送开始信号
|
// 发送开始信号
|
||||||
sht40_i2c->interface.start(sht40_i2c);
|
_sht40_i2c->interface.start(_sht40_i2c);
|
||||||
// 发送写入地址命令
|
// 发送写入地址命令
|
||||||
sht40_i2c->interface.write_byte(sht40_i2c, SHT40_I2C_ADDRESS << 1);
|
_sht40_i2c->interface.write_byte(_sht40_i2c, SHT40_I2C_ADDRESS << 1);
|
||||||
// 等待写入地址命令响应
|
// 等待写入地址命令响应
|
||||||
if (sht40_i2c->interface.wait_ack(sht40_i2c) == FALSE)
|
if (_sht40_i2c->interface.wait_ack(_sht40_i2c) == FALSE)
|
||||||
{
|
{
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
// 发送测量命令
|
// 发送测量命令
|
||||||
sht40_i2c->interface.write_byte(sht40_i2c, SHT40_MEASURE_CMD);
|
_sht40_i2c->interface.write_byte(_sht40_i2c, SHT40_MEASURE_CMD);
|
||||||
// 等待测量命令响应
|
// 等待测量命令响应
|
||||||
if (sht40_i2c->interface.wait_ack(sht40_i2c) == FALSE)
|
if (_sht40_i2c->interface.wait_ack(_sht40_i2c) == FALSE)
|
||||||
{
|
{
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
// 停止I2C总线
|
// 停止I2C总线
|
||||||
sht40_i2c->interface.stop(sht40_i2c);
|
_sht40_i2c->interface.stop(_sht40_i2c);
|
||||||
|
|
||||||
LL_mDelay(10); // 根据 SHT40 数据手册,等待至少 10ms
|
_delay_us(10000); // 根据 SHT40 数据手册,等待至少 10ms
|
||||||
|
|
||||||
// 发送开始信号
|
// 发送开始信号
|
||||||
sht40_i2c->interface.start(sht40_i2c);
|
_sht40_i2c->interface.start(_sht40_i2c);
|
||||||
// 发送写入地址命令
|
// 发送写入地址命令
|
||||||
sht40_i2c->interface.write_byte(sht40_i2c, (SHT40_I2C_ADDRESS << 1) | 1);
|
_sht40_i2c->interface.write_byte(_sht40_i2c, (SHT40_I2C_ADDRESS << 1) | 1);
|
||||||
// 等待写入地址命令响应
|
// 等待写入地址命令响应
|
||||||
if (sht40_i2c->interface.wait_ack(sht40_i2c) == FALSE)
|
if (_sht40_i2c->interface.wait_ack(_sht40_i2c) == FALSE)
|
||||||
{
|
{
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
@ -99,16 +120,16 @@ BOOL sht40_read(float32 *temperature, float32 *humidity)
|
||||||
{
|
{
|
||||||
if (i == 5)
|
if (i == 5)
|
||||||
{
|
{
|
||||||
data[i] = sht40_i2c->interface.read_byte(sht40_i2c, FALSE);
|
data[i] = _sht40_i2c->interface.read_byte(_sht40_i2c, FALSE);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
data[i] = sht40_i2c->interface.read_byte(sht40_i2c, TRUE);
|
data[i] = _sht40_i2c->interface.read_byte(_sht40_i2c, TRUE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 停止I2C总线
|
// 停止I2C总线
|
||||||
sht40_i2c->interface.stop(sht40_i2c);
|
_sht40_i2c->interface.stop(_sht40_i2c);
|
||||||
|
|
||||||
*temperature = 0;
|
*temperature = 0;
|
||||||
*humidity = 0;
|
*humidity = 0;
|
|
@ -2,7 +2,7 @@
|
||||||
#define __SHT40_H
|
#define __SHT40_H
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
|
|
||||||
void sht40_init(void); ///< 初始化 SHT40 传感器
|
void sht40_init(TIM_TypeDef *timer_us); ///< 初始化 SHT40 传感器
|
||||||
void sht40_dinit(void); ///< 反初始化 SHT40 传感器
|
void sht40_dinit(void); ///< 反初始化 SHT40 传感器
|
||||||
BOOL sht40_read(float32 *temperature, float32 *humidity); ///< 读取温湿度传感器数据
|
BOOL sht40_read(float32 *temperature, float32 *humidity); ///< 读取温湿度传感器数据
|
||||||
|
|
|
@ -1,21 +0,0 @@
|
||||||
/***
|
|
||||||
* @Author:
|
|
||||||
* @Date: 2023-04-11 18:31:07
|
|
||||||
* @LastEditors: xxx
|
|
||||||
* @LastEditTime: 2023-04-11 18:31:20
|
|
||||||
* @Description:
|
|
||||||
* @email:
|
|
||||||
* @Copyright (c) 2023 by xxx, All Rights Reserved.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef __DELAY_H
|
|
||||||
#define __DELAY_H
|
|
||||||
|
|
||||||
#include "sys.h"
|
|
||||||
|
|
||||||
void delay_init(uint16_t sysclk); /* 初始化延迟函数 */
|
|
||||||
void delay_ms(uint16_t nms); /* 延时nms */
|
|
||||||
void delay_us(uint32_t nus); /* 延时nus */
|
|
||||||
void delay_tick(uint32_t ticks); /* 延时ticks */
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
#include "pid_c.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 设置PID控制器参数
|
||||||
|
* @param {PID_C} *self - PID控制器结构体指针
|
||||||
|
* @param {float32} kp - 比例系数
|
||||||
|
* @param {float32} ki - 积分系数
|
||||||
|
* @param {float32} kd - 微分系数
|
||||||
|
* @param {float32} out_min - 最小输出
|
||||||
|
* @param {float32} out_max - 最大输出
|
||||||
|
* @return {*} - 空
|
||||||
|
*/
|
||||||
|
static void _set_ctrl_prm(struct PID_C *self, float32 kp, float32 ki, float32 kd, float32 out_min, float32 out_max)
|
||||||
|
{
|
||||||
|
self->pri.kp = kp; /*比例系数*/
|
||||||
|
self->pri.ki = ki; /*积分系数*/
|
||||||
|
self->pri.kd = kd; /*微分系数*/
|
||||||
|
|
||||||
|
self->pri.deadband = 0.5; /*死区*/
|
||||||
|
self->pri.maximum = out_max; /*最大输出*/
|
||||||
|
self->pri.minimum = out_min; /*最小输出*/
|
||||||
|
self->pri.last_error = 0; /*上一次误差*/
|
||||||
|
self->pri.prev_error = 0; /*上上次误差*/
|
||||||
|
}
|
||||||
|
|
||||||
|
static float32 _PID(struct PID_C *self, float32 target, float32 feedback)
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 实现PID算法
|
||||||
|
*/
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void pid_c_constructor(struct PID_C *self)
|
||||||
|
{
|
||||||
|
self->set_ctrl_prm = _set_ctrl_prm;
|
||||||
|
self->PID = _PID;
|
||||||
|
}
|
|
@ -0,0 +1,34 @@
|
||||||
|
#ifndef __PID_C_H__
|
||||||
|
#define __PID_C_H__
|
||||||
|
#include "lib.h"
|
||||||
|
|
||||||
|
typedef struct PID_C
|
||||||
|
{
|
||||||
|
/* 设置PID三个参数 */
|
||||||
|
void (*set_ctrl_prm)(struct PID_C *self, float32 kp, float32 ki, float32 kd, float32 out_min, float32 out_max);
|
||||||
|
/* 控制接口 */
|
||||||
|
float32 (*PID)(struct PID_C *self, float32 target, float32 feedback);
|
||||||
|
|
||||||
|
// 自定义参数
|
||||||
|
/* 实际值与目标值之间的误差 */
|
||||||
|
float32 err;
|
||||||
|
/* 输出值 */
|
||||||
|
float32 out;
|
||||||
|
/* private */
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
float32 kp; /*比例学习速度*/
|
||||||
|
float32 ki; /*积分学习速度*/
|
||||||
|
float32 kd; /*微分学习速度*/
|
||||||
|
float32 ki_error; /*积分误差*/
|
||||||
|
float32 last_error; /*前一拍偏差*/
|
||||||
|
float32 prev_error; /*前两拍偏差*/
|
||||||
|
float32 deadband; /*死区*/
|
||||||
|
float32 maximum; /*输出值的上限*/
|
||||||
|
float32 minimum; /*输出值的下限*/
|
||||||
|
} pri;
|
||||||
|
} pid_c_t;
|
||||||
|
|
||||||
|
extern void pid_c_constructor(struct PID_C *self);
|
||||||
|
|
||||||
|
#endif // __PID_C_H__
|
|
@ -0,0 +1,285 @@
|
||||||
|
#include "pid_g.h"
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 复位PID积分及微分控制数据
|
||||||
|
* @param {PID_G} *self
|
||||||
|
* @return {*}
|
||||||
|
*/
|
||||||
|
static void _restctrl(struct PID_G *self)
|
||||||
|
{
|
||||||
|
self->pri.pre_error = 0;
|
||||||
|
self->pri.sum_iterm = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 更新控制区间
|
||||||
|
* @param {PID_G} *self
|
||||||
|
* @param {float32} out_min
|
||||||
|
* @param {float32} out_max
|
||||||
|
* @return {*}
|
||||||
|
* @note
|
||||||
|
*/
|
||||||
|
static void _set_range(struct PID_G *self, float32 out_min, float32 out_max)
|
||||||
|
{
|
||||||
|
self->pri.out_max = out_max;
|
||||||
|
self->pri.out_min = out_min;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 更新kp
|
||||||
|
* @param {PID_G} *self
|
||||||
|
* @param {float32} kp
|
||||||
|
* @return {*}
|
||||||
|
* @note
|
||||||
|
*/
|
||||||
|
static void _set_kp(struct PID_G *self, float32 kp)
|
||||||
|
{
|
||||||
|
self->pri.kp = kp;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 更新ki
|
||||||
|
* @param {PID_G} *self
|
||||||
|
* @param {float32} ki
|
||||||
|
* @return {*}
|
||||||
|
* @note
|
||||||
|
*/
|
||||||
|
static void _set_ki(struct PID_G *self, float32 ki)
|
||||||
|
{
|
||||||
|
self->pri.ki = ki;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 更新kd
|
||||||
|
* @param {PID_G} *self
|
||||||
|
* @param {float32} kd
|
||||||
|
* @return {*}
|
||||||
|
* @note
|
||||||
|
*/
|
||||||
|
static void _set_kd(struct PID_G *self, float32 kd)
|
||||||
|
{
|
||||||
|
self->pri.kd = kd;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 使能积分控制
|
||||||
|
* @param {PID_G} *self
|
||||||
|
* @param {BOOL} enable
|
||||||
|
* @return {*}
|
||||||
|
* @note
|
||||||
|
*/
|
||||||
|
static void _set_ki_enable(struct PID_G *self, BOOL enable)
|
||||||
|
{
|
||||||
|
self->pri.ki_enable = enable;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 使能微分控制
|
||||||
|
* @param {PID_G} *self
|
||||||
|
* @param {BOOL} enable
|
||||||
|
* @return {*}
|
||||||
|
* @note
|
||||||
|
*/
|
||||||
|
static void _set_kd_enable(struct PID_G *self, BOOL enable)
|
||||||
|
{
|
||||||
|
self->pri.kd_enable = enable;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 初始化控制参数
|
||||||
|
* @return {*}
|
||||||
|
* @note
|
||||||
|
*/
|
||||||
|
static void _set_ctrl_prm(struct PID_G *self, float32 kp, float32 ki, float32 kd, float32 err_dead, float32 out_min, float32 out_max)
|
||||||
|
{
|
||||||
|
g_param_t *pri = &self->pri;
|
||||||
|
osel_memset((uint8_t *)pri, 0, sizeof(pid_g_t));
|
||||||
|
pri->kp = kp;
|
||||||
|
pri->ki = ki;
|
||||||
|
pri->kd = kd;
|
||||||
|
pri->err_dead = err_dead;
|
||||||
|
pri->out_max = out_max;
|
||||||
|
pri->out_min = out_min;
|
||||||
|
pri->detach = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _update_ctrl_prm(struct PID_G *self, float32 kp, float32 ki, float32 kd, float32 err_dead, float32 out_min, float32 out_max)
|
||||||
|
{
|
||||||
|
g_param_t *pri = &self->pri;
|
||||||
|
pri->kp = kp;
|
||||||
|
pri->ki = ki;
|
||||||
|
pri->kd = kd;
|
||||||
|
pri->err_dead = err_dead;
|
||||||
|
pri->out_max = out_max;
|
||||||
|
pri->out_min = out_min;
|
||||||
|
pri->detach = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 非0时配置为积分分离+抗积分饱和PID,否则为普通抗积分饱和PID
|
||||||
|
* @param {PID_G} *self
|
||||||
|
* @param {float32} max_err
|
||||||
|
* @param {BOOL} mode
|
||||||
|
* @return {*}
|
||||||
|
*/
|
||||||
|
static void _set_cfg(struct PID_G *self, float32 max_err, BOOL mode)
|
||||||
|
{
|
||||||
|
self->pri.err_limit = max_err;
|
||||||
|
self->pri.detach = mode == FALSE ? FALSE : TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 设置积分权重
|
||||||
|
* @param {PID_G} *self
|
||||||
|
* @param {float32} max_weight
|
||||||
|
* @return {*}
|
||||||
|
* @note
|
||||||
|
*/
|
||||||
|
static void _set_weight(struct PID_G *self, float32 max_ratio, BOOL mode)
|
||||||
|
{
|
||||||
|
self->pri.ui_ratio = max_ratio;
|
||||||
|
self->pri.weight = mode == FALSE ? FALSE : TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief PID算法函数
|
||||||
|
* @param {PID_G} *self
|
||||||
|
* @param {float32} target 目标位置
|
||||||
|
* @param {float32} feedback 实际位置
|
||||||
|
* @return {*}
|
||||||
|
* @note
|
||||||
|
*/
|
||||||
|
static float32 _PID(struct PID_G *self, float32 target, float32 feedback)
|
||||||
|
{
|
||||||
|
float32 error = 0.0f;
|
||||||
|
float32 insert = 0.0f; ///< 该值为0时积分不介入计算
|
||||||
|
float32 temp_iterm = 0.0f;
|
||||||
|
float32 temp_kd = 0.0f;
|
||||||
|
|
||||||
|
g_param_t *pri = &self->pri;
|
||||||
|
|
||||||
|
pri->ref = target; ///< 目标位置
|
||||||
|
pri->feed_back = feedback; ///< 实际位置
|
||||||
|
pri->error = pri->ref - pri->feed_back; /// 误差
|
||||||
|
error = pri->error;
|
||||||
|
if (fabs(pri->error) <= pri->err_dead) ///< 误差小于死区,不计算
|
||||||
|
{
|
||||||
|
error = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*根据PID配置的模式,获取积分数据,进行积分累加*/
|
||||||
|
if (pri->out >= pri->out_max) ///< 到达输出上限
|
||||||
|
{
|
||||||
|
if (fabs(error) > pri->err_limit && pri->detach) ///< 误差大于积分介入区间,积分不介入计算
|
||||||
|
{
|
||||||
|
insert = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
insert = 1;
|
||||||
|
if (error < 0)
|
||||||
|
{
|
||||||
|
temp_iterm = pri->ki * error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (pri->out <= pri->out_min) ///< 到达输出下限
|
||||||
|
{
|
||||||
|
if (fabs(error) > pri->err_limit && pri->detach) ///< 误差大于积分介入区间,积分不介入计算
|
||||||
|
{
|
||||||
|
insert = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
insert = 1;
|
||||||
|
if (error > 0)
|
||||||
|
{
|
||||||
|
temp_iterm = pri->ki * error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (fabs(error) > pri->err_limit && pri->detach)
|
||||||
|
{
|
||||||
|
insert = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
insert = 1;
|
||||||
|
temp_iterm = pri->ki * error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (pri->ki_enable == FALSE)
|
||||||
|
{
|
||||||
|
temp_iterm = 0;
|
||||||
|
insert = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* integral */
|
||||||
|
pri->sum_iterm += temp_iterm;
|
||||||
|
|
||||||
|
if (pri->weight == TRUE)
|
||||||
|
{
|
||||||
|
if (pri->sum_iterm > pri->ui_ratio)
|
||||||
|
{
|
||||||
|
pri->sum_iterm = pri->ui_ratio;
|
||||||
|
}
|
||||||
|
else if (pri->sum_iterm < -pri->ui_ratio)
|
||||||
|
{
|
||||||
|
pri->sum_iterm = -pri->ui_ratio;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (pri->sum_iterm > pri->out_max)
|
||||||
|
{
|
||||||
|
pri->sum_iterm = pri->out_max;
|
||||||
|
}
|
||||||
|
else if (pri->sum_iterm < pri->out_min)
|
||||||
|
{
|
||||||
|
pri->sum_iterm = pri->out_min;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* differential */
|
||||||
|
if (pri->kd_enable == TRUE)
|
||||||
|
{
|
||||||
|
temp_kd = pri->kd;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
temp_kd = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
pri->out = pri->kp * pri->error + pri->sum_iterm * insert + (pri->error - pri->pre_error) * temp_kd;
|
||||||
|
pri->pre_error = pri->error; ///< 记录这次误差,为下次微分计算做准备
|
||||||
|
pri->pre_feed_back = pri->feed_back;
|
||||||
|
|
||||||
|
/*limt pid output*/
|
||||||
|
pri->out = RANGE(pri->out, pri->out_min, pri->out_max); ///< 限制输出
|
||||||
|
return pri->out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief PID接口
|
||||||
|
* @param {PID_G} *self
|
||||||
|
* @return {*}
|
||||||
|
* @note
|
||||||
|
*/
|
||||||
|
void pid_g_constructor(struct PID_G *self)
|
||||||
|
{
|
||||||
|
self->set_ctrl_prm = _set_ctrl_prm;
|
||||||
|
self->update_ctrl_prm = _update_ctrl_prm;
|
||||||
|
self->set_cfg = _set_cfg;
|
||||||
|
self->set_kp = _set_kp;
|
||||||
|
self->set_ki_enable = _set_ki_enable;
|
||||||
|
self->set_ki = _set_ki;
|
||||||
|
self->set_kd_enable = _set_kd_enable;
|
||||||
|
self->set_kd = _set_kd;
|
||||||
|
self->set_range = _set_range;
|
||||||
|
self->restctrl = _restctrl;
|
||||||
|
self->PID = _PID;
|
||||||
|
self->set_weight = _set_weight;
|
||||||
|
}
|
|
@ -0,0 +1,65 @@
|
||||||
|
#ifndef __PID_G_H__
|
||||||
|
#define __PID_G_H__
|
||||||
|
#include "lib.h"
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
float32 ref; /*目标*/
|
||||||
|
float32 feed_back; /*实际*/
|
||||||
|
float32 pre_feed_back; /*上一次实际*/
|
||||||
|
float32 kp; /*比例学习速度*/
|
||||||
|
float32 ki; /*积分学习速度*/
|
||||||
|
float32 kd; /*微分学习速度*/
|
||||||
|
float32 ki_error; /*积分误差*/
|
||||||
|
float32 error; /*误差*/
|
||||||
|
float32 pre_error; /*前一拍偏差*/
|
||||||
|
float32 prev_error; /*前两拍偏差*/
|
||||||
|
float32 err_dead; /*死区*/
|
||||||
|
float32 err_limit; /*积分分离上限*/
|
||||||
|
float32 maximum; /*输出值的上限*/
|
||||||
|
float32 minimum; /*输出值的下限*/
|
||||||
|
float32 out; /*输出值*/
|
||||||
|
float32 sum_iterm; /*积分累加*/
|
||||||
|
float32 ui_ratio; /*积分权重*/
|
||||||
|
BOOL ki_enable; /*积分使能*/
|
||||||
|
BOOL kd_enable; /*微分使能*/
|
||||||
|
BOOL detach; /*积分分离标志*/
|
||||||
|
BOOL weight; /*积分权重标志*/
|
||||||
|
float32 out_max; /*输出最大值*/
|
||||||
|
float32 out_min; /*输出最小值*/
|
||||||
|
} g_param_t;
|
||||||
|
|
||||||
|
typedef struct PID_G
|
||||||
|
{
|
||||||
|
/* 设置PID三个参数 */
|
||||||
|
void (*set_ctrl_prm)(struct PID_G *self, float32 kp, float32 ki, float32 kd, float32 err_dead, float32 out_min, float32 out_max);
|
||||||
|
/* 更新PID参数 */
|
||||||
|
void (*update_ctrl_prm)(struct PID_G *self, float32 kp, float32 ki, float32 kd, float32 err_dead, float32 out_min, float32 out_max);
|
||||||
|
/* 控制接口 */
|
||||||
|
float32 (*PID)(struct PID_G *self, float32 target, float32 feedback);
|
||||||
|
/* 更新控制区间 */
|
||||||
|
void (*set_range)(struct PID_G *self, float32 out_min, float32 out_max);
|
||||||
|
/* 设置积分分离 */
|
||||||
|
void (*set_cfg)(struct PID_G *self, float32 max_err, BOOL mode);
|
||||||
|
/* 设置积分权重 */
|
||||||
|
void (*set_weight)(struct PID_G *self, float32 max_ratio, BOOL mode);
|
||||||
|
/* 更新kp */
|
||||||
|
void (*set_kp)(struct PID_G *self, float32 kp);
|
||||||
|
/* 使能ki */
|
||||||
|
void (*set_ki_enable)(struct PID_G *self, BOOL enable);
|
||||||
|
/* 更新ki */
|
||||||
|
void (*set_ki)(struct PID_G *self, float32 ki);
|
||||||
|
/* 使能kd */
|
||||||
|
void (*set_kd_enable)(struct PID_G *self, BOOL enable);
|
||||||
|
/* 更新kd */
|
||||||
|
void (*set_kd)(struct PID_G *self, float32 kd);
|
||||||
|
/* 复位PID积分及微分控制数据 */
|
||||||
|
void (*restctrl)(struct PID_G *self);
|
||||||
|
|
||||||
|
/* private */
|
||||||
|
g_param_t pri;
|
||||||
|
|
||||||
|
} pid_g_t;
|
||||||
|
|
||||||
|
extern void pid_g_constructor(struct PID_G *self);
|
||||||
|
#endif // __PID_G_H__
|
|
@ -0,0 +1,166 @@
|
||||||
|
#include "pid_hd.h"
|
||||||
|
#include <math.h>
|
||||||
|
#include "sys.h"
|
||||||
|
#include "app.h"
|
||||||
|
|
||||||
|
#if INCOMPLETE_DIFFEREN_HD == 1 // 积分分离
|
||||||
|
/*计算微分项,使用追随误差微分项*/
|
||||||
|
static float32 td_derivative(struct PID_HD *self, float32 current_err, float32 pre_err, float32 dt)
|
||||||
|
{
|
||||||
|
pid_hd_position_t *pri = &self->pri_u.position;
|
||||||
|
float32 derivative = (current_err - pre_err) / dt; // 计算积分项
|
||||||
|
derivative = pri->td_alpha * derivative + (1 - pri->td_alpha) * pri->td_beta * pri->pre_derivative; // 追随误差微分器平滑输出
|
||||||
|
pri->pre_derivative = derivative; // 更新上一次误差
|
||||||
|
return derivative;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*杭电:设置位置式PID参数*/
|
||||||
|
static void _set_ctrl_prm_position(struct PID_HD *self, float32 kp, float32 ki, float32 kd)
|
||||||
|
{
|
||||||
|
pid_hd_position_t *pri = &self->pri_u.position;
|
||||||
|
osel_memset((uint8_t *)pri, 0, sizeof(pid_hd_position_t));
|
||||||
|
|
||||||
|
/*观测传进来的Kp、Ki、Kd*/
|
||||||
|
|
||||||
|
pri->kp = kp;
|
||||||
|
pri->ki = ki;
|
||||||
|
pri->kd = kd;
|
||||||
|
pri->ki_limit = 10; // 积分分离界限
|
||||||
|
pri->err_dead = 0.5; // 控制死区范围
|
||||||
|
#if INCOMPLETE_DIFFEREN_HD == 1
|
||||||
|
/*不完全微分系数*/
|
||||||
|
pri->td_alpha = 0.5;
|
||||||
|
pri->td_beta = 0.5;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/*杭电:设置输出限幅参数*/
|
||||||
|
static void _set_out_prm_position(struct PID_HD *self, float32 maximum, float32 minimum)
|
||||||
|
{
|
||||||
|
self->pri_u.position.out_max = maximum;
|
||||||
|
self->pri_u.position.out_min = minimum;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*杭电:位置式PID控制算法*/
|
||||||
|
static float32 _pid_position(struct PID_HD *self, float32 err)
|
||||||
|
{
|
||||||
|
/*计算控制的运行时间*/
|
||||||
|
// sys_millis_reset();
|
||||||
|
self->pri_u.position.control_time = sys_millis();
|
||||||
|
self->pri_u.position.tmp_time = 0;
|
||||||
|
|
||||||
|
/*测试:4.18*/
|
||||||
|
if (fabs(err) < 0.1)
|
||||||
|
{
|
||||||
|
err = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
float32 x[3];
|
||||||
|
self->pri_u.position.err = err;
|
||||||
|
|
||||||
|
/*抗积分饱和*/
|
||||||
|
#if INTEGRAL_SEPARATION == 1 // 积分分离
|
||||||
|
if (self->pri_u.position.out > self->pri_u.position.out_max)
|
||||||
|
{
|
||||||
|
if (self->pri_u.position.err > self->pri_u.position.ki_limit) // 积分分离
|
||||||
|
{
|
||||||
|
self->pri_u.position.ki_error += 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (self->pri_u.position.err < 0) // 若偏差为负值,执行负偏差的累加
|
||||||
|
{
|
||||||
|
self->pri_u.position.ki_error += self->pri_u.position.err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (self->pri_u.position.out < self->pri_u.position.out_min)
|
||||||
|
{
|
||||||
|
if (self->pri_u.position.err > self->pri_u.position.ki_limit) // 若偏差为负值,停止积分
|
||||||
|
{
|
||||||
|
self->pri_u.position.ki_error += 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (self->pri_u.position.err > 0) // 若偏差为正值,执行正偏差的累加
|
||||||
|
{
|
||||||
|
self->pri_u.position.ki_error += self->pri_u.position.err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (fabs(err) > self->pri_u.position.ki_limit || fabs(err) < 0.5)
|
||||||
|
{
|
||||||
|
self->pri_u.position.ki_error += 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
self->pri_u.position.ki_error += self->pri_u.position.err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else /*无积分分离操作*/
|
||||||
|
if (fabs(err) < 0.4)
|
||||||
|
{
|
||||||
|
self->pri_u.position.ki_error += 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
self->pri_u.position.ki_error += self->pri_u.position.err;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*输出*/
|
||||||
|
if (fabs(err) < self->pri_u.position.err_dead)
|
||||||
|
{
|
||||||
|
/*输出上一次的值*/
|
||||||
|
// self->pri_u.position.out = self->pri_u.position.pre_out;
|
||||||
|
x[0] = self->pri_u.position.err;
|
||||||
|
x[1] = self->pri_u.position.ki_error;
|
||||||
|
self->pri_u.position.out = self->pri_u.position.kp * x[0] + self->pri_u.position.ki * x[1] + self->pri_u.position.kd * x[2];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
x[0] = self->pri_u.position.err;
|
||||||
|
x[1] = self->pri_u.position.ki_error;
|
||||||
|
|
||||||
|
#if INCOMPLETE_DIFFEREN_HD == 1
|
||||||
|
/*不完全微分项,为了解决普通PID为微分环节容易振荡的问题*/
|
||||||
|
self->pri_u.position.tmp_time = sys_millis();
|
||||||
|
self->pri_u.position.control_time -= self->pri_u.position.tmp_time;
|
||||||
|
self->pri_u.position.control_time /= 1000.0; // 将单位转换为秒
|
||||||
|
x[2] = td_derivative(&_pid.pid_u.hd, err, self->pri_u.position.pre_error, self->pri_u.position.control_time);
|
||||||
|
#else
|
||||||
|
// 普通的微分环节
|
||||||
|
x[2] = self->pri_u.position.err - self->pri_u.position.pre_error;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
self->pri_u.position.out = self->pri_u.position.kp * x[0] + self->pri_u.position.ki * x[1] + self->pri_u.position.kd * x[2];
|
||||||
|
}
|
||||||
|
|
||||||
|
/*输出限幅*/
|
||||||
|
if (self->pri_u.position.out > self->pri_u.position.out_max)
|
||||||
|
{
|
||||||
|
self->pri_u.position.out = self->pri_u.position.out_max;
|
||||||
|
}
|
||||||
|
if (self->pri_u.position.out < self->pri_u.position.out_min)
|
||||||
|
{
|
||||||
|
self->pri_u.position.out = self->pri_u.position.out_min;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 更新误差历史
|
||||||
|
self->pri_u.position.pre_error = self->pri_u.position.err; /*上一次误差值*/
|
||||||
|
// 更新输出历史
|
||||||
|
self->pri_u.position.pre_out = self->pri_u.position.out; /*上一次输出值*/
|
||||||
|
|
||||||
|
return self->pri_u.position.out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*杭电:参数控制器*/
|
||||||
|
void pid_hd_constructor(struct PID_HD *self)
|
||||||
|
{
|
||||||
|
self->set_ctrl_prm_position = _set_ctrl_prm_position;
|
||||||
|
self->set_out_prm_position = _set_out_prm_position;
|
||||||
|
self->pid_position = _pid_position;
|
||||||
|
}
|
|
@ -0,0 +1,66 @@
|
||||||
|
#ifndef __PID_HD__
|
||||||
|
#define __PID_HD__
|
||||||
|
#include "lib.h"
|
||||||
|
|
||||||
|
#define INTEGRAL_SEPARATION 1 // 积分分离
|
||||||
|
#define INCOMPLETE_DIFFEREN_HD 1 // 不完全微分
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
float32 ref;
|
||||||
|
float32 feed_back;
|
||||||
|
float32 pre_feed_back;
|
||||||
|
float32 pre_error;
|
||||||
|
float32 ki_error; /*积分误差*/
|
||||||
|
float32 ki_limit; /*积分分离界限*/
|
||||||
|
float32 ki_alpha; /*变积分的系数*/
|
||||||
|
float32 err;
|
||||||
|
float32 sum_iterm;
|
||||||
|
float32 kp;
|
||||||
|
float32 kp_small; /*在接近稳态时的Kp*/
|
||||||
|
float32 kp_big; /*在大范围时的Kp*/
|
||||||
|
float32 ki;
|
||||||
|
float32 kd;
|
||||||
|
float32 err_limit;
|
||||||
|
BOOL detach;
|
||||||
|
float32 err_dead;
|
||||||
|
#if INCOMPLETE_DIFFEREN_HD == 1
|
||||||
|
float32 td_alpha; /*不完全微分系数*/
|
||||||
|
float32 td_beta; /*不完全微分系数beta*/
|
||||||
|
float32 pre_derivative; /*上一次微分值*/
|
||||||
|
#endif
|
||||||
|
float32 out;
|
||||||
|
float32 pre_out;
|
||||||
|
float32 out_max;
|
||||||
|
float32 out_min;
|
||||||
|
BOOL sm;
|
||||||
|
float32 sv_range;
|
||||||
|
uint32_t control_time; /*控制算法运行一次花费的时间*/
|
||||||
|
uint32_t tmp_time; /*临时用来记录控制的运行时间*/
|
||||||
|
} pid_hd_position_t; // 位置式PID
|
||||||
|
|
||||||
|
typedef struct PID_HD
|
||||||
|
{
|
||||||
|
/* 设置PID三个参数 */
|
||||||
|
void (*set_ctrl_prm_position)(struct PID_HD *self, float32 kp, float32 ki, float32 kd);
|
||||||
|
/* 设置输出范围 */
|
||||||
|
void (*set_out_prm_position)(struct PID_HD *self, float32 maximum, float32 minimum);
|
||||||
|
|
||||||
|
/* 控制接口 */
|
||||||
|
float32 (*pid_position)(struct PID_HD *self, float32 err);
|
||||||
|
|
||||||
|
// 自定义参数
|
||||||
|
/* 实际值与目标值之间的误差 */
|
||||||
|
float32 err;
|
||||||
|
/* 输出值 */
|
||||||
|
float32 out;
|
||||||
|
/* private */
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
pid_hd_position_t position;
|
||||||
|
} pri_u;
|
||||||
|
} pid_hd_t;
|
||||||
|
|
||||||
|
extern void pid_hd_constructor(struct PID_HD *self);
|
||||||
|
|
||||||
|
#endif // __PID_HD__
|
|
@ -0,0 +1,481 @@
|
||||||
|
#include "pid_x.h"
|
||||||
|
#include "math.h"
|
||||||
|
#define LAG_PHASE (6) // 迟滞相位,单位:拍
|
||||||
|
|
||||||
|
#ifndef PI
|
||||||
|
#define PI 3.14159265358979f
|
||||||
|
#endif
|
||||||
|
// 注1:自适应模糊pid最重要的就是论域的选择,要和你应该控制的对象相切合
|
||||||
|
// 注2:以下各阀值、限幅值、输出值均需要根据具体的使用情况进行更改
|
||||||
|
// 注3:因为我的控制对象惯性比较大,所以以下各部分取值较小
|
||||||
|
// 论域e:[-5,5] ec:[-0.5,0.5]
|
||||||
|
|
||||||
|
// 误差的阀值,小于这个数值的时候,不做PID调整,避免误差较小时频繁调节引起震荡
|
||||||
|
#define Emin 0.3f
|
||||||
|
#define Emid 1.0f
|
||||||
|
#define Emax 5.0f
|
||||||
|
// 调整值限幅,防止积分饱和
|
||||||
|
#define Umax 1
|
||||||
|
#define Umin -1
|
||||||
|
|
||||||
|
#define NB 0
|
||||||
|
#define NM 1
|
||||||
|
#define NS 2
|
||||||
|
#define ZO 3
|
||||||
|
#define PS 4
|
||||||
|
#define PM 5
|
||||||
|
#define PB 6
|
||||||
|
|
||||||
|
int32_t kp[7][7] = {{PB, PB, PM, PM, PS, ZO, ZO},
|
||||||
|
{PB, PB, PM, PS, PS, ZO, ZO},
|
||||||
|
{PM, PM, PM, PS, ZO, NS, NS},
|
||||||
|
{PM, PM, PS, ZO, NS, NM, NM},
|
||||||
|
{PS, PS, ZO, NS, NS, NM, NM},
|
||||||
|
{PS, ZO, NS, NM, NM, NM, NB},
|
||||||
|
{ZO, ZO, NM, NM, NM, NB, NB}};
|
||||||
|
|
||||||
|
int32_t kd[7][7] = {{PS, NS, NB, NB, NB, NM, PS},
|
||||||
|
{PS, NS, NB, NM, NM, NS, ZO},
|
||||||
|
{ZO, NS, NM, NM, NS, NS, ZO},
|
||||||
|
{ZO, NS, NS, NS, NS, NS, ZO},
|
||||||
|
{ZO, ZO, ZO, ZO, ZO, ZO, ZO},
|
||||||
|
{PB, NS, PS, PS, PS, PS, PB},
|
||||||
|
{PB, PM, PM, PM, PS, PS, PB}};
|
||||||
|
|
||||||
|
int32_t ki[7][7] = {{NB, NB, NM, NM, NS, ZO, ZO},
|
||||||
|
{NB, NB, NM, NS, NS, ZO, ZO},
|
||||||
|
{NB, NM, NS, NS, ZO, PS, PS},
|
||||||
|
{NM, NM, NS, ZO, PS, PM, PM},
|
||||||
|
{NM, NS, ZO, PS, PS, PM, PB},
|
||||||
|
{ZO, ZO, PS, PS, PM, PB, PB},
|
||||||
|
{ZO, ZO, PS, PM, PM, PB, PB}};
|
||||||
|
|
||||||
|
static float32 ec; // 误差变化率
|
||||||
|
/**************求隶属度(三角形)***************/
|
||||||
|
float32 FTri(float32 x, float32 a, float32 b, float32 c) // FuzzyTriangle
|
||||||
|
{
|
||||||
|
if (x <= a)
|
||||||
|
return 0;
|
||||||
|
else if ((a < x) && (x <= b))
|
||||||
|
return (x - a) / (b - a);
|
||||||
|
else if ((b < x) && (x <= c))
|
||||||
|
return (c - x) / (c - b);
|
||||||
|
else if (x > c)
|
||||||
|
return 0;
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/*****************求隶属度(梯形左)*******************/
|
||||||
|
float32 FTraL(float32 x, float32 a, float32 b) // FuzzyTrapezoidLeft
|
||||||
|
{
|
||||||
|
if (x <= a)
|
||||||
|
return 1;
|
||||||
|
else if ((a < x) && (x <= b))
|
||||||
|
return (b - x) / (b - a);
|
||||||
|
else if (x > b)
|
||||||
|
return 0;
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/*****************求隶属度(梯形右)*******************/
|
||||||
|
float32 FTraR(float32 x, float32 a, float32 b) // FuzzyTrapezoidRight
|
||||||
|
{
|
||||||
|
if (x <= a)
|
||||||
|
return 0;
|
||||||
|
if ((a < x) && (x < b))
|
||||||
|
return (x - a) / (b - a);
|
||||||
|
if (x >= b)
|
||||||
|
return 1;
|
||||||
|
else
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
/****************三角形反模糊化处理**********************/
|
||||||
|
float32 uFTri(float32 x, float32 a, float32 b, float32 c)
|
||||||
|
{
|
||||||
|
float32 y, z;
|
||||||
|
z = (b - a) * x + a;
|
||||||
|
y = c - (c - b) * x;
|
||||||
|
return (y + z) / 2;
|
||||||
|
}
|
||||||
|
/*******************梯形(左)反模糊化***********************/
|
||||||
|
float32 uFTraL(float32 x, float32 a, float32 b)
|
||||||
|
{
|
||||||
|
return b - (b - a) * x;
|
||||||
|
}
|
||||||
|
/*******************梯形(右)反模糊化***********************/
|
||||||
|
float32 uFTraR(float32 x, float32 a, float32 b)
|
||||||
|
{
|
||||||
|
return (b - a) * x + a;
|
||||||
|
}
|
||||||
|
/**************************求交集****************************/
|
||||||
|
float32 fand(float32 a, float32 b)
|
||||||
|
{
|
||||||
|
return (a < b) ? a : b;
|
||||||
|
}
|
||||||
|
/**************************求并集****************************/
|
||||||
|
float32 forr(float32 a, float32 b)
|
||||||
|
{
|
||||||
|
return (a < b) ? b : a;
|
||||||
|
}
|
||||||
|
|
||||||
|
static float32 _PID(struct PID_X *self, float32 target, float32 feedback)
|
||||||
|
{
|
||||||
|
float32 pwm_var; // pwm调整量
|
||||||
|
float32 iError; // 当前误差
|
||||||
|
float32 set, input;
|
||||||
|
CLASSICPID *pri = &self->pri;
|
||||||
|
// 计算隶属度表
|
||||||
|
float32 es[7], ecs[7], e;
|
||||||
|
float32 form[7][7];
|
||||||
|
int i = 0, j = 0;
|
||||||
|
int MaxX = 0, MaxY = 0;
|
||||||
|
|
||||||
|
// 记录隶属度最大项及相应推理表的p、i、d值
|
||||||
|
float32 lsd;
|
||||||
|
int temp_p, temp_d, temp_i;
|
||||||
|
float32 detkp, detkd, detki; // 推理后的结果
|
||||||
|
|
||||||
|
// 输入格式的转化及偏差计算
|
||||||
|
set = target;
|
||||||
|
input = feedback;
|
||||||
|
iError = set - input; // 偏差
|
||||||
|
|
||||||
|
e = iError;
|
||||||
|
ec = iError - pri->lasterror;
|
||||||
|
|
||||||
|
// 当温度差的绝对值小于Emax时,对pid的参数进行调整
|
||||||
|
if (fabs(iError) <= Emax)
|
||||||
|
{
|
||||||
|
// 计算iError在es与ecs中各项的隶属度
|
||||||
|
es[NB] = FTraL(e * 5, -3, -1); // e
|
||||||
|
es[NM] = FTri(e * 5, -3, -2, 0);
|
||||||
|
es[NS] = FTri(e * 5, -3, -1, 1);
|
||||||
|
es[ZO] = FTri(e * 5, -2, 0, 2);
|
||||||
|
es[PS] = FTri(e * 5, -1, 1, 3);
|
||||||
|
es[PM] = FTri(e * 5, 0, 2, 3);
|
||||||
|
es[PB] = FTraR(e * 5, 1, 3);
|
||||||
|
|
||||||
|
ecs[NB] = FTraL(ec * 30, -3, -1); // ec
|
||||||
|
ecs[NM] = FTri(ec * 30, -3, -2, 0);
|
||||||
|
ecs[NS] = FTri(ec * 30, -3, -1, 1);
|
||||||
|
ecs[ZO] = FTri(ec * 30, -2, 0, 2);
|
||||||
|
ecs[PS] = FTri(ec * 30, -1, 1, 3);
|
||||||
|
ecs[PM] = FTri(ec * 30, 0, 2, 3);
|
||||||
|
ecs[PB] = FTraR(ec * 30, 1, 3);
|
||||||
|
|
||||||
|
// 计算隶属度表,确定e和ec相关联后表格各项隶属度的值
|
||||||
|
for (i = 0; i < 7; i++)
|
||||||
|
{
|
||||||
|
for (j = 0; j < 7; j++)
|
||||||
|
{
|
||||||
|
form[i][j] = fand(es[i], ecs[j]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 取出具有最大隶属度的那一项
|
||||||
|
for (i = 0; i < 7; i++)
|
||||||
|
{
|
||||||
|
for (j = 0; j < 7; j++)
|
||||||
|
{
|
||||||
|
if (form[MaxX][MaxY] < form[i][j])
|
||||||
|
{
|
||||||
|
MaxX = i;
|
||||||
|
MaxY = j;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 进行模糊推理,并去模糊
|
||||||
|
lsd = form[MaxX][MaxY];
|
||||||
|
temp_p = kp[MaxX][MaxY];
|
||||||
|
temp_d = kd[MaxX][MaxY];
|
||||||
|
temp_i = ki[MaxX][MaxY];
|
||||||
|
|
||||||
|
if (temp_p == NB)
|
||||||
|
detkp = uFTraL(lsd, -0.3, -0.1);
|
||||||
|
else if (temp_p == NM)
|
||||||
|
detkp = uFTri(lsd, -0.3, -0.2, 0);
|
||||||
|
else if (temp_p == NS)
|
||||||
|
detkp = uFTri(lsd, -0.3, -0.1, 0.1);
|
||||||
|
else if (temp_p == ZO)
|
||||||
|
detkp = uFTri(lsd, -0.2, 0, 0.2);
|
||||||
|
else if (temp_p == PS)
|
||||||
|
detkp = uFTri(lsd, -0.1, 0.1, 0.3);
|
||||||
|
else if (temp_p == PM)
|
||||||
|
detkp = uFTri(lsd, 0, 0.2, 0.3);
|
||||||
|
else if (temp_p == PB)
|
||||||
|
detkp = uFTraR(lsd, 0.1, 0.3);
|
||||||
|
|
||||||
|
if (temp_d == NB)
|
||||||
|
detkd = uFTraL(lsd, -3, -1);
|
||||||
|
else if (temp_d == NM)
|
||||||
|
detkd = uFTri(lsd, -3, -2, 0);
|
||||||
|
else if (temp_d == NS)
|
||||||
|
detkd = uFTri(lsd, -3, 1, 1);
|
||||||
|
else if (temp_d == ZO)
|
||||||
|
detkd = uFTri(lsd, -2, 0, 2);
|
||||||
|
else if (temp_d == PS)
|
||||||
|
detkd = uFTri(lsd, -1, 1, 3);
|
||||||
|
else if (temp_d == PM)
|
||||||
|
detkd = uFTri(lsd, 0, 2, 3);
|
||||||
|
else if (temp_d == PB)
|
||||||
|
detkd = uFTraR(lsd, 1, 3);
|
||||||
|
|
||||||
|
if (temp_i == NB)
|
||||||
|
detki = uFTraL(lsd, -0.06, -0.02);
|
||||||
|
else if (temp_i == NM)
|
||||||
|
detki = uFTri(lsd, -0.06, -0.04, 0);
|
||||||
|
else if (temp_i == NS)
|
||||||
|
detki = uFTri(lsd, -0.06, -0.02, 0.02);
|
||||||
|
else if (temp_i == ZO)
|
||||||
|
detki = uFTri(lsd, -0.04, 0, 0.04);
|
||||||
|
else if (temp_i == PS)
|
||||||
|
detki = uFTri(lsd, -0.02, 0.02, 0.06);
|
||||||
|
else if (temp_i == PM)
|
||||||
|
detki = uFTri(lsd, 0, 0.04, 0.06);
|
||||||
|
else if (temp_i == PB)
|
||||||
|
detki = uFTraR(lsd, 0.02, 0.06);
|
||||||
|
|
||||||
|
// pid三项系数的修改
|
||||||
|
pri->pKp += detkp;
|
||||||
|
pri->pKi += detki;
|
||||||
|
if (pri->kd_e)
|
||||||
|
{
|
||||||
|
pri->pKd += detkd;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pri->pKd = 0; // 取消微分作用
|
||||||
|
}
|
||||||
|
|
||||||
|
// 对Kp,Ki进行限幅
|
||||||
|
if (pri->pKp < 0)
|
||||||
|
{
|
||||||
|
pri->pKp = 0;
|
||||||
|
}
|
||||||
|
if (pri->pKi < 0)
|
||||||
|
{
|
||||||
|
pri->pKi = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 计算新的K1,nKi,nKd
|
||||||
|
pri->nKp = pri->pKp + pri->pKi + pri->pKd;
|
||||||
|
pri->nKi = -(pri->pKp + 2 * pri->pKd);
|
||||||
|
pri->nKd = pri->pKd;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (iError > Emax)
|
||||||
|
{
|
||||||
|
pri->out = pri->max;
|
||||||
|
pwm_var = 0;
|
||||||
|
pri->flag = 1; // 设定标志位,如果误差超过了门限值,则认为当控制量第一次到达给定值时,应该采取下面的 抑制超调 的措施
|
||||||
|
}
|
||||||
|
else if (iError < -Emax)
|
||||||
|
{
|
||||||
|
pri->out = pri->min;
|
||||||
|
pwm_var = 0;
|
||||||
|
}
|
||||||
|
else if (fabsf(iError) <= Emin)
|
||||||
|
{
|
||||||
|
pwm_var = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (iError < Emid && pri->flag == 1) // 第一次超过(设定值-Emid(-0.08)摄氏度),是输出为零,防止超调,也可以输出其他值,不至于太小而引起震荡
|
||||||
|
{
|
||||||
|
pri->out = 0;
|
||||||
|
pri->flag = 0;
|
||||||
|
}
|
||||||
|
else if (-iError > Emid) // 超过(设定+Emid(+0.08)摄氏度)
|
||||||
|
{
|
||||||
|
pwm_var = -1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// 增量计算
|
||||||
|
pwm_var = (pri->nKp * iError // e[k]
|
||||||
|
+ pri->nKi * pri->lasterror // e[k-1]
|
||||||
|
+ pri->nKd * pri->preverror); // e[k-2]
|
||||||
|
}
|
||||||
|
if (pwm_var >= Umax)
|
||||||
|
pwm_var = Umax; // 调整值限幅,防止积分饱和
|
||||||
|
if (pwm_var <= Umin)
|
||||||
|
pwm_var = Umin; // 调整值限幅,防止积分饱和
|
||||||
|
}
|
||||||
|
pri->preverror = pri->lasterror;
|
||||||
|
pri->lasterror = iError;
|
||||||
|
|
||||||
|
pri->out += pwm_var; // 调整PWM输出
|
||||||
|
|
||||||
|
if (pri->out > pri->max)
|
||||||
|
pri->out = pri->max; // 输出值限幅
|
||||||
|
if (pri->out < pri->min)
|
||||||
|
pri->out = pri->min; // 输出值限幅
|
||||||
|
|
||||||
|
return pri->out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*整定开始前的预处理,判断状态及初始化变量*/
|
||||||
|
static void tune_pretreatment(struct PID_X *self)
|
||||||
|
{
|
||||||
|
CLASSIC_AUTOTUNE *tune = &self->tune;
|
||||||
|
CLASSICPID *vPID = &self->pri;
|
||||||
|
|
||||||
|
tune->tuneTimer = 0;
|
||||||
|
tune->startTime = 0;
|
||||||
|
tune->endTime = 0;
|
||||||
|
tune->outputStep = 100;
|
||||||
|
|
||||||
|
if (*vPID->pSV >= *vPID->pPV)
|
||||||
|
{
|
||||||
|
tune->initialStatus = 1;
|
||||||
|
tune->outputStatus = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tune->initialStatus = 0;
|
||||||
|
tune->outputStatus = 1;
|
||||||
|
}
|
||||||
|
tune->tuneEnable = 1;
|
||||||
|
tune->preEnable = 0;
|
||||||
|
tune->zeroAcrossCounter = 0;
|
||||||
|
tune->riseLagCounter = 0;
|
||||||
|
tune->fallLagCounter = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*计算PID参数值*/
|
||||||
|
static void calculation_parameters(struct PID_X *self)
|
||||||
|
{
|
||||||
|
CLASSIC_AUTOTUNE *tune = &self->tune;
|
||||||
|
CLASSICPID *vPID = &self->pri;
|
||||||
|
float32 kc = 0.0f;
|
||||||
|
float32 tc = 0.0f;
|
||||||
|
float32 zn[3][3] = {{0.5f, 100000.0f, 0.0f}, {0.45f, 0.8f, 0.0f}, {0.6f, 0.5f, 0.125f}};
|
||||||
|
|
||||||
|
tc = (tune->endTime - tune->startTime) * tune->tunePeriod / 1000.0;
|
||||||
|
kc = (8.0f * tune->outputStep) / (PI * (tune->maxPV - tune->minPV));
|
||||||
|
|
||||||
|
vPID->pKp = zn[tune->controllerType][0] * kc; // 比例系数
|
||||||
|
vPID->pKi = vPID->pKp * tune->tunePeriod / (zn[tune->controllerType][1] * tc); // 积分系数
|
||||||
|
vPID->pKd = vPID->pKp * zn[tune->controllerType][2] * tc / tune->tunePeriod; // 微分系数
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 自整定函数
|
||||||
|
* @param {PID_X} *self
|
||||||
|
* @return {*}
|
||||||
|
* @note 成员变量tuneEnable、preEnable和controllerType需要提前赋值。tuneEnable变量值为0时是使用PID控制器,而tuneEnable变量值为1时是开启整定过程,当tuneEnable变量值为2时是指示整定失败。preEnable变量在整定前赋值为1,表示先做预处理。而controllerType则根据所整定的控制器的类型来定,主要用于参数的计算。
|
||||||
|
*/
|
||||||
|
static uint8_t _auto_tune(struct PID_X *self)
|
||||||
|
{
|
||||||
|
CLASSIC_AUTOTUNE *tune = &self->tune;
|
||||||
|
CLASSICPID *vPID = &self->pri;
|
||||||
|
/*整定开始前的预处理,只执行一次*/
|
||||||
|
if (tune->preEnable == 1)
|
||||||
|
{
|
||||||
|
tune_pretreatment(self);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t tuneDuration = 0;
|
||||||
|
tune->tuneTimer++;
|
||||||
|
tuneDuration = (tune->tuneTimer * tune->tunePeriod) / 1000;
|
||||||
|
if (tuneDuration > (10 * 60)) // 整定过程持续超过10分钟,未能形成有效振荡,整定失败
|
||||||
|
{
|
||||||
|
tune->tuneEnable = 2;
|
||||||
|
tune->preEnable = 1;
|
||||||
|
return tune->tuneEnable;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*vPID->pSV >= *vPID->pPV) // 设定值大于测量值,则开执行单元
|
||||||
|
{
|
||||||
|
tune->riseLagCounter++;
|
||||||
|
tune->fallLagCounter = 0;
|
||||||
|
|
||||||
|
if (tune->riseLagCounter > LAG_PHASE)
|
||||||
|
{
|
||||||
|
*vPID->pMV = vPID->max;
|
||||||
|
if (tune->outputStatus == 0)
|
||||||
|
{
|
||||||
|
tune->outputStatus = 1;
|
||||||
|
tune->zeroAcrossCounter++;
|
||||||
|
|
||||||
|
if (tune->zeroAcrossCounter == 3)
|
||||||
|
{
|
||||||
|
tune->startTime = tune->tuneTimer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tune->riseLagCounter = 0;
|
||||||
|
tune->fallLagCounter++;
|
||||||
|
|
||||||
|
if (tune->fallLagCounter > LAG_PHASE)
|
||||||
|
{
|
||||||
|
*vPID->pMV = vPID->min;
|
||||||
|
if (tune->outputStatus == 1)
|
||||||
|
{
|
||||||
|
tune->outputStatus = 0;
|
||||||
|
tune->zeroAcrossCounter++;
|
||||||
|
|
||||||
|
if (tune->zeroAcrossCounter == 3)
|
||||||
|
{
|
||||||
|
tune->startTime = tune->tuneTimer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tune->zeroAcrossCounter == 3) // 已经两次过零,可以记录波形数据
|
||||||
|
{
|
||||||
|
if (tune->initialStatus == 1) // 初始设定值大于测量值,则区域3出现最小值
|
||||||
|
{
|
||||||
|
if (*vPID->pPV < tune->minPV)
|
||||||
|
{
|
||||||
|
tune->minPV = *vPID->pPV;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (tune->initialStatus == 0) // 初始设定值小于测量值,则区域3出现最大值
|
||||||
|
{
|
||||||
|
if (*vPID->pPV > tune->maxPV)
|
||||||
|
{
|
||||||
|
tune->maxPV = *vPID->pPV;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (tune->zeroAcrossCounter == 4) // 已经三次过零,记录另半波的数据
|
||||||
|
{
|
||||||
|
if (tune->initialStatus == 1) // 初始设定值大于测量值,则区域4出现最大值
|
||||||
|
{
|
||||||
|
if (*vPID->pPV > tune->maxPV)
|
||||||
|
{
|
||||||
|
tune->maxPV = *vPID->pPV;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (tune->initialStatus == 0) // 初始设定值小于测量值,则区域4出现最小值
|
||||||
|
{
|
||||||
|
if (*vPID->pPV < tune->minPV)
|
||||||
|
{
|
||||||
|
tune->minPV = *vPID->pPV;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (tune->zeroAcrossCounter == 5) // 已经四次过零,振荡已形成可以整定参数
|
||||||
|
{
|
||||||
|
calculation_parameters(self);
|
||||||
|
|
||||||
|
tune->tuneEnable = 0;
|
||||||
|
tune->preEnable = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return tune->tuneEnable;
|
||||||
|
}
|
||||||
|
|
||||||
|
void pid_x_constructor(struct PID_X *self)
|
||||||
|
{
|
||||||
|
self->PID = _PID;
|
||||||
|
self->AUTO_TUNE = _auto_tune;
|
||||||
|
self->pri.flag = 0;
|
||||||
|
self->pri.out = 0;
|
||||||
|
self->tune.preEnable = 1;
|
||||||
|
}
|
|
@ -0,0 +1,71 @@
|
||||||
|
#ifndef __PID_X_H__
|
||||||
|
#define __PID_X_H__
|
||||||
|
#include "lib.h"
|
||||||
|
|
||||||
|
/*定义PID对象类型*/
|
||||||
|
typedef struct CLASSIC
|
||||||
|
{
|
||||||
|
float32 *pPV; // 测量值指针
|
||||||
|
float32 *pSV; // 设定值指针
|
||||||
|
float32 *pMV; // 输出值指针
|
||||||
|
BOOL *pMA; // 手自动操作指针
|
||||||
|
|
||||||
|
float32 out; // 输出值
|
||||||
|
float32 setpoint; // 设定值
|
||||||
|
float32 lasterror; // 前一拍偏差
|
||||||
|
float32 preverror; // 前两拍偏差
|
||||||
|
float32 max; // 输出值上限
|
||||||
|
float32 min; // 输出值下限
|
||||||
|
|
||||||
|
uint16_t flag; // 状态标志位
|
||||||
|
|
||||||
|
float32 pKp; // 比例系数
|
||||||
|
float32 pKi; // 积分系数
|
||||||
|
float32 pKd; // 微分系数
|
||||||
|
|
||||||
|
float32 nKp; // 比例系数
|
||||||
|
float32 nKi; // 积分系数
|
||||||
|
float32 nKd; // 微分系数
|
||||||
|
|
||||||
|
BOOL direct; // 正反作用
|
||||||
|
BOOL sm; // 设定值平滑
|
||||||
|
BOOL cas; // 串级设定
|
||||||
|
BOOL pac; // 输出防陡变
|
||||||
|
BOOL kd_e; // 微分使能
|
||||||
|
} CLASSICPID;
|
||||||
|
|
||||||
|
// 定义整定参数
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
uint8_t tuneEnable : 2; // 整定与PID控制开关,0:PID控制;1:参数整定;2:整定失败
|
||||||
|
uint8_t preEnable : 2; // 预处理使能,在开始整定前置位
|
||||||
|
uint8_t initialStatus : 1; // 记录开始整定前偏差的初始状态
|
||||||
|
uint8_t outputStatus : 1; // 记录输出的初始状态,0允许上升过零计数;1允许下降过零计数
|
||||||
|
uint8_t controllerType : 2; // 控制器类型:0,P控制器;1,PI控制器;2,PID控制器
|
||||||
|
|
||||||
|
uint8_t zeroAcrossCounter; // 过零点计数器,每次输出改变加1,比实际过零次数多1
|
||||||
|
uint8_t riseLagCounter; // 上升迟滞时间计数器
|
||||||
|
uint8_t fallLagCounter; // 下降迟滞时间计数器
|
||||||
|
|
||||||
|
uint16_t tunePeriod; // 整定采样周期
|
||||||
|
uint32_t tuneTimer; // 整定计时器
|
||||||
|
uint32_t startTime; // 记录波形周期起始时间
|
||||||
|
uint32_t endTime; // 记录波形周期结束时间
|
||||||
|
|
||||||
|
float32 outputStep; // 输出阶跃d
|
||||||
|
float32 maxPV; // 振荡波形中测量值的最大值
|
||||||
|
float32 minPV; // 振荡波形中测量值的最小值
|
||||||
|
} CLASSIC_AUTOTUNE;
|
||||||
|
|
||||||
|
typedef struct PID_X
|
||||||
|
{
|
||||||
|
/* 控制接口 */
|
||||||
|
float32 (*PID)(struct PID_X *self, float32 target, float32 feedback);
|
||||||
|
uint8_t (*AUTO_TUNE)(struct PID_X *self);
|
||||||
|
/* private */
|
||||||
|
CLASSICPID pri;
|
||||||
|
CLASSIC_AUTOTUNE tune;
|
||||||
|
} pid_x_t;
|
||||||
|
|
||||||
|
extern void pid_x_constructor(struct PID_X *self);
|
||||||
|
#endif // __PID_X_H__
|
|
@ -0,0 +1,467 @@
|
||||||
|
#include "pid_zh.h"
|
||||||
|
#include "sys.h"
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
// 定义输出量比例因子
|
||||||
|
#ifdef GPS3000
|
||||||
|
#define KUP 0.0f // #define KUP 3.0f
|
||||||
|
#define KUI 0.00f
|
||||||
|
#define KUD 0.0f // #define KUP 3.0f
|
||||||
|
#else
|
||||||
|
#define KUP 3.0f
|
||||||
|
#define KUI 0.0f
|
||||||
|
#define KUD 0.0f
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// 模糊集合
|
||||||
|
#define NL -3
|
||||||
|
#define NM -2
|
||||||
|
#define NS -1
|
||||||
|
#define ZE 0
|
||||||
|
#define PS 1
|
||||||
|
#define PM 2
|
||||||
|
#define PL 3
|
||||||
|
|
||||||
|
// 定义偏差E的范围,因为设置了非线性区间,误差在10时才开始进行PID调节,这里E的范围为10
|
||||||
|
#define MAXE (10)
|
||||||
|
#define MINE (-MAXE)
|
||||||
|
// 定义EC的范围,因为变化非常缓慢!,每次的EC都非常小,这里可以根据实际需求来调整,
|
||||||
|
#define MAXEC (10)
|
||||||
|
#define MINEC (-MAXEC)
|
||||||
|
// 定义e,ec的量化因子
|
||||||
|
#define KE 3 / MAXE
|
||||||
|
#define KEC 3 / MAXEC
|
||||||
|
|
||||||
|
static const float32 fuzzyRuleKp[7][7] = {
|
||||||
|
PL, PL, PM, PL, PS, PM, PL,
|
||||||
|
PL, PM, PM, PM, PS, PM, PL,
|
||||||
|
PM, PS, PS, PS, PS, PS, PM,
|
||||||
|
PM, PS, ZE, ZE, ZE, PS, PM,
|
||||||
|
PS, PS, PS, PS, PS, PM, PM,
|
||||||
|
PM, PM, PM, PM, PL, PL, PL,
|
||||||
|
PM, PL, PL, PL, PL, PL, PL};
|
||||||
|
|
||||||
|
static const float32 fuzzyRuleKi[7][7] = {
|
||||||
|
PL, PL, PL, PL, PM, PL, PL,
|
||||||
|
PL, PL, PM, PM, PM, PL, PL,
|
||||||
|
PM, PM, PS, PS, PS, PM, PM,
|
||||||
|
PM, PS, ZE, ZE, ZE, PS, PM,
|
||||||
|
PM, PS, PS, PS, PS, PM, PM,
|
||||||
|
PM, PM, PS, PM, PM, PL, PL,
|
||||||
|
PM, PL, PM, PL, PL, PL, PL};
|
||||||
|
|
||||||
|
/*
|
||||||
|
static const float32 fuzzyRuleKi[7][7] = {
|
||||||
|
NL, NL, NL, NL, NM, NL, NL,
|
||||||
|
NL, NL, NM, NM, NM, NL, NL,
|
||||||
|
NM, NM, NS, NS, NS, NM, NM,
|
||||||
|
NM, NS, ZE, ZE, ZE, NS, NM,
|
||||||
|
NM, NS, NS, NS, NS, NM, NM,
|
||||||
|
NM, NM, NS, NM, NM, NL, NL,
|
||||||
|
NM, NL, NM, NL, NL, NL, NL};
|
||||||
|
*/
|
||||||
|
|
||||||
|
static const float32 fuzzyRuleKd[7][7] = {
|
||||||
|
PS, PS, ZE, ZE, ZE, PL, PL,
|
||||||
|
PS, PS, PS, PS, ZE, PS, PM,
|
||||||
|
PL, PL, PM, PS, ZE, PS, PM,
|
||||||
|
PL, PM, PM, PS, ZE, PS, PM,
|
||||||
|
PL, PM, PS, PS, ZE, PS, PS,
|
||||||
|
PM, PS, PS, PS, ZE, PS, PS,
|
||||||
|
PS, ZE, ZE, ZE, ZE, PL, PL};
|
||||||
|
|
||||||
|
/*
|
||||||
|
static const float32 fuzzyRuleKp[7][7] = {
|
||||||
|
PL, PL, PM, PM, PS, ZE, ZE,
|
||||||
|
PL, PL, PM, PS, PS, ZE, NS,
|
||||||
|
PM, PM, PM, PS, ZE, NS, NS,
|
||||||
|
PM, PM, PS, ZE, NS, NM, NM,
|
||||||
|
PS, PS, ZE, NS, NS, NM, NM,
|
||||||
|
PS, ZE, NS, NM, NM, NM, NL,
|
||||||
|
ZE, ZE, NM, NM, NM, NL, NL};
|
||||||
|
|
||||||
|
static const float32 fuzzyRuleKi[7][7] = {
|
||||||
|
NL, NL, NM, NM, NS, ZE, ZE,
|
||||||
|
NL, NL, NM, NS, NS, ZE, ZE,
|
||||||
|
NL, NM, NS, NS, ZE, PS, PS,
|
||||||
|
NM, NM, NS, ZE, PS, PM, PM,
|
||||||
|
NM, NS, ZE, PS, PS, NM, PL,
|
||||||
|
ZE, ZE, PS, PS, PM, PL, PL,
|
||||||
|
ZE, ZE, PS, PM, PM, PL, PL};
|
||||||
|
|
||||||
|
static const float32 fuzzyRuleKd[7][7] = {
|
||||||
|
PS, NS, NL, NL, NL, NM, PS,
|
||||||
|
PS, NS, NL, NM, NM, NS, ZE,
|
||||||
|
ZE, NS, NM, NM, NS, NS, ZE,
|
||||||
|
ZE, NS, NS, NS, NS, NS, ZE,
|
||||||
|
|
||||||
|
ZE, ZE, ZE, ZE, ZE, ZE, ZE,
|
||||||
|
PL, NS, PS, PS, PS, PS, PL,
|
||||||
|
PL, PM, PM, PM, PS, PS, PL};
|
||||||
|
*/
|
||||||
|
|
||||||
|
static void fuzzy(float32 e, float32 ec, FUZZY_PID_ZH_t *fuzzy_pid)
|
||||||
|
{
|
||||||
|
|
||||||
|
float32 etemp, ectemp;
|
||||||
|
float32 eLefttemp, ecLefttemp; // ec,e,左隶属度
|
||||||
|
float32 eRighttemp, ecRighttemp;
|
||||||
|
|
||||||
|
int eLeftIndex, ecLeftIndex; // 模糊位置标号
|
||||||
|
int eRightIndex, ecRightIndex;
|
||||||
|
e = RANGE(e, MINE, MAXE);
|
||||||
|
ec = RANGE(ec, MINEC, MAXEC);
|
||||||
|
e = e * KE;
|
||||||
|
ec = ec * KEC;
|
||||||
|
|
||||||
|
etemp = e > 3.0f ? 0.0f : (e < -3.0f ? 0.0f : (e >= 0.0f ? (e >= 2.0f ? 2.5f : (e >= 1.0f ? 1.5f : 0.5f)) : (e >= -1.0f ? -0.5f : (e >= -2.0f ? -1.5f : (e >= -3.0f ? -2.5f : 0.0f)))));
|
||||||
|
eLeftIndex = (int)((etemp - 0.5f) + 3); //[-3,2] -> [0,5]
|
||||||
|
eRightIndex = (int)((etemp + 0.5f) + 3);
|
||||||
|
eLefttemp = etemp == 0.0f ? 0.0f : ((etemp + 0.5f) - e);
|
||||||
|
eRighttemp = etemp == 0.0f ? 0.0f : (e - (etemp - 0.5f));
|
||||||
|
|
||||||
|
ectemp = ec > 3.0f ? 0.0f : (ec < -3.0f ? 0.0f : (ec >= 0.0f ? (ec >= 2.0f ? 2.5f : (ec >= 1.0f ? 1.5f : 0.5f)) : (ec >= -1.0f ? -0.5f : (ec >= -2.0f ? -1.5f : (ec >= -3.0f ? -2.5f : 0.0f)))));
|
||||||
|
ecLeftIndex = (int)((ectemp - 0.5f) + 3); //[-3,2] -> [0,5]
|
||||||
|
ecRightIndex = (int)((ectemp + 0.5f) + 3);
|
||||||
|
ecLefttemp = ectemp == 0.0f ? 0.0f : ((ectemp + 0.5f) - ec);
|
||||||
|
ecRighttemp = ectemp == 0.0f ? 0.0f : (ec - (ectemp - 0.5f));
|
||||||
|
|
||||||
|
/*************************************反模糊*************************************/
|
||||||
|
|
||||||
|
fuzzy_pid->kp = (eLefttemp * ecLefttemp * fuzzyRuleKp[eLeftIndex][ecLeftIndex] + eLefttemp * ecRighttemp * fuzzyRuleKp[eLeftIndex][ecRightIndex] + eRighttemp * ecLefttemp * fuzzyRuleKp[eRightIndex][ecLeftIndex] + eRighttemp * ecRighttemp * fuzzyRuleKp[eRightIndex][ecRightIndex]);
|
||||||
|
|
||||||
|
fuzzy_pid->ki = (eLefttemp * ecLefttemp * fuzzyRuleKi[eLeftIndex][ecLeftIndex] + eLefttemp * ecRighttemp * fuzzyRuleKi[eLeftIndex][ecRightIndex] + eRighttemp * ecLefttemp * fuzzyRuleKi[eRightIndex][ecLeftIndex] + eRighttemp * ecRighttemp * fuzzyRuleKi[eRightIndex][ecRightIndex]);
|
||||||
|
|
||||||
|
fuzzy_pid->kd = (eLefttemp * ecLefttemp * fuzzyRuleKd[eLeftIndex][ecLeftIndex] + eLefttemp * ecRighttemp * fuzzyRuleKd[eLeftIndex][ecRightIndex] + eRighttemp * ecLefttemp * fuzzyRuleKd[eRightIndex][ecLeftIndex] + eRighttemp * ecRighttemp * fuzzyRuleKd[eRightIndex][ecRightIndex]);
|
||||||
|
// 对解算出的KP,KI,KD进行量化映射
|
||||||
|
fuzzy_pid->kp = fuzzy_pid->kp * fuzzy_pid->kup;
|
||||||
|
fuzzy_pid->ki = fuzzy_pid->ki * fuzzy_pid->kui;
|
||||||
|
fuzzy_pid->kd = fuzzy_pid->kd * fuzzy_pid->kud;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void smoothSetpoint(struct PID_FUZZY_ZH *self, float32 target_sv)
|
||||||
|
{
|
||||||
|
#if FUZZY_SUB_TYPE == PID_SUB_TYPE_POSITION
|
||||||
|
pid_zh_position_t *pri = &self->pri;
|
||||||
|
#else
|
||||||
|
pid_common_increment_t *pri = &self->pri;
|
||||||
|
#endif
|
||||||
|
float32 stepIn = (pri->sv_range) * 0.1f;
|
||||||
|
float32 kFactor = 0.0f;
|
||||||
|
if (fabs(pri->ref - target_sv) <= stepIn)
|
||||||
|
{
|
||||||
|
pri->ref = target_sv;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (pri->ref - target_sv > 0)
|
||||||
|
{
|
||||||
|
kFactor = -1.0f;
|
||||||
|
}
|
||||||
|
else if (pri->ref - target_sv < 0)
|
||||||
|
{
|
||||||
|
kFactor = 1.0f;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
kFactor = 0.0f;
|
||||||
|
}
|
||||||
|
pri->ref = pri->ref + kFactor * stepIn;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*封装模糊接口*/
|
||||||
|
static void compensate(float32 e, float32 ec, FUZZY_PID_ZH_t *fuzzy_d)
|
||||||
|
{
|
||||||
|
fuzzy(e, ec, fuzzy_d);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 复位PID积分及微分控制数据
|
||||||
|
* @param {PID_FUZZY_ZH} *self
|
||||||
|
* @return {*}
|
||||||
|
*/
|
||||||
|
static void _restctrl(struct PID_FUZZY_ZH *self)
|
||||||
|
{
|
||||||
|
self->pri.pre_error = 0;
|
||||||
|
self->pri.sum_iterm = 0;
|
||||||
|
#if INCOMPLETE_DIFFEREN == 1
|
||||||
|
self->pri.lastdev = 0;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 更新最大最小值
|
||||||
|
* @param {PID_FUZZY_ZH} *self
|
||||||
|
* @param {float32} out_min
|
||||||
|
* @param {float32} out_max
|
||||||
|
* @return {*}
|
||||||
|
* @note
|
||||||
|
*/
|
||||||
|
static void _set_range(struct PID_FUZZY_ZH *self, float32 out_min, float32 out_max)
|
||||||
|
{
|
||||||
|
self->pri.out_max = out_max;
|
||||||
|
self->pri.out_min = out_min;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 使能积分控制
|
||||||
|
* @param {PID_FUZZY_ZH} *self
|
||||||
|
* @param {BOOL} enable
|
||||||
|
* @return {*}
|
||||||
|
* @note
|
||||||
|
*/
|
||||||
|
// static void _set_ki_enable(struct PID_FUZZY_ZH *self, BOOL enable)
|
||||||
|
// {
|
||||||
|
// self->pri.ki_enable = enable;
|
||||||
|
// }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 使能微分控制
|
||||||
|
* @param {PID_FUZZY_ZH} *self
|
||||||
|
* @param {BOOL} enable
|
||||||
|
* @return {*}
|
||||||
|
* @note
|
||||||
|
*/
|
||||||
|
static void _set_kd_enable(struct PID_FUZZY_ZH *self, BOOL enable)
|
||||||
|
{
|
||||||
|
self->pri.kd_enable = enable;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Function:使能平滑控制
|
||||||
|
* parameter:*pid需要配,PID参数结构指针,sv_range控制范围sv的范围
|
||||||
|
* return:无
|
||||||
|
*/
|
||||||
|
static void _set_smooth_enable(struct PID_FUZZY_ZH *self, BOOL enable, float32 sv_range)
|
||||||
|
{
|
||||||
|
#if FUZZY_SUB_TYPE == PID_SUB_TYPE_POSITION
|
||||||
|
pid_zh_position_t *pri = &self->pri;
|
||||||
|
#else
|
||||||
|
pid_common_increment_t *pri = &self->pri;
|
||||||
|
#endif
|
||||||
|
pri->sm = enable;
|
||||||
|
pri->sv_range = sv_range;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 设置控制参数
|
||||||
|
static void _set_ctrl_prm(struct PID_FUZZY_ZH *self, float32 kp, float32 ki, float32 kd, float32 err_dead,
|
||||||
|
float32 out_min, float32 out_max)
|
||||||
|
{
|
||||||
|
self->open = TRUE;
|
||||||
|
self->fuzzy.kup = KUP;
|
||||||
|
self->fuzzy.kui = KUI;
|
||||||
|
self->fuzzy.kud = KUD;
|
||||||
|
#if FUZZY_SUB_TYPE == PID_SUB_TYPE_POSITION
|
||||||
|
pid_zh_position_t *pri = &self->pri;
|
||||||
|
osel_memset((uint8_t *)pri, 0, sizeof(pid_zh_position_t));
|
||||||
|
pri->kp = kp;
|
||||||
|
pri->ki = ki;
|
||||||
|
pri->kd = kd;
|
||||||
|
pri->err_dead = err_dead;
|
||||||
|
pri->out_max = out_max;
|
||||||
|
pri->out_min = out_min;
|
||||||
|
pri->detach = FALSE;
|
||||||
|
pri->sm = FALSE;
|
||||||
|
#else
|
||||||
|
pid_common_increment_t *pri = &self->pri;
|
||||||
|
osel_memset((uint8_t *)pri, 0, sizeof(pid_common_increment_t));
|
||||||
|
pri->kp = kp;
|
||||||
|
pri->ki = ki;
|
||||||
|
pri->kd = kd;
|
||||||
|
pri->err_dead = err_dead;
|
||||||
|
pri->out_max = out_max;
|
||||||
|
pri->out_min = out_min;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (kd > 0)
|
||||||
|
{
|
||||||
|
pri->kd_enable = TRUE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pri->kd_enable = FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _update_ctrl_prm(struct PID_FUZZY_ZH *self, float32 kp, float32 ki, float32 kd, float32 err_dead,
|
||||||
|
float32 out_min, float32 out_max)
|
||||||
|
{
|
||||||
|
#if FUZZY_SUB_TYPE == PID_SUB_TYPE_POSITION
|
||||||
|
pid_zh_position_t *pri = &self->pri;
|
||||||
|
pri->kp = kp;
|
||||||
|
pri->ki = ki;
|
||||||
|
pri->kd = kd;
|
||||||
|
pri->err_dead = err_dead;
|
||||||
|
pri->out_max = out_max;
|
||||||
|
pri->out_min = out_min;
|
||||||
|
pri->detach = FALSE;
|
||||||
|
pri->sm = FALSE;
|
||||||
|
#else
|
||||||
|
pid_common_increment_t *pri = &self->pri;
|
||||||
|
pri->kp = kp;
|
||||||
|
pri->ki = ki;
|
||||||
|
pri->kd = kd;
|
||||||
|
pri->err_dead = err_dead;
|
||||||
|
pri->out_max = out_max;
|
||||||
|
pri->out_min = out_min;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (kd > 0)
|
||||||
|
{
|
||||||
|
pri->kd_enable = TRUE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pri->kd_enable = FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 非0时配置为积分分离+抗积分饱和PID,否则为普通抗积分饱和PID
|
||||||
|
* @param {PID_FUZZY_ZH} *self
|
||||||
|
* @param {float32} max_err
|
||||||
|
* @param {BOOL} mode
|
||||||
|
* @return {*}
|
||||||
|
*/
|
||||||
|
static void _set_cfg(struct PID_FUZZY_ZH *self, float32 max_err, BOOL mode)
|
||||||
|
{
|
||||||
|
self->pri.err_limit = max_err;
|
||||||
|
self->pri.detach = mode == FALSE ? FALSE : TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if FUZZY_SUB_TYPE == PID_SUB_TYPE_POSITION
|
||||||
|
static float32 _PID(struct PID_FUZZY_ZH *self, float32 target, float32 feedback)
|
||||||
|
{
|
||||||
|
float32 error = 0;
|
||||||
|
float32 insert = 0;
|
||||||
|
float32 ec = 0;
|
||||||
|
float32 kd = 0;
|
||||||
|
#if INCOMPLETE_DIFFEREN == 1
|
||||||
|
float32 thisdev = 0;
|
||||||
|
#else
|
||||||
|
// float32 dinput = 0.0f;
|
||||||
|
#endif
|
||||||
|
float32 temp_iterm = 0.0f;
|
||||||
|
pid_zh_position_t *pri = &self->pri;
|
||||||
|
|
||||||
|
/*获取期望值与实际值,进行偏差计算*/
|
||||||
|
if (pri->sm == 1)
|
||||||
|
{
|
||||||
|
smoothSetpoint(self, target);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pri->ref = target;
|
||||||
|
}
|
||||||
|
|
||||||
|
pri->feed_back = feedback;
|
||||||
|
error = pri->ref - pri->feed_back;
|
||||||
|
if (fabs(error) <= pri->err_dead)
|
||||||
|
error = 0;
|
||||||
|
|
||||||
|
/* fuzzy control caculate */
|
||||||
|
ec = error - pri->pre_error;
|
||||||
|
if (self->open == TRUE)
|
||||||
|
{
|
||||||
|
compensate(error, ec, &self->fuzzy);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*根据PID配置的模式,获取积分数据,进行积分累加*/
|
||||||
|
if (pri->out >= pri->out_max)
|
||||||
|
{
|
||||||
|
if (fabs(error) > pri->err_limit && pri->detach)
|
||||||
|
{
|
||||||
|
insert = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
insert = 1;
|
||||||
|
if (error < 0)
|
||||||
|
{
|
||||||
|
temp_iterm = (pri->ki + self->fuzzy.ki) * error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (pri->out <= pri->out_min)
|
||||||
|
{
|
||||||
|
if (fabs(error) > pri->err_limit && pri->detach)
|
||||||
|
{
|
||||||
|
insert = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
insert = 1;
|
||||||
|
if (error > 0)
|
||||||
|
{
|
||||||
|
temp_iterm = (pri->ki + self->fuzzy.ki) * error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (fabs(error) > pri->err_limit && pri->detach)
|
||||||
|
{
|
||||||
|
insert = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
insert = 1;
|
||||||
|
temp_iterm = (pri->ki + self->fuzzy.ki) * error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pri->sum_iterm += temp_iterm;
|
||||||
|
/* limt integral */
|
||||||
|
pri->sum_iterm = RANGE(pri->sum_iterm, pri->out_min, pri->out_max);
|
||||||
|
/*
|
||||||
|
if (pri->sum_ref)
|
||||||
|
pri->sum_iterm = RANGE(pri->sum_iterm, pri->sum_ref - 1.0f, pri->sum_ref + 1.0f);
|
||||||
|
else
|
||||||
|
pri->sum_iterm = RANGE(pri->sum_iterm, pri->out_min, pri->out_max);
|
||||||
|
*/
|
||||||
|
#if INCOMPLETE_DIFFEREN == 1
|
||||||
|
/*不完全微分*/
|
||||||
|
thisdev = (pri->kd + self->fuzzy.kd) * (1.0 - pri->alpha) * (error - pri->pre_error) + pri->alpha * pri->lastdev;
|
||||||
|
/*caculate pid out*/
|
||||||
|
pri->out = (pri->kp + self->fuzzy.kp) * error + pri->sum_iterm * insert + thisdev;
|
||||||
|
|
||||||
|
/*record last dev result*/
|
||||||
|
pri->lastdev = thisdev;
|
||||||
|
#else
|
||||||
|
|
||||||
|
if (pri->kd_enable == TRUE)
|
||||||
|
{
|
||||||
|
kd = pri->kd + self->fuzzy.kd;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
kd = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
pri->out = (pri->kp + self->fuzzy.kp) * error + pri->sum_iterm * insert + (error - pri->pre_error) * (kd);
|
||||||
|
// pri->out += pri->sum_ref;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
pri->pre_error = error;
|
||||||
|
/*record last feedback sensor result*/
|
||||||
|
pri->pre_feed_back = pri->feed_back;
|
||||||
|
/*limt pid output*/
|
||||||
|
pri->out = RANGE(pri->out, pri->out_min, pri->out_max);
|
||||||
|
return pri->out;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void pid_zh_constructor(struct PID_FUZZY_ZH *self)
|
||||||
|
{
|
||||||
|
self->set_ctrl_prm = _set_ctrl_prm;
|
||||||
|
self->update_ctrl_prm = _update_ctrl_prm;
|
||||||
|
self->set_cfg = _set_cfg;
|
||||||
|
self->set_smooth_enable = _set_smooth_enable;
|
||||||
|
// self->set_ki_enable = _set_ki_enable;
|
||||||
|
self->set_kd_enable = _set_kd_enable;
|
||||||
|
self->set_range = _set_range;
|
||||||
|
self->restctrl = _restctrl;
|
||||||
|
self->PID = _PID;
|
||||||
|
}
|
|
@ -0,0 +1,73 @@
|
||||||
|
#ifndef __PID_ZH_H__
|
||||||
|
#define __PID_ZH_H__
|
||||||
|
#include "lib.h"
|
||||||
|
#include "pid_auto_tune.h"
|
||||||
|
|
||||||
|
#define GPS2000
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
float32 ref;
|
||||||
|
float32 feed_back;
|
||||||
|
float32 pre_feed_back;
|
||||||
|
float32 pre_error;
|
||||||
|
float32 sum_ref;
|
||||||
|
float32 sum_iterm;
|
||||||
|
float32 kp;
|
||||||
|
float32 ki;
|
||||||
|
float32 kd;
|
||||||
|
float32 err_limit;
|
||||||
|
BOOL detach;
|
||||||
|
float32 err_dead;
|
||||||
|
#if INCOMPLETE_DIFFEREN == 1
|
||||||
|
float32 alpha;
|
||||||
|
float32 lastdev;
|
||||||
|
#endif
|
||||||
|
float32 out;
|
||||||
|
float32 out_max;
|
||||||
|
float32 out_min;
|
||||||
|
float32 sv_range;
|
||||||
|
BOOL sm;
|
||||||
|
BOOL ki_enable;
|
||||||
|
BOOL kd_enable;
|
||||||
|
} pid_zh_position_t; // 位置式PID
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
float32 kp;
|
||||||
|
float32 ki;
|
||||||
|
float32 kd;
|
||||||
|
|
||||||
|
float32 kup;
|
||||||
|
float32 kui;
|
||||||
|
float32 kud;
|
||||||
|
} FUZZY_PID_ZH_t;
|
||||||
|
|
||||||
|
// 模糊PID
|
||||||
|
typedef struct PID_FUZZY_ZH
|
||||||
|
{
|
||||||
|
/* 设置PID三个参数 */
|
||||||
|
void (*set_ctrl_prm)(struct PID_FUZZY_ZH *self, float32 kp, float32 ki, float32 kd, float32 err_dead,
|
||||||
|
float32 out_min, float32 out_max); // 设置PID参数
|
||||||
|
void (*update_ctrl_prm)(struct PID_FUZZY_ZH *self, float32 kp, float32 ki, float32 kd, float32 err_dead,
|
||||||
|
float32 out_min, float32 out_max); // 更新PID参数
|
||||||
|
void (*set_range)(struct PID_FUZZY_ZH *self, float32 out_min, float32 out_max); // 更新最大最小值
|
||||||
|
void (*set_cfg)(struct PID_FUZZY_ZH *self, float32 max_err, BOOL mode); // 配置PID模式,默认不使用积分分离
|
||||||
|
void (*set_smooth_enable)(struct PID_FUZZY_ZH *self, BOOL enable, float32 sv_range); // 设置平滑范围
|
||||||
|
// void (*set_ki_enable)(struct PID_FUZZY *self, BOOL enable);
|
||||||
|
// 微分开启使能
|
||||||
|
void (*set_kd_enable)(struct PID_FUZZY_ZH *self, BOOL enable);
|
||||||
|
void (*restctrl)(struct PID_FUZZY_ZH *self); // 复位PID积分及微分控制数据
|
||||||
|
/* 控制接口 */
|
||||||
|
float32 (*PID)(struct PID_FUZZY_ZH *self, float32 target, float32 feedback);
|
||||||
|
|
||||||
|
pid_zh_position_t pri;
|
||||||
|
|
||||||
|
BOOL open; // 是否使用模糊PID控制
|
||||||
|
|
||||||
|
FUZZY_PID_ZH_t fuzzy;
|
||||||
|
|
||||||
|
} pid_zh_t; // 模糊PID
|
||||||
|
|
||||||
|
extern void pid_zh_constructor(struct PID_FUZZY_ZH *self);
|
||||||
|
#endif
|
|
@ -0,0 +1,619 @@
|
||||||
|
|
||||||
|
#include <math.h>
|
||||||
|
#include "pid_zh1.h"
|
||||||
|
|
||||||
|
// 定义输出量比例因子
|
||||||
|
#define KUP 1.0f
|
||||||
|
#define KUI 1.0f
|
||||||
|
#define KUD 1.0f
|
||||||
|
|
||||||
|
// 模糊集合
|
||||||
|
#define NL -3
|
||||||
|
#define NM -2
|
||||||
|
#define NS -1
|
||||||
|
#define ZE 0
|
||||||
|
#define PS 1
|
||||||
|
#define PM 2
|
||||||
|
#define PL 3
|
||||||
|
|
||||||
|
// 定义偏差E的范围,因为设置了非线性区间,误差在10时才开始进行PID调节,这里E的范围为10
|
||||||
|
#define MAXE (10)
|
||||||
|
#define MINE (-MAXE)
|
||||||
|
// 定义EC的范围,因为变化非常缓慢!,每次的EC都非常小,这里可以根据实际需求来调整,
|
||||||
|
#define MAXEC (10)
|
||||||
|
#define MINEC (-MAXEC)
|
||||||
|
// 定义e,ec的量化因子
|
||||||
|
#define KE 3 / MAXE
|
||||||
|
#define KEC 3 / MAXEC
|
||||||
|
/*
|
||||||
|
static const float fuzzyRuleKp[7][7] = {
|
||||||
|
PL, PL, PM, PL, PS, PM, PL,
|
||||||
|
PL, PM, PM, PM, PS, PM, PL,
|
||||||
|
PM, PS, PS, PS, PS, PS, PM,
|
||||||
|
PM, PS, ZE, ZE, ZE, PS, PM,
|
||||||
|
PS, PS, PS, PS, PS, PM, PM,
|
||||||
|
PM, PM, PM, PM, PL, PL, PL,
|
||||||
|
PM, PL, PL, PL, PL, PL, PL};
|
||||||
|
|
||||||
|
static const float fuzzyRuleKi[7][7] = {
|
||||||
|
PL, PL, PL, PL, PM, PL, PL,
|
||||||
|
PL, PL, PM, PM, PM, PL, PL,
|
||||||
|
PM, PM, PS, PS, PS, PM, PM,
|
||||||
|
PM, PS, ZE, ZE, ZE, PS, PM,
|
||||||
|
PM, PS, PS, PS, PS, PM, PM,
|
||||||
|
PM, PM, PS, PM, PM, PL, PL,
|
||||||
|
PM, PL, PM, PL, PL, PL, PL};
|
||||||
|
|
||||||
|
static const float fuzzyRuleKd[7][7] = {
|
||||||
|
PS, PS, ZE, ZE, ZE, PL, PL,
|
||||||
|
PS, PS, PS, PS, ZE, PS, PM,
|
||||||
|
PL, PL, PM, PS, ZE, PS, PM,
|
||||||
|
PL, PM, PM, PS, ZE, PS, PM,
|
||||||
|
PL, PM, PS, PS, ZE, PS, PS,
|
||||||
|
PM, PS, PS, PS, ZE, PS, PS,
|
||||||
|
PS, ZE, ZE, ZE, ZE, PL, PL};
|
||||||
|
*/
|
||||||
|
static const float fuzzyRuleKp[7][7] = {
|
||||||
|
PL, PL, PM, PL, PS, PM, PL,
|
||||||
|
PL, PM, PM, PM, PS, PM, PL,
|
||||||
|
PM, PS, PS, PS, PS, PS, PM,
|
||||||
|
PM, PS, ZE, ZE, ZE, PS, PM,
|
||||||
|
PS, PS, PS, PS, PS, PM, PM,
|
||||||
|
PM, PM, PM, PM, PL, PL, PL,
|
||||||
|
PM, PL, PL, PL, PL, PL, PL};
|
||||||
|
|
||||||
|
static const float fuzzyRuleKi[7][7] = {
|
||||||
|
PL, PL, PL, PL, PM, PL, PL,
|
||||||
|
PL, PL, PM, PM, PM, PL, PL,
|
||||||
|
PM, PM, PS, PS, PS, PM, PM,
|
||||||
|
PM, PS, ZE, ZE, ZE, PS, PM,
|
||||||
|
PM, PS, PS, PS, PS, PM, PM,
|
||||||
|
PM, PM, PS, PM, PM, PL, PL,
|
||||||
|
PM, PL, PM, PL, PL, PL, PL};
|
||||||
|
|
||||||
|
static const float fuzzyRuleKd[7][7] = {
|
||||||
|
PS, PS, ZE, ZE, ZE, PL, PL,
|
||||||
|
PS, PS, PS, PS, ZE, PS, PM,
|
||||||
|
PL, PL, PM, PS, ZE, PS, PM,
|
||||||
|
PL, PM, PM, PS, ZE, PS, PM,
|
||||||
|
PL, PM, PS, PS, ZE, PS, PS,
|
||||||
|
PM, PS, PS, PS, ZE, PS, PS,
|
||||||
|
PS, ZE, ZE, ZE, ZE, PL, PL};
|
||||||
|
|
||||||
|
static void fuzzy(float e, float ec, fuzzy_pid_t *fuzzy_pid)
|
||||||
|
{
|
||||||
|
|
||||||
|
float etemp, ectemp;
|
||||||
|
float eLefttemp, ecLefttemp; // 左隶属度
|
||||||
|
float eRighttemp, ecRighttemp; // 右隶属度
|
||||||
|
|
||||||
|
int eLeftIndex, ecLeftIndex; // 模糊位置标号
|
||||||
|
int eRightIndex, ecRightIndex;
|
||||||
|
e = RANGE(e, MINE, MAXE);
|
||||||
|
ec = RANGE(ec, MINEC, MAXEC);
|
||||||
|
e = e * KE;
|
||||||
|
ec = ec * KEC;
|
||||||
|
|
||||||
|
etemp = e > 3.0f ? 0.0f : (e < -3.0f ? 0.0f : (e >= 0.0f ? (e >= 2.0f ? 2.5f : (e >= 1.0f ? 1.5f : 0.5f)) : (e >= -1.0f ? -0.5f : (e >= -2.0f ? -1.5f : (e >= -3.0f ? -2.5f : 0.0f)))));
|
||||||
|
eLeftIndex = (int)((etemp - 0.5f) + 3);
|
||||||
|
eRightIndex = (int)((etemp + 0.5f) + 3);
|
||||||
|
eLefttemp = etemp == 0.0f ? 0.0f : ((etemp + 0.5f) - e);
|
||||||
|
eRighttemp = etemp == 0.0f ? 0.0f : (e - (etemp - 0.5f));
|
||||||
|
|
||||||
|
ectemp = ec > 3.0f ? 0.0f : (ec < -3.0f ? 0.0f : (ec >= 0.0f ? (ec >= 2.0f ? 2.5f : (ec >= 1.0f ? 1.5f : 0.5f)) : (ec >= -1.0f ? -0.5f : (ec >= -2.0f ? -1.5f : (ec >= -3.0f ? -2.5f : 0.0f)))));
|
||||||
|
ecLeftIndex = (int)((ectemp - 0.5f) + 3);
|
||||||
|
ecRightIndex = (int)((ectemp + 0.5f) + 3);
|
||||||
|
ecLefttemp = ectemp == 0.0f ? 0.0f : ((ectemp + 0.5f) - ec);
|
||||||
|
ecRighttemp = ectemp == 0.0f ? 0.0f : (ec - (ectemp - 0.5f));
|
||||||
|
|
||||||
|
/*************************************反模糊*************************************/
|
||||||
|
|
||||||
|
fuzzy_pid->kp = (eLefttemp * ecLefttemp * fuzzyRuleKp[eLeftIndex][ecLeftIndex] + eLefttemp * ecRighttemp * fuzzyRuleKp[eLeftIndex][ecRightIndex] + eRighttemp * ecLefttemp * fuzzyRuleKp[eRightIndex][ecLeftIndex] + eRighttemp * ecRighttemp * fuzzyRuleKp[eRightIndex][ecRightIndex]);
|
||||||
|
|
||||||
|
fuzzy_pid->ki = (eLefttemp * ecLefttemp * fuzzyRuleKi[eLeftIndex][ecLeftIndex] + eLefttemp * ecRighttemp * fuzzyRuleKi[eLeftIndex][ecRightIndex] + eRighttemp * ecLefttemp * fuzzyRuleKi[eRightIndex][ecLeftIndex] + eRighttemp * ecRighttemp * fuzzyRuleKi[eRightIndex][ecRightIndex]);
|
||||||
|
|
||||||
|
fuzzy_pid->kd = (eLefttemp * ecLefttemp * fuzzyRuleKd[eLeftIndex][ecLeftIndex] + eLefttemp * ecRighttemp * fuzzyRuleKd[eLeftIndex][ecRightIndex] + eRighttemp * ecLefttemp * fuzzyRuleKd[eRightIndex][ecLeftIndex] + eRighttemp * ecRighttemp * fuzzyRuleKd[eRightIndex][ecRightIndex]);
|
||||||
|
// 对解算出的KP,KI,KD进行量化映射
|
||||||
|
fuzzy_pid->kp = fuzzy_pid->kp * fuzzy_pid->kup;
|
||||||
|
fuzzy_pid->ki = fuzzy_pid->ki * fuzzy_pid->kui;
|
||||||
|
fuzzy_pid->kd = fuzzy_pid->kd * fuzzy_pid->kud;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void smooth_init(smart_pid_t *pid, BOOL sm_open, float maxTarget)
|
||||||
|
{
|
||||||
|
if (!pid)
|
||||||
|
return;
|
||||||
|
|
||||||
|
pid->sm_open = sm_open;
|
||||||
|
pid->maxTarget = maxTarget;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void smooth_target(smart_pid_t *pid, float *target)
|
||||||
|
{
|
||||||
|
|
||||||
|
if ((!pid) || (!target))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!pid->maxTarget)
|
||||||
|
return;
|
||||||
|
|
||||||
|
float sm_step = (pid->maxTarget) * 0.1f;
|
||||||
|
float k = 0.0f;
|
||||||
|
|
||||||
|
if (fabs(pid->target - *target) <= sm_step)
|
||||||
|
{
|
||||||
|
pid->target = *target;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (pid->target - *target > 0)
|
||||||
|
{
|
||||||
|
k = -1.0f;
|
||||||
|
}
|
||||||
|
else if (pid->target - *target < 0)
|
||||||
|
{
|
||||||
|
k = 1.0f;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
k = 0.0f;
|
||||||
|
}
|
||||||
|
pid->target += k * sm_step;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void smart_pid_init(smart_pid_t *pid, float *duty, float *kp, float *ki, float *kd, float *errorDead, float *iDetachCondation, float *maxOut)
|
||||||
|
{
|
||||||
|
if ((!pid) || (!duty) || (!kp) || (!ki) || (!kd) || (!iDetachCondation) || (!maxOut))
|
||||||
|
return;
|
||||||
|
|
||||||
|
pid->duty = *duty;
|
||||||
|
pid->kp = *kp;
|
||||||
|
pid->ki = *ki;
|
||||||
|
pid->kd = *kd;
|
||||||
|
pid->errorDead = *errorDead;
|
||||||
|
pid->iDetachCondation = *iDetachCondation;
|
||||||
|
pid->maxOutput = *maxOut;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cascade_pid_init(cascade_pid_t *pid, smart_pid_t *pid_outer, smart_pid_t *pid_inner)
|
||||||
|
{
|
||||||
|
|
||||||
|
smooth_init(&pid->outer, pid_outer->sm_open, pid_outer->maxTarget);
|
||||||
|
smooth_init(&pid->inner, pid_inner->sm_open, pid_inner->maxTarget);
|
||||||
|
|
||||||
|
smart_pid_init(&pid->outer, &pid_outer->duty, &pid_outer->kp, &pid_outer->ki, &pid_outer->kd, &pid_outer->errorDead, &pid_outer->iDetachCondation, &pid_outer->maxOutput);
|
||||||
|
smart_pid_init(&pid->inner, &pid_inner->duty, &pid_inner->kp, &pid_inner->ki, &pid_inner->kd, &pid_inner->errorDead, &pid_inner->iDetachCondation, &pid_inner->maxOutput);
|
||||||
|
}
|
||||||
|
|
||||||
|
void smart_pid_calc(smart_pid_t *pid, float *target, float *feedback)
|
||||||
|
{
|
||||||
|
// 将旧error存起来
|
||||||
|
pid->lastError = pid->error;
|
||||||
|
// 平滑处理目标值
|
||||||
|
if (pid->sm_open == TRUE)
|
||||||
|
smooth_target(pid, target);
|
||||||
|
else
|
||||||
|
pid->target = *target;
|
||||||
|
// 计算新error
|
||||||
|
pid->error = pid->target - *feedback;
|
||||||
|
if (fabs(pid->error) <= pid->errorDead)
|
||||||
|
pid->error = 0.0f;
|
||||||
|
// 计算误差变化
|
||||||
|
pid->dError = pid->error - pid->lastError;
|
||||||
|
// 选用模糊规则
|
||||||
|
if (pid->fuzzy_open == TRUE)
|
||||||
|
{
|
||||||
|
fuzzy(pid->error, pid->dError, &pid->fuzzy_pid);
|
||||||
|
}
|
||||||
|
// 计算微分
|
||||||
|
float dout = pid->dError * (pid->kd + pid->fuzzy_pid.kd);
|
||||||
|
// 计算比例
|
||||||
|
float pout = pid->error * (pid->kp + pid->fuzzy_pid.kp);
|
||||||
|
// 积分分离
|
||||||
|
if (fabs(pid->error) <= pid->iDetachCondation)
|
||||||
|
{
|
||||||
|
pid->integral += pid->error * (pid->ki + pid->fuzzy_pid.ki);
|
||||||
|
pid->iDetach = FALSE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pid->iDetach = TRUE;
|
||||||
|
pid->integral = 0;
|
||||||
|
}
|
||||||
|
// 积分限幅
|
||||||
|
if (pid->integral > pid->maxOutput)
|
||||||
|
pid->integral = pid->maxOutput;
|
||||||
|
else if (pid->integral < -pid->maxOutput)
|
||||||
|
pid->integral = -pid->maxOutput;
|
||||||
|
// 计算输出
|
||||||
|
pid->output = pout + dout + pid->integral * (!pid->iDetach);
|
||||||
|
// 输出限幅
|
||||||
|
if (pid->output > pid->maxOutput)
|
||||||
|
pid->output = pid->maxOutput;
|
||||||
|
else if (pid->output < -pid->maxOutput)
|
||||||
|
pid->output = -pid->maxOutput;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cascade_pid_calc(struct CascadePID *pid, float *outerRef, float *outerFdb, float *innerFdb)
|
||||||
|
{
|
||||||
|
// 外环位置控制
|
||||||
|
smart_pid_calc(&pid->cascade_pid.outer, outerRef, outerFdb);
|
||||||
|
// 内环速度控制
|
||||||
|
smart_pid_calc(&pid->cascade_pid.inner, &pid->cascade_pid.outer.output, innerFdb);
|
||||||
|
// 内环输出就是串级PID的输出
|
||||||
|
// pid->cascade_pid.output = pid->cascade_pid.inner.output;
|
||||||
|
pid->cascade_pid.output = pid->cascade_pid.outer.output;
|
||||||
|
}
|
||||||
|
|
||||||
|
void pid_zh_constructor1(struct CascadePID *pid)
|
||||||
|
{
|
||||||
|
pid->smart_pid_init = smart_pid_init;
|
||||||
|
pid->smart_pid_calc = smart_pid_calc;
|
||||||
|
pid->cascade_pid_init = cascade_pid_init;
|
||||||
|
pid->cascade_pid_calc = cascade_pid_calc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
典型输入信号
|
||||||
|
L[1] -> 1/s
|
||||||
|
L[t] -> 1/s^2
|
||||||
|
L[1/2t^2] -> 1/s^3
|
||||||
|
系统传递函数
|
||||||
|
G(s) = k/(TS+1)
|
||||||
|
G(s) = k/S^i(TS+1)
|
||||||
|
i = 0 0型系统 i = 1 I 型系统 I = 2 II 型系统
|
||||||
|
系统开环传递函数: G(s)
|
||||||
|
系统闭环传递函数: G闭(s) = G(s) / 1 + G(s)
|
||||||
|
系统静差: R(s) = 1/1+G(s)
|
||||||
|
终值定理:limf(t) = lim s*G(s)
|
||||||
|
t->无穷 s->0
|
||||||
|
o型系统,单位输入:r/s
|
||||||
|
e = lim f(t) = lim s*G(s) = G(s) = k/1+G(s) = k/ 1 + (Ts+1+k)..
|
||||||
|
t->无穷 s->0 s->0 s->0 = s->0
|
||||||
|
*系统误差有给定和扰动引起的
|
||||||
|
*线性系统符合叠加原理
|
||||||
|
*动态性能指标
|
||||||
|
超调 、过度过程时间、上升时间 tr 延迟时间 td 峰值指标tp
|
||||||
|
误差积分指标大 好小 好?
|
||||||
|
典型二阶系统
|
||||||
|
G(s) = 1/ s^2 *(2ξwn)s + wn^2
|
||||||
|
ξ:阻尼系统
|
||||||
|
wn = 1/T:震荡频率
|
||||||
|
如果有一个极点和零点很接近,可以忽略该极点。
|
||||||
|
主导极点用二阶系统定义的
|
||||||
|
开环传递函数 K T
|
||||||
|
复变函数
|
||||||
|
频率特性
|
||||||
|
阻容RC电路 一阶低通滤波器 一阶惰性系统
|
||||||
|
Gs = 1/Ts+1
|
||||||
|
正弦稳态
|
||||||
|
|
||||||
|
控制系统设计依据:
|
||||||
|
考虑到被控对象包含 弹簧储能、填料阻尼、EPM气压控制等主导环节,忽略其它非主导惯性、阻尼环节,将被控系统模型归纳为典型二阶阻尼震荡系统:
|
||||||
|
被控对象开环传递函数:G(s) = wn^2/ s*( s + 2ξwn)
|
||||||
|
未加控制器被控对象闭环传递函数:G(s) = wn^2/ (s^2 + (2ξwn)s + wn^2)
|
||||||
|
ξ :为系统阻尼比。跟阀座填料材、压力正相关(忽略其他非主导阻尼环节)
|
||||||
|
Wn :无阻尼自然震荡角频率。跟弹簧的固有振荡频率正相关(忽略其他非主导惯性环节)
|
||||||
|
|
||||||
|
阀杆填料阻尼比: 0 < ξ < 1
|
||||||
|
|
||||||
|
系统特征方程s^2 + (2ξwn)s + wn^2 = 0 时,有两个共轭复根,要想系统稳定,根的实部要远离虚轴,且在允许情况下,越远越稳定。
|
||||||
|
标准二阶系统是零型系统,存在静差。而且,考虑气体压缩比大,导致系统的惯性环节增大。
|
||||||
|
因此需要控制器将系统变为I型系统来消除静差(增加积分环节),而且需要在控制器传递函数的零点增加最小项来克服系统的大惯性(增加微分环节)。因此,设计控制器类型为PID控制器。
|
||||||
|
|
||||||
|
※ 难点在于系统的无阻尼自然震荡角频率和阀座阻尼系数无法准确获得,整定算法计算的特性参数不一定合理。
|
||||||
|
※ 另一个难点在于EPM本身的控制特性线性度差,会导致控制器的矫正环节达不到理想效果或在部分区间达不到理想效果,因此,
|
||||||
|
系统会不稳定或在部分区间不稳定。
|
||||||
|
※ EMP本身的控制线性度差,通过控制器弥补EPM性能的不足。
|
||||||
|
(因为阀杆速度变化快慢,直接由EPM IP开度大小决定,因此考虑增加阀杆速度环控制来弥补EPM本身的不足)
|
||||||
|
|
||||||
|
算法核心原理说明 :
|
||||||
|
核心算法: PID
|
||||||
|
u(t) = k*(e(t) +∫e(t)dt + de(t)dt)
|
||||||
|
u(n) = k*(e(n) + ∑e(n)/Ti + Td*(e(n) - e(n-1)))
|
||||||
|
|
||||||
|
位置控制:PID + PD控制
|
||||||
|
误差在[-5%,5%] 内 PID 控制,控制静差 < 0.3%
|
||||||
|
误差在[-100%,5%] 或 [5%,100%] 时,PD控制,防止积分引起的系统不稳定
|
||||||
|
|
||||||
|
积分分离:当误差<= 5% 时,加入积分
|
||||||
|
当误差> 5%时,积分分离、积分项清零
|
||||||
|
积分限幅:
|
||||||
|
当积分项 >= 100% 积分项 = 100%
|
||||||
|
当积分项 <= -100% 积分项 = -100%
|
||||||
|
|
||||||
|
整定算法: 继电反馈整定
|
||||||
|
设定目标位置:额定行程 60%
|
||||||
|
控制初始位置: < 60%
|
||||||
|
施加最大控制量 ->检测实时位置->过零,计t0、上冲峰值 -> 施加最小控制量 -> 检测实时位置 -> 过零,计t1、下冲峰值— ↓
|
||||||
|
↑ <—————————————————————————————————————————————————————————————————————————————————————————————————|
|
||||||
|
|
||||||
|
循环三次,记录系统稳态下波峰、波谷,和震荡周期Tu
|
||||||
|
计算: Ku = (控制量最大值 - 控制量最小值)/ (位置波峰 - 位置波谷)
|
||||||
|
查表:Kp = 0.8 * Ku
|
||||||
|
Ti = 0.6 * Tu
|
||||||
|
Td = 0.125 * Tu
|
||||||
|
Ki = Kp / Ti = Kp / (0.6 * Tu)
|
||||||
|
Kd = Kp * Td = Kp * 0.125 * Td
|
||||||
|
|
||||||
|
速度控制算法:
|
||||||
|
s1:初始位置AD值
|
||||||
|
s2:单位时间位置移动后AD值
|
||||||
|
v1:当前速度
|
||||||
|
v2: 前速度
|
||||||
|
v: 实时速度
|
||||||
|
a:实时加速度
|
||||||
|
t: 速度计算周期
|
||||||
|
v = (s2 - s1) / t
|
||||||
|
a = (v2 - v1) / t
|
||||||
|
|
||||||
|
整定过程,分别整定上升过程平均速度和下降过程平均速度。
|
||||||
|
分别以上升和下降速度为PID 内环参考速度,计算速度控制量。
|
||||||
|
速度偏差 = 当前速度 - 参考速度
|
||||||
|
加速度 = 速度偏差变化(即位置的二阶导数)
|
||||||
|
速度控制量 = Kp*速度偏差 + Ki * ∑速度偏差 + Kd * 加速度
|
||||||
|
|
||||||
|
串级控制
|
||||||
|
外环位置检测,进行速度控制
|
||||||
|
内环速度检测,进行位置控制
|
||||||
|
位置偏差 = 位置给定 - 位置反馈
|
||||||
|
位置偏差变化 = 位置偏差 - 上次位置偏差
|
||||||
|
速度控制量 = Kp1*位置偏差 + Ki1 * ∑位置偏差 + Kd1 * 位置偏差变化
|
||||||
|
速度偏差 = 速度控制量 - 速度反馈
|
||||||
|
速度偏差变化 = 速度偏差 - 上次速度偏差
|
||||||
|
位置控制量 = Kp2*速度偏差 + Ki2 * ∑速度偏差 + Kd2 * 速度偏差变化
|
||||||
|
串级速度整定:???
|
||||||
|
|
||||||
|
automatic control theory
|
||||||
|
control system
|
||||||
|
linear and nonlinear system
|
||||||
|
线性连续系统
|
||||||
|
离散系统
|
||||||
|
modelling
|
||||||
|
analysis
|
||||||
|
矫正
|
||||||
|
分析 时域分析方法 微分方程 传递函数 一阶系统 二阶系统
|
||||||
|
频域分析方法 闭环特性 低频特性 高频特性
|
||||||
|
根轨迹
|
||||||
|
建模 分析 矫正
|
||||||
|
离散系统
|
||||||
|
非线性控制理论
|
||||||
|
L变换 Z变换
|
||||||
|
采样控制系统 数字控制系统
|
||||||
|
条件稳定系统
|
||||||
|
problems
|
||||||
|
time consuming
|
||||||
|
行列式计算
|
||||||
|
相对稳定性
|
||||||
|
劳斯准则只能判断系统是否稳定,不能判断稳定程度
|
||||||
|
伯德图
|
||||||
|
nyquist 图
|
||||||
|
相位裕度
|
||||||
|
闭环特征方程的根闭,开环增益0到无穷 特征方程根的变化规律
|
||||||
|
root locus
|
||||||
|
单位负反馈
|
||||||
|
G(s) = k/s(s+1)
|
||||||
|
复角条件复值条件
|
||||||
|
渐近线与实轴交点
|
||||||
|
出射角p-n/n-m
|
||||||
|
|
||||||
|
lambda
|
||||||
|
大纯滞后
|
||||||
|
积分对象
|
||||||
|
lambda
|
||||||
|
纯滞后 tao/t
|
||||||
|
斯密斯预估 闭环传递函数 整定方法
|
||||||
|
阶跃响应 鲁棒性 积分过程 输入干扰
|
||||||
|
执行机构偏离,不确定不准确,调整速度
|
||||||
|
PI 为主 D
|
||||||
|
两自由度PID 比例积分先行
|
||||||
|
鲁棒性 性能不完全微分
|
||||||
|
负载扰
|
||||||
|
|
||||||
|
makefile 工作原理:
|
||||||
|
1、可执行文件生成过程:预处理->编译->链接
|
||||||
|
#source object target
|
||||||
|
SRC := *.c
|
||||||
|
OBJ := *.o
|
||||||
|
TARGET := mqtt_test
|
||||||
|
|
||||||
|
#compile library include
|
||||||
|
CC := cc
|
||||||
|
LIB:= -lpthread
|
||||||
|
LDFLAG := -L. libmosquitto.so
|
||||||
|
CFLAG :=
|
||||||
|
CXXFLAG :=
|
||||||
|
#link
|
||||||
|
$(TARGET):$(OBJ)
|
||||||
|
$(CC) -o $(TARGET) $(BOJ) $(LIB) $(LDFLAG)
|
||||||
|
$(CC) -o $@ $^ $(LIB) $(LDFLAG)
|
||||||
|
$(OBJ):$(SRC)
|
||||||
|
$(CC) -c $(SRC)
|
||||||
|
#all
|
||||||
|
all:$(TARGET)
|
||||||
|
$(CC) -o $(TARGET) $(SRC) $(LIB) $(LDFLAG)
|
||||||
|
#clean
|
||||||
|
clean:
|
||||||
|
rm -rf *.o $(TARGET)
|
||||||
|
*/
|
||||||
|
// ————————————————————————————————————
|
||||||
|
|
||||||
|
/*
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
int argc;
|
||||||
|
char **argv;
|
||||||
|
int sock;
|
||||||
|
}st_app_param;
|
||||||
|
|
||||||
|
const char *g_version = "V1.0.0 24.08.16";
|
||||||
|
int child_mian_ini()
|
||||||
|
{
|
||||||
|
int i_re;
|
||||||
|
i_re = gw_support_init();
|
||||||
|
if(i_re < 0)
|
||||||
|
{
|
||||||
|
printf("解析支持文件错误.\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
i_re = gw_config_init();
|
||||||
|
if(i_re < 0)
|
||||||
|
{
|
||||||
|
printf("解析配置文件错误.\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
i_re = gw_data_init();
|
||||||
|
if(i_re < 0)
|
||||||
|
{
|
||||||
|
printf("数据初始化错误.\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
i_re = gw_modol_init();
|
||||||
|
if(i_re < 0)
|
||||||
|
{
|
||||||
|
printf("解析模型文件错误.\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
i_re = gw_stat_init();
|
||||||
|
if(i_re < 0)
|
||||||
|
{
|
||||||
|
printf("数据统计初始化错误.\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
i_re = gw_process_init();
|
||||||
|
if(i_re < 0)
|
||||||
|
{
|
||||||
|
printf("规约初始化错误.\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
i_re = gw_manage_init();
|
||||||
|
if(i_re < 0)
|
||||||
|
{
|
||||||
|
printf("界面通讯初始化错误.\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
pthread_create(tid,thread_task1,p_param);
|
||||||
|
|
||||||
|
while(1)
|
||||||
|
{
|
||||||
|
get_sys_time();
|
||||||
|
sleep(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int child_main(int argc,char **argv)
|
||||||
|
{
|
||||||
|
|
||||||
|
if((argc == 2)&&(strcasecmp(argv[1],"-version") == 0))
|
||||||
|
{
|
||||||
|
printf("version [%s]",g_version);
|
||||||
|
}
|
||||||
|
|
||||||
|
child_mian_ini();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static int run_child_process_thread((void *)param)
|
||||||
|
{
|
||||||
|
st_app_param *p_param;
|
||||||
|
|
||||||
|
p_param = param;
|
||||||
|
chlid_main(p_parm->argc,p_param->argv);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int run_child_process(int argc,char **argv,int sock)
|
||||||
|
{
|
||||||
|
int i_re;
|
||||||
|
pthread_t *tid;
|
||||||
|
st_app_param p_param;
|
||||||
|
|
||||||
|
p_param.argc = argc;
|
||||||
|
p_param.argv = argv;
|
||||||
|
p_param.sock = sock;
|
||||||
|
|
||||||
|
pthread_creat(tid,run_child_process_thread,(void *)p_param);
|
||||||
|
i_re = recv(sock,..,0);//阻塞接收
|
||||||
|
send(sock,'q',0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc,char**argv)
|
||||||
|
{
|
||||||
|
int i_re,fd,pid;
|
||||||
|
char lock_file[16];
|
||||||
|
socketpair sockpaire[2];
|
||||||
|
|
||||||
|
sprintf(lock_file,"%s.lock",argv[0]);
|
||||||
|
|
||||||
|
fd = open(lock_file,_O_WRONLY|_EXC,0777);
|
||||||
|
if(fd < 0)
|
||||||
|
{
|
||||||
|
printf("应用:[%s]已运行.\n",argv[0]);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
sockpaire[0] = -1;
|
||||||
|
|
||||||
|
while(1)
|
||||||
|
{
|
||||||
|
i_re = socketpaire(sockpaire,AN_UNIX,..);
|
||||||
|
if(i_re < 0)
|
||||||
|
{
|
||||||
|
printf("[%d]创建sockpaire失败.\n",getpid());
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
pid = fork();
|
||||||
|
|
||||||
|
if(pid < 0)
|
||||||
|
{
|
||||||
|
printf("[%d]创建进程失败.\n",getpid());
|
||||||
|
close(sockpaire[0]);
|
||||||
|
sockpaire[0] = -1
|
||||||
|
close(sockpaire[1]);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(pid == 0)//child process
|
||||||
|
{
|
||||||
|
close(sockpair[0]);
|
||||||
|
return run_child_process(argc,argv,sockpair[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("[%d]创建子进程成功.\n",getpid());
|
||||||
|
close(sockpair[1]);
|
||||||
|
while(1)//father process
|
||||||
|
{
|
||||||
|
i_re = recv(sockpaire[0],....,0);//阻塞接收
|
||||||
|
if(i_re <= 0)
|
||||||
|
{
|
||||||
|
//连接中断,重连
|
||||||
|
sockpaire[0] = -1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//正常退出
|
||||||
|
goto EXIT:
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
EXIT:
|
||||||
|
//退出操作
|
||||||
|
if(sockpaire[0] == -1)
|
||||||
|
{
|
||||||
|
//有子进程,关闭子进程
|
||||||
|
}
|
||||||
|
close(fd);
|
||||||
|
unlink(file_lock);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
|
@ -0,0 +1,63 @@
|
||||||
|
/*
|
||||||
|
* @Author: 张小明 zxm5337@163.com
|
||||||
|
* @Date: 2024-06-25 10:26:36
|
||||||
|
* @LastEditors: DaMingSY zxm5337@163.com
|
||||||
|
* @LastEditTime: 2024-09-03 09:19:23
|
||||||
|
* @FilePath: \controller-v2\User\lib\control\custom\cascade_pid_zh.h
|
||||||
|
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
|
||||||
|
*/
|
||||||
|
#ifndef __CASCADE_PID_ZH__
|
||||||
|
#define __CASCADE_PID_ZH__
|
||||||
|
|
||||||
|
#include "data_type_def.h"
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
TARGET_DIR_ADD,
|
||||||
|
TARGET_DIR_SUB,
|
||||||
|
} target_dir_e;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
float kp;
|
||||||
|
float ki;
|
||||||
|
float kd;
|
||||||
|
|
||||||
|
float kup;
|
||||||
|
float kui;
|
||||||
|
float kud;
|
||||||
|
} fuzzy_pid_t;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
BOOL iDetach, sm_open, fuzzy_open;
|
||||||
|
float feedBack;
|
||||||
|
float target, maxTarget;
|
||||||
|
float duty, kp, ki, kd;
|
||||||
|
float error, dError, lastError, errorDead;
|
||||||
|
float integral, iDetachCondation;
|
||||||
|
float output, maxOutput;
|
||||||
|
fuzzy_pid_t fuzzy_pid;
|
||||||
|
} smart_pid_t;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
smart_pid_t inner;
|
||||||
|
smart_pid_t outer;
|
||||||
|
float output;
|
||||||
|
} cascade_pid_t;
|
||||||
|
|
||||||
|
typedef struct CascadePID
|
||||||
|
{
|
||||||
|
void (*smart_pid_init)(smart_pid_t *pid, float *duty, float *kp, float *ki, float *kd, float *errorDead, float *iDetachCondation, float *maxOut);
|
||||||
|
void (*cascade_pid_init)(cascade_pid_t *pid, smart_pid_t *pid_outer, smart_pid_t *pid_inner);
|
||||||
|
void (*smart_pid_calc)(smart_pid_t *pid, float *target, float *feedback);
|
||||||
|
void (*cascade_pid_calc)(struct CascadePID *pid, float *outerRef, float *outerFdb, float *innerFdb);
|
||||||
|
|
||||||
|
smart_pid_t smart_pid;
|
||||||
|
cascade_pid_t cascade_pid;
|
||||||
|
} pid_zh1_t; // PID_t;
|
||||||
|
|
||||||
|
extern void pid_zh_constructor1(struct CascadePID *pid);
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,26 @@
|
||||||
|
# 架构
|
||||||
|
|文件|路径| <div style="width:300px">说明</div>|
|
||||||
|
|:--|:--|:--|
|
||||||
|
|pid|User\lib\control\src|PID算法模块|
|
||||||
|
|execute|User\application\src|执行器|
|
||||||
|
|app_flow|User|任务流程控制|
|
||||||
|
|
||||||
|
## APP_FLOW任务流程控制
|
||||||
|
> adjust_inspection 中在没有检测到调试信号时执行<b style="color:blue">execute_dac,EXECUTE_PLAN</b>定义了需要执行的算法任务计划
|
||||||
|
|
||||||
|
## PID算法模块
|
||||||
|
文件内容:
|
||||||
|
|文件| <div style="width:300px">说明</div>|
|
||||||
|
|:--|:--|
|
||||||
|
|pid.c|构造算法的入口|
|
||||||
|
|pid_common.c|普通算法|
|
||||||
|
|pid_neural.c|神经网络算法|
|
||||||
|
|pid_fuzzy.c|模糊算法|
|
||||||
|
|
||||||
|
<b style="color:blue">custom 目录下为各自算法实现</b>
|
||||||
|
|
||||||
|
|
||||||
|
## EXECUTE执行器
|
||||||
|
> execute_pid_init中定义了初始化参数
|
||||||
|
> execute_dac中定义了执行器
|
||||||
|
|
|
@ -1,9 +1,17 @@
|
||||||
#ifndef __PID_H__
|
#ifndef __PID_H__
|
||||||
#define __PID_H__
|
#define __PID_H__
|
||||||
#include "lib.h"
|
#include "lib.h"
|
||||||
|
|
||||||
#include "pid_auto_tune.h"
|
#include "pid_auto_tune.h"
|
||||||
|
|
||||||
#define INCOMPLETE_DIFFEREN 0 // 不完全微分
|
#include "pid_c.h"
|
||||||
|
#include "pid_g.h"
|
||||||
|
#include "pid_x.h"
|
||||||
|
#include "pid_zh.h"
|
||||||
|
#include "pid_zh1.h"
|
||||||
|
#include "pid_hd.h"
|
||||||
|
|
||||||
|
#define INCOMPLETE_DIFFEREN 1 // 不完全微分
|
||||||
|
|
||||||
typedef enum
|
typedef enum
|
||||||
{
|
{
|
||||||
|
@ -54,6 +62,7 @@ typedef struct
|
||||||
float32 err_limit;
|
float32 err_limit;
|
||||||
BOOL detach;
|
BOOL detach;
|
||||||
float32 err_dead;
|
float32 err_dead;
|
||||||
|
// 不完全微分方式在微分环节采用了低通滤波有效地提高了微分项的特性。其中α的取值是一个0~1之间的数。两个极限值,在0时其实就是没有滤波的普通微分环节;而取1时,则没有微分作用。所以α的取值对不完全微分的效果是至关重要的,一般要根据被控对象的特性来确定
|
||||||
float32 alpha;
|
float32 alpha;
|
||||||
float32 lastdev;
|
float32 lastdev;
|
||||||
float32 out;
|
float32 out;
|
||||||
|
@ -219,6 +228,14 @@ typedef struct
|
||||||
pid_common_t common;
|
pid_common_t common;
|
||||||
pid_neural_t neural;
|
pid_neural_t neural;
|
||||||
pid_fuzzy_t fuzzy;
|
pid_fuzzy_t fuzzy;
|
||||||
|
|
||||||
|
// 自定义PID
|
||||||
|
pid_c_t cao;
|
||||||
|
pid_g_t gao;
|
||||||
|
pid_x_t xu;
|
||||||
|
pid_zh_t zhang;
|
||||||
|
pid_zh1_t zhang1;
|
||||||
|
pid_hd_t hd;
|
||||||
} pid_u;
|
} pid_u;
|
||||||
pid_auto_tune_t auto_tune;
|
pid_auto_tune_t auto_tune;
|
||||||
} pid_t;
|
} pid_t;
|
|
@ -20,6 +20,22 @@ void pid_constructor(pid_t *self)
|
||||||
case PID_TYPE_AUTO_TUNE:
|
case PID_TYPE_AUTO_TUNE:
|
||||||
pid_auto_tune_constructor(&self->auto_tune);
|
pid_auto_tune_constructor(&self->auto_tune);
|
||||||
break;
|
break;
|
||||||
|
case PID_TYPE_CUSTOM_CAO:
|
||||||
|
pid_c_constructor(&self->pid_u.cao);
|
||||||
|
break;
|
||||||
|
case PID_TYPE_CUSTOM_GAO:
|
||||||
|
pid_g_constructor(&self->pid_u.gao);
|
||||||
|
break;
|
||||||
|
case PID_TYPE_CUSTOM_XU:
|
||||||
|
pid_x_constructor(&self->pid_u.xu);
|
||||||
|
break;
|
||||||
|
case PID_TYPE_CUSTOM_ZHANG:
|
||||||
|
// pid_zh_constructor(&self->pid_u.zhang);
|
||||||
|
pid_zh_constructor1(&self->pid_u.zhang1);
|
||||||
|
break;
|
||||||
|
case PID_TYPE_CUSTOM_HANGDIAN:
|
||||||
|
pid_hd_constructor(&self->pid_u.hd);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
|
@ -13,17 +13,17 @@
|
||||||
#define PL 3
|
#define PL 3
|
||||||
|
|
||||||
// 定义偏差E的范围,因为设置了非线性区间,误差在10时才开始进行PID调节,这里E的范围为10
|
// 定义偏差E的范围,因为设置了非线性区间,误差在10时才开始进行PID调节,这里E的范围为10
|
||||||
#define MAXE (100)
|
#define MAXE (30)
|
||||||
#define MINE (-MAXE)
|
#define MINE (-MAXE)
|
||||||
// 定义EC的范围,因为变化非常缓慢!,每次的EC都非常小,这里可以根据实际需求来调整,
|
// 定义EC的范围,因为变化非常缓慢!,每次的EC都非常小,这里可以根据实际需求来调整,
|
||||||
#define MAXEC (100)
|
#define MAXEC (30)
|
||||||
#define MINEC (-MAXEC)
|
#define MINEC (-MAXEC)
|
||||||
// 定义e,ec的量化因子
|
// 定义e,ec的量化因子
|
||||||
#define KE 3 / MAXE
|
#define KE 3 / MAXE
|
||||||
#define KEC 3 / MAXEC
|
#define KEC 3 / MAXEC
|
||||||
|
|
||||||
// 定义输出量比例因子
|
// 定义输出量比例因子
|
||||||
#define KUP 1.0f // 这里只使用了模糊PID的比例增益
|
#define KUP 3.0f // 这里只使用了模糊PID的比例增益
|
||||||
#define KUI 0.0f
|
#define KUI 0.0f
|
||||||
#define KUD 0.0f
|
#define KUD 0.0f
|
||||||
|
|
||||||
|
@ -442,6 +442,7 @@ static void _set_ctrl_prm(struct PID_FUZZY *self, float32 kp, float32 ki, float3
|
||||||
pri->detach = FALSE;
|
pri->detach = FALSE;
|
||||||
pri->sm = FALSE;
|
pri->sm = FALSE;
|
||||||
pri->ki_enable = TRUE;
|
pri->ki_enable = TRUE;
|
||||||
|
pri->alpha = 0.25;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -456,6 +457,7 @@ static void _set_ctrl_prm(struct PID_FUZZY *self, float32 kp, float32 ki, float3
|
||||||
pri->out_max = out_max;
|
pri->out_max = out_max;
|
||||||
pri->out_min = out_min;
|
pri->out_min = out_min;
|
||||||
pri->ki_enable = TRUE;
|
pri->ki_enable = TRUE;
|
||||||
|
pri->alpha = 0.25;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,50 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2020, Armink, <armink.ztl@gmail.com>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* @brief basic KV samples.
|
||||||
|
*
|
||||||
|
* basic Key-Value Database KV feature samples
|
||||||
|
* get and show currnet boot counts
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <flashdb.h>
|
||||||
|
|
||||||
|
#ifdef FDB_USING_KVDB
|
||||||
|
|
||||||
|
#define FDB_LOG_TAG "[sample][kvdb][basic]"
|
||||||
|
|
||||||
|
void kvdb_basic_sample(fdb_kvdb_t kvdb)
|
||||||
|
{
|
||||||
|
struct fdb_blob blob;
|
||||||
|
int boot_count = 0;
|
||||||
|
|
||||||
|
FDB_INFO("==================== kvdb_basic_sample ====================\n");
|
||||||
|
|
||||||
|
{ /* GET the KV value */
|
||||||
|
/* get the "boot_count" KV value */
|
||||||
|
fdb_kv_get_blob(kvdb, "boot_count", fdb_blob_make(&blob, &boot_count, sizeof(boot_count)));
|
||||||
|
/* the blob.saved.len is more than 0 when get the value successful */
|
||||||
|
if (blob.saved.len > 0) {
|
||||||
|
FDB_INFO("get the 'boot_count' value is %d\n", boot_count);
|
||||||
|
} else {
|
||||||
|
FDB_INFO("get the 'boot_count' failed\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{ /* CHANGE the KV value */
|
||||||
|
/* increase the boot count */
|
||||||
|
boot_count ++;
|
||||||
|
/* change the "boot_count" KV's value */
|
||||||
|
fdb_kv_set_blob(kvdb, "boot_count", fdb_blob_make(&blob, &boot_count, sizeof(boot_count)));
|
||||||
|
FDB_INFO("set the 'boot_count' value to %d\n", boot_count);
|
||||||
|
}
|
||||||
|
|
||||||
|
FDB_INFO("===========================================================\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* FDB_USING_KVDB */
|
|
@ -0,0 +1,63 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2020, Armink, <armink.ztl@gmail.com>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* @brief blob KV samples.
|
||||||
|
*
|
||||||
|
* Key-Value Database blob type KV feature samples
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <flashdb.h>
|
||||||
|
|
||||||
|
#ifdef FDB_USING_KVDB
|
||||||
|
|
||||||
|
#define FDB_LOG_TAG "[sample][kvdb][blob]"
|
||||||
|
|
||||||
|
void kvdb_type_blob_sample(fdb_kvdb_t kvdb)
|
||||||
|
{
|
||||||
|
struct fdb_blob blob;
|
||||||
|
|
||||||
|
FDB_INFO("==================== kvdb_type_blob_sample ====================\n");
|
||||||
|
|
||||||
|
{ /* CREATE new Key-Value */
|
||||||
|
int temp_data = 36;
|
||||||
|
|
||||||
|
/* It will create new KV node when "temp" KV not in database.
|
||||||
|
* fdb_blob_make: It's a blob make function, and it will return the blob when make finish.
|
||||||
|
*/
|
||||||
|
fdb_kv_set_blob(kvdb, "temp", fdb_blob_make(&blob, &temp_data, sizeof(temp_data)));
|
||||||
|
FDB_INFO("create the 'temp' blob KV, value is: %d\n", temp_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
{ /* GET the KV value */
|
||||||
|
int temp_data = 0;
|
||||||
|
|
||||||
|
/* get the "temp" KV value */
|
||||||
|
fdb_kv_get_blob(kvdb, "temp", fdb_blob_make(&blob, &temp_data, sizeof(temp_data)));
|
||||||
|
/* the blob.saved.len is more than 0 when get the value successful */
|
||||||
|
if (blob.saved.len > 0) {
|
||||||
|
FDB_INFO("get the 'temp' value is: %d\n", temp_data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{ /* CHANGE the KV value */
|
||||||
|
int temp_data = 38;
|
||||||
|
|
||||||
|
/* change the "temp" KV's value to 38 */
|
||||||
|
fdb_kv_set_blob(kvdb, "temp", fdb_blob_make(&blob, &temp_data, sizeof(temp_data)));
|
||||||
|
FDB_INFO("set 'temp' value to %d\n", temp_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
{ /* DELETE the KV by name */
|
||||||
|
fdb_kv_del(kvdb, "temp");
|
||||||
|
FDB_INFO("delete the 'temp' finish\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
FDB_INFO("===========================================================\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* FDB_USING_KVDB */
|
|
@ -0,0 +1,63 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2020, Armink, <armink.ztl@gmail.com>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* @brief string KV samples.
|
||||||
|
*
|
||||||
|
* Key-Value Database string type KV feature samples source file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <flashdb.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#ifdef FDB_USING_KVDB
|
||||||
|
|
||||||
|
#define FDB_LOG_TAG "[sample][kvdb][string]"
|
||||||
|
|
||||||
|
void kvdb_type_string_sample(fdb_kvdb_t kvdb)
|
||||||
|
{
|
||||||
|
FDB_INFO("==================== kvdb_type_string_sample ====================\n");
|
||||||
|
|
||||||
|
{ /* CREATE new Key-Value */
|
||||||
|
char temp_data[10] = "36C";
|
||||||
|
|
||||||
|
/* It will create new KV node when "temp" KV not in database. */
|
||||||
|
fdb_kv_set(kvdb, "temp", temp_data);
|
||||||
|
FDB_INFO("create the 'temp' string KV, value is: %s\n", temp_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
{ /* GET the KV value */
|
||||||
|
char *return_value, temp_data[10] = { 0 };
|
||||||
|
|
||||||
|
/* Get the "temp" KV value.
|
||||||
|
* NOTE: The return value saved in fdb_kv_get's buffer. Please copy away as soon as possible.
|
||||||
|
*/
|
||||||
|
return_value = fdb_kv_get(kvdb, "temp");
|
||||||
|
/* the return value is NULL when get the value failed */
|
||||||
|
if (return_value != NULL) {
|
||||||
|
strncpy(temp_data, return_value, sizeof(temp_data));
|
||||||
|
FDB_INFO("get the 'temp' value is: %s\n", temp_data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{ /* CHANGE the KV value */
|
||||||
|
char temp_data[10] = "38C";
|
||||||
|
|
||||||
|
/* change the "temp" KV's value to "38.1" */
|
||||||
|
fdb_kv_set(kvdb, "temp", temp_data);
|
||||||
|
FDB_INFO("set 'temp' value to %s\n", temp_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
{ /* DELETE the KV by name */
|
||||||
|
fdb_kv_del(kvdb, "temp");
|
||||||
|
FDB_INFO("delete the 'temp' finish\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
FDB_INFO("===========================================================\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* FDB_USING_KVDB */
|
|
@ -0,0 +1,126 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2020, Armink, <armink.ztl@gmail.com>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* @brief TSDB samples.
|
||||||
|
*
|
||||||
|
* Time series log (like TSDB) feature samples source file.
|
||||||
|
*
|
||||||
|
* TSL is time series log, the TSDB saved many TSLs.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <flashdb.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#ifdef FDB_USING_TSDB
|
||||||
|
|
||||||
|
#define FDB_LOG_TAG "[sample][tsdb]"
|
||||||
|
|
||||||
|
#ifdef FDB_USING_TIMESTAMP_64BIT
|
||||||
|
#define __PRITS "ld"
|
||||||
|
#else
|
||||||
|
#define __PRITS "d"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct env_status {
|
||||||
|
int temp;
|
||||||
|
int humi;
|
||||||
|
};
|
||||||
|
|
||||||
|
static bool query_cb(fdb_tsl_t tsl, void *arg);
|
||||||
|
static bool query_by_time_cb(fdb_tsl_t tsl, void *arg);
|
||||||
|
static bool set_status_cb(fdb_tsl_t tsl, void *arg);
|
||||||
|
|
||||||
|
void tsdb_sample(fdb_tsdb_t tsdb)
|
||||||
|
{
|
||||||
|
struct fdb_blob blob;
|
||||||
|
|
||||||
|
FDB_INFO("==================== tsdb_sample ====================\n");
|
||||||
|
|
||||||
|
{ /* APPEND new TSL (time series log) */
|
||||||
|
struct env_status status;
|
||||||
|
|
||||||
|
/* append new log to TSDB */
|
||||||
|
status.temp = 36;
|
||||||
|
status.humi = 85;
|
||||||
|
fdb_tsl_append(tsdb, fdb_blob_make(&blob, &status, sizeof(status)));
|
||||||
|
FDB_INFO("append the new status.temp (%d) and status.humi (%d)\n", status.temp, status.humi);
|
||||||
|
|
||||||
|
status.temp = 38;
|
||||||
|
status.humi = 90;
|
||||||
|
fdb_tsl_append(tsdb, fdb_blob_make(&blob, &status, sizeof(status)));
|
||||||
|
FDB_INFO("append the new status.temp (%d) and status.humi (%d)\n", status.temp, status.humi);
|
||||||
|
}
|
||||||
|
|
||||||
|
{ /* QUERY the TSDB */
|
||||||
|
/* query all TSL in TSDB by iterator */
|
||||||
|
fdb_tsl_iter(tsdb, query_cb, tsdb);
|
||||||
|
}
|
||||||
|
|
||||||
|
{ /* QUERY the TSDB by time */
|
||||||
|
/* prepare query time (from 1970-01-01 00:00:00 to 2020-05-05 00:00:00) */
|
||||||
|
struct tm tm_from = { .tm_year = 1970 - 1900, .tm_mon = 0, .tm_mday = 1, .tm_hour = 0, .tm_min = 0, .tm_sec = 0 };
|
||||||
|
struct tm tm_to = { .tm_year = 2020 - 1900, .tm_mon = 4, .tm_mday = 5, .tm_hour = 0, .tm_min = 0, .tm_sec = 0 };
|
||||||
|
time_t from_time = mktime(&tm_from), to_time = mktime(&tm_to);
|
||||||
|
size_t count;
|
||||||
|
/* query all TSL in TSDB by time */
|
||||||
|
fdb_tsl_iter_by_time(tsdb, from_time, to_time, query_by_time_cb, tsdb);
|
||||||
|
/* query all FDB_TSL_WRITE status TSL's count in TSDB by time */
|
||||||
|
count = fdb_tsl_query_count(tsdb, from_time, to_time, FDB_TSL_WRITE);
|
||||||
|
FDB_INFO("query count is: %zu\n", count);
|
||||||
|
}
|
||||||
|
|
||||||
|
{ /* SET the TSL status */
|
||||||
|
/* Change the TSL status by iterator or time iterator
|
||||||
|
* set_status_cb: the change operation will in this callback
|
||||||
|
*
|
||||||
|
* NOTE: The actions to modify the state must be in order.
|
||||||
|
* like: FDB_TSL_WRITE -> FDB_TSL_USER_STATUS1 -> FDB_TSL_DELETED -> FDB_TSL_USER_STATUS2
|
||||||
|
* The intermediate states can also be ignored.
|
||||||
|
* such as: FDB_TSL_WRITE -> FDB_TSL_DELETED
|
||||||
|
*/
|
||||||
|
fdb_tsl_iter(tsdb, set_status_cb, tsdb);
|
||||||
|
}
|
||||||
|
|
||||||
|
FDB_INFO("===========================================================\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool query_cb(fdb_tsl_t tsl, void *arg)
|
||||||
|
{
|
||||||
|
struct fdb_blob blob;
|
||||||
|
struct env_status status;
|
||||||
|
fdb_tsdb_t db = arg;
|
||||||
|
|
||||||
|
fdb_blob_read((fdb_db_t) db, fdb_tsl_to_blob(tsl, fdb_blob_make(&blob, &status, sizeof(status))));
|
||||||
|
FDB_INFO("[query_cb] queried a TSL: time: %" __PRITS ", temp: %d, humi: %d\n", tsl->time, status.temp, status.humi);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool query_by_time_cb(fdb_tsl_t tsl, void *arg)
|
||||||
|
{
|
||||||
|
struct fdb_blob blob;
|
||||||
|
struct env_status status;
|
||||||
|
fdb_tsdb_t db = arg;
|
||||||
|
|
||||||
|
fdb_blob_read((fdb_db_t) db, fdb_tsl_to_blob(tsl, fdb_blob_make(&blob, &status, sizeof(status))));
|
||||||
|
FDB_INFO("[query_by_time_cb] queried a TSL: time: %" __PRITS ", temp: %d, humi: %d\n", tsl->time, status.temp, status.humi);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool set_status_cb(fdb_tsl_t tsl, void *arg)
|
||||||
|
{
|
||||||
|
fdb_tsdb_t db = arg;
|
||||||
|
|
||||||
|
FDB_INFO("set the TSL (time %" __PRITS ") status from %d to %d\n", tsl->time, tsl->status, FDB_TSL_USER_STATUS1);
|
||||||
|
fdb_tsl_set_status(db, tsl, FDB_TSL_USER_STATUS1);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* FDB_USING_TSDB */
|
|
@ -0,0 +1,62 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2006-2018, RT-Thread Development Team
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*
|
||||||
|
* Change Logs:
|
||||||
|
* Date Author Notes
|
||||||
|
* 2018-05-17 armink the first version
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <fal.h>
|
||||||
|
|
||||||
|
static uint8_t init_ok = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* FAL (Flash Abstraction Layer) initialization.
|
||||||
|
* It will initialize all flash device and all flash partition.
|
||||||
|
*
|
||||||
|
* @return >= 0: partitions total number
|
||||||
|
*/
|
||||||
|
int fal_init(void)
|
||||||
|
{
|
||||||
|
extern int fal_flash_init(void);
|
||||||
|
extern int fal_partition_init(void);
|
||||||
|
|
||||||
|
int result;
|
||||||
|
|
||||||
|
/* initialize all flash device on FAL flash table */
|
||||||
|
result = fal_flash_init();
|
||||||
|
|
||||||
|
if (result < 0) {
|
||||||
|
goto __exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* initialize all flash partition on FAL partition table */
|
||||||
|
result = fal_partition_init();
|
||||||
|
|
||||||
|
__exit:
|
||||||
|
|
||||||
|
if ((result > 0) && (!init_ok))
|
||||||
|
{
|
||||||
|
init_ok = 1;
|
||||||
|
log_i("Flash Abstraction Layer (V%s) initialize success.", FAL_SW_VERSION);
|
||||||
|
}
|
||||||
|
else if(result <= 0)
|
||||||
|
{
|
||||||
|
init_ok = 0;
|
||||||
|
log_e("Flash Abstraction Layer (V%s) initialize failed.", FAL_SW_VERSION);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the FAL is initialized successfully
|
||||||
|
*
|
||||||
|
* @return 0: not init or init failed; 1: init success
|
||||||
|
*/
|
||||||
|
int fal_init_check(void)
|
||||||
|
{
|
||||||
|
return init_ok;
|
||||||
|
}
|
|
@ -0,0 +1,151 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2006-2018, RT-Thread Development Team
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*
|
||||||
|
* Change Logs:
|
||||||
|
* Date Author Notes
|
||||||
|
* 2018-05-17 armink the first version
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _FAL_H_
|
||||||
|
#define _FAL_H_
|
||||||
|
|
||||||
|
#include <fal_cfg.h>
|
||||||
|
#include "fal_def.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* FAL (Flash Abstraction Layer) initialization.
|
||||||
|
* It will initialize all flash device and all flash partition.
|
||||||
|
*
|
||||||
|
* @return >= 0: partitions total number
|
||||||
|
*/
|
||||||
|
int fal_init(void);
|
||||||
|
|
||||||
|
/* =============== flash device operator API =============== */
|
||||||
|
/**
|
||||||
|
* find flash device by name
|
||||||
|
*
|
||||||
|
* @param name flash device name
|
||||||
|
*
|
||||||
|
* @return != NULL: flash device
|
||||||
|
* NULL: not found
|
||||||
|
*/
|
||||||
|
const struct fal_flash_dev *fal_flash_device_find(const char *name);
|
||||||
|
|
||||||
|
/* =============== partition operator API =============== */
|
||||||
|
/**
|
||||||
|
* find the partition by name
|
||||||
|
*
|
||||||
|
* @param name partition name
|
||||||
|
*
|
||||||
|
* @return != NULL: partition
|
||||||
|
* NULL: not found
|
||||||
|
*/
|
||||||
|
const struct fal_partition *fal_partition_find(const char *name);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get the partition table
|
||||||
|
*
|
||||||
|
* @param len return the partition table length
|
||||||
|
*
|
||||||
|
* @return partition table
|
||||||
|
*/
|
||||||
|
const struct fal_partition *fal_get_partition_table(size_t *len);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* set partition table temporarily
|
||||||
|
* This setting will modify the partition table temporarily, the setting will be lost after restart.
|
||||||
|
*
|
||||||
|
* @param table partition table
|
||||||
|
* @param len partition table length
|
||||||
|
*/
|
||||||
|
void fal_set_partition_table_temp(struct fal_partition *table, size_t len);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* read data from partition
|
||||||
|
*
|
||||||
|
* @param part partition
|
||||||
|
* @param addr relative address for partition
|
||||||
|
* @param buf read buffer
|
||||||
|
* @param size read size
|
||||||
|
*
|
||||||
|
* @return >= 0: successful read data size
|
||||||
|
* -1: error
|
||||||
|
*/
|
||||||
|
int fal_partition_read(const struct fal_partition *part, uint32_t addr, uint8_t *buf, size_t size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* write data to partition
|
||||||
|
*
|
||||||
|
* @param part partition
|
||||||
|
* @param addr relative address for partition
|
||||||
|
* @param buf write buffer
|
||||||
|
* @param size write size
|
||||||
|
*
|
||||||
|
* @return >= 0: successful write data size
|
||||||
|
* -1: error
|
||||||
|
*/
|
||||||
|
int fal_partition_write(const struct fal_partition *part, uint32_t addr, const uint8_t *buf, size_t size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* erase partition data
|
||||||
|
*
|
||||||
|
* @param part partition
|
||||||
|
* @param addr relative address for partition
|
||||||
|
* @param size erase size
|
||||||
|
*
|
||||||
|
* @return >= 0: successful erased data size
|
||||||
|
* -1: error
|
||||||
|
*/
|
||||||
|
int fal_partition_erase(const struct fal_partition *part, uint32_t addr, size_t size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* erase partition all data
|
||||||
|
*
|
||||||
|
* @param part partition
|
||||||
|
*
|
||||||
|
* @return >= 0: successful erased data size
|
||||||
|
* -1: error
|
||||||
|
*/
|
||||||
|
int fal_partition_erase_all(const struct fal_partition *part);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* print the partition table
|
||||||
|
*/
|
||||||
|
void fal_show_part_table(void);
|
||||||
|
|
||||||
|
/* =============== API provided to RT-Thread =============== */
|
||||||
|
/**
|
||||||
|
* create RT-Thread block device by specified partition
|
||||||
|
*
|
||||||
|
* @param parition_name partition name
|
||||||
|
*
|
||||||
|
* @return != NULL: created block device
|
||||||
|
* NULL: created failed
|
||||||
|
*/
|
||||||
|
struct rt_device *fal_blk_device_create(const char *parition_name);
|
||||||
|
|
||||||
|
#if defined(RT_USING_MTD_NOR)
|
||||||
|
/**
|
||||||
|
* create RT-Thread MTD NOR device by specified partition
|
||||||
|
*
|
||||||
|
* @param parition_name partition name
|
||||||
|
*
|
||||||
|
* @return != NULL: created MTD NOR device
|
||||||
|
* NULL: created failed
|
||||||
|
*/
|
||||||
|
struct rt_device *fal_mtd_nor_device_create(const char *parition_name);
|
||||||
|
#endif /* defined(RT_USING_MTD_NOR) */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* create RT-Thread char device by specified partition
|
||||||
|
*
|
||||||
|
* @param parition_name partition name
|
||||||
|
*
|
||||||
|
* @return != NULL: created char device
|
||||||
|
* NULL: created failed
|
||||||
|
*/
|
||||||
|
struct rt_device *fal_char_device_create(const char *parition_name);
|
||||||
|
|
||||||
|
#endif /* _FAL_H_ */
|
|
@ -0,0 +1,56 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2006-2018, RT-Thread Development Team
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*
|
||||||
|
* Change Logs:
|
||||||
|
* Date Author Notes
|
||||||
|
* 2018-05-17 armink the first version
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _FAL_CFG_H_
|
||||||
|
#define _FAL_CFG_H_
|
||||||
|
#include "eeprom_m95.h"
|
||||||
|
#include "eeprom_fm24.h"
|
||||||
|
#include "flash.h"
|
||||||
|
|
||||||
|
#define FAL_PART_HAS_TABLE_CFG
|
||||||
|
#define FAL_ERASE_SIZE 100
|
||||||
|
// 需要块大小为2的N次方
|
||||||
|
#define EEPROM_M95_1_BLOCK_SIZE M95_PAGE_SIZE_256 * 32
|
||||||
|
#define EEPROM_M95_2_BLOCK_SIZE M95_PAGE_SIZE_256 * 32
|
||||||
|
#define EEPROM_FM24_BLOCK_SIZE FM24_PAGE_SIZE * 16
|
||||||
|
|
||||||
|
#define EEPROM_M95_1_SIZE _M95M02_
|
||||||
|
#define EEPROM_M95_2_SIZE _M95M02_
|
||||||
|
#define EEPROM_FM24_SIZE FM24_SIZE
|
||||||
|
|
||||||
|
#define EEPROM_M95_1_DEV_NAME "eeprom_m95_1"
|
||||||
|
#define EEPROM_M95_2_DEV_NAME "eeprom_m95_2"
|
||||||
|
#define EEPROM_FM24_DEV_NAME "eeprom_fm24"
|
||||||
|
|
||||||
|
/* ===================== Flash device Configuration ========================= */
|
||||||
|
extern struct fal_flash_dev eeprom_m95_1;
|
||||||
|
extern struct fal_flash_dev eeprom_m95_2;
|
||||||
|
extern struct fal_flash_dev eeprom_fm24;
|
||||||
|
|
||||||
|
/* flash device table */
|
||||||
|
#define FAL_FLASH_DEV_TABLE \
|
||||||
|
{ \
|
||||||
|
&eeprom_m95_1, \
|
||||||
|
&eeprom_m95_2, \
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ====================== Partition Configuration ========================== */
|
||||||
|
#ifdef FAL_PART_HAS_TABLE_CFG
|
||||||
|
/* partition table */
|
||||||
|
// issues :https://github.com/armink/FlashDB/issues/40 ;epprom的扇区太小
|
||||||
|
#define FAL_PART_TABLE \
|
||||||
|
{ \
|
||||||
|
{FAL_PART_MAGIC_WORD, "KVDB", EEPROM_M95_1_DEV_NAME, 0, EEPROM_M95_1_SIZE, 0}, \
|
||||||
|
{FAL_PART_MAGIC_WORD, "TSDB", EEPROM_M95_2_DEV_NAME, 0, EEPROM_M95_2_SIZE, 0}, \
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* FAL_PART_HAS_TABLE_CFG */
|
||||||
|
|
||||||
|
#endif /* _FAL_CFG_H_ */
|
|
@ -0,0 +1,153 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2006-2018, RT-Thread Development Team
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*
|
||||||
|
* Change Logs:
|
||||||
|
* Date Author Notes
|
||||||
|
* 2018-05-17 armink the first version
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _FAL_DEF_H_
|
||||||
|
#define _FAL_DEF_H_
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#ifdef FDB_USING_NATIVE_ASSERT
|
||||||
|
#include <assert.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define FAL_SW_VERSION "0.5.99"
|
||||||
|
|
||||||
|
#ifdef __RTTHREAD__ /* for RT-Thread platform */
|
||||||
|
#include <rtthread.h>
|
||||||
|
#define FAL_PRINTF rt_kprintf
|
||||||
|
#define FAL_MALLOC rt_malloc
|
||||||
|
#define FAL_CALLOC rt_calloc
|
||||||
|
#define FAL_REALLOC rt_realloc
|
||||||
|
#define FAL_FREE rt_free
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef FAL_MALLOC
|
||||||
|
#define FAL_MALLOC malloc
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef FAL_CALLOC
|
||||||
|
#define FAL_CALLOC calloc
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef FAL_REALLOC
|
||||||
|
#define FAL_REALLOC realloc
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef FAL_FREE
|
||||||
|
#define FAL_FREE free
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef FAL_PRINTF
|
||||||
|
#define FAL_PRINTF printf
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef FAL_DEBUG
|
||||||
|
#define FAL_DEBUG 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if FAL_DEBUG
|
||||||
|
#ifndef FDB_USING_NATIVE_ASSERT
|
||||||
|
#ifdef assert
|
||||||
|
#undef assert
|
||||||
|
#endif
|
||||||
|
#define assert(EXPR) \
|
||||||
|
if (!(EXPR)) \
|
||||||
|
{ \
|
||||||
|
FAL_PRINTF("(%s) has assert failed at %s.\n", #EXPR, __func__ ); \
|
||||||
|
while (1); \
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* debug level log */
|
||||||
|
#ifdef log_d
|
||||||
|
#undef log_d
|
||||||
|
#endif
|
||||||
|
#include <inttypes.h>
|
||||||
|
#define log_d(...) FAL_PRINTF("[D/FAL] (%s:%" PRIdLEAST16 ") ", __func__, __LINE__); FAL_PRINTF(__VA_ARGS__);FAL_PRINTF("\n")
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#ifndef FDB_USING_NATIVE_ASSERT
|
||||||
|
#ifdef assert
|
||||||
|
#undef assert
|
||||||
|
#endif
|
||||||
|
#define assert(EXPR) ((void)0);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* debug level log */
|
||||||
|
#ifdef log_d
|
||||||
|
#undef log_d
|
||||||
|
#endif
|
||||||
|
#define log_d(...)
|
||||||
|
#endif /* FAL_DEBUG */
|
||||||
|
|
||||||
|
/* error level log */
|
||||||
|
#ifdef log_e
|
||||||
|
#undef log_e
|
||||||
|
#endif
|
||||||
|
#define log_e(...) FAL_PRINTF("\033[31;22m[E/FAL] (%s:%d) ", __func__, __LINE__);FAL_PRINTF(__VA_ARGS__);FAL_PRINTF("\033[0m\n")
|
||||||
|
|
||||||
|
/* info level log */
|
||||||
|
#ifdef log_i
|
||||||
|
#undef log_i
|
||||||
|
#endif
|
||||||
|
#define log_i(...) FAL_PRINTF("\033[32;22m[I/FAL] "); FAL_PRINTF(__VA_ARGS__);FAL_PRINTF("\033[0m\n")
|
||||||
|
|
||||||
|
/* FAL flash and partition device name max length */
|
||||||
|
#ifndef FAL_DEV_NAME_MAX
|
||||||
|
#define FAL_DEV_NAME_MAX 24
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct fal_flash_dev
|
||||||
|
{
|
||||||
|
char name[FAL_DEV_NAME_MAX];
|
||||||
|
|
||||||
|
/* flash device start address and len */
|
||||||
|
uint32_t addr;
|
||||||
|
size_t len;
|
||||||
|
/* the block size in the flash for erase minimum granularity */
|
||||||
|
size_t blk_size;
|
||||||
|
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
int (*init)(void);
|
||||||
|
int (*read)(long offset, uint8_t *buf, size_t size);
|
||||||
|
int (*write)(long offset, const uint8_t *buf, size_t size);
|
||||||
|
int (*erase)(long offset, size_t size);
|
||||||
|
} ops;
|
||||||
|
|
||||||
|
/* write minimum granularity, unit: bit.
|
||||||
|
1(nor flash)/ 8(stm32f2/f4)/ 32(stm32f1)/ 64(stm32l4)
|
||||||
|
0 will not take effect. */
|
||||||
|
size_t write_gran;
|
||||||
|
};
|
||||||
|
typedef struct fal_flash_dev *fal_flash_dev_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* FAL partition
|
||||||
|
*/
|
||||||
|
struct fal_partition
|
||||||
|
{
|
||||||
|
uint32_t magic_word;
|
||||||
|
|
||||||
|
/* partition name */
|
||||||
|
char name[FAL_DEV_NAME_MAX];
|
||||||
|
/* flash device name for partition */
|
||||||
|
char flash_name[FAL_DEV_NAME_MAX];
|
||||||
|
|
||||||
|
/* partition offset address on flash device */
|
||||||
|
long offset;
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
uint32_t reserved;
|
||||||
|
};
|
||||||
|
typedef struct fal_partition *fal_partition_t;
|
||||||
|
|
||||||
|
#endif /* _FAL_DEF_H_ */
|
|
@ -0,0 +1,79 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2006-2018, RT-Thread Development Team
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*
|
||||||
|
* Change Logs:
|
||||||
|
* Date Author Notes
|
||||||
|
* 2018-05-17 armink the first version
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <fal.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
/* flash device table, must defined by user */
|
||||||
|
#if !defined(FAL_FLASH_DEV_TABLE)
|
||||||
|
#error "You must defined flash device table (FAL_FLASH_DEV_TABLE) on 'fal_cfg.h'"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static const struct fal_flash_dev * const device_table[] = FAL_FLASH_DEV_TABLE;
|
||||||
|
static const size_t device_table_len = sizeof(device_table) / sizeof(device_table[0]);
|
||||||
|
static uint8_t init_ok = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize all flash device on FAL flash table
|
||||||
|
*
|
||||||
|
* @return result
|
||||||
|
*/
|
||||||
|
int fal_flash_init(void)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
if (init_ok)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < device_table_len; i++)
|
||||||
|
{
|
||||||
|
assert(device_table[i]->ops.read);
|
||||||
|
assert(device_table[i]->ops.write);
|
||||||
|
assert(device_table[i]->ops.erase);
|
||||||
|
/* init flash device on flash table */
|
||||||
|
if (device_table[i]->ops.init)
|
||||||
|
{
|
||||||
|
device_table[i]->ops.init();
|
||||||
|
}
|
||||||
|
log_d("Flash device | %*.*s | addr: 0x%08lx | len: 0x%08x | blk_size: 0x%08x |initialized finish.",
|
||||||
|
FAL_DEV_NAME_MAX, FAL_DEV_NAME_MAX, device_table[i]->name, device_table[i]->addr, device_table[i]->len,
|
||||||
|
device_table[i]->blk_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
init_ok = 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* find flash device by name
|
||||||
|
*
|
||||||
|
* @param name flash device name
|
||||||
|
*
|
||||||
|
* @return != NULL: flash device
|
||||||
|
* NULL: not found
|
||||||
|
*/
|
||||||
|
const struct fal_flash_dev *fal_flash_device_find(const char *name)
|
||||||
|
{
|
||||||
|
assert(init_ok);
|
||||||
|
assert(name);
|
||||||
|
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
for (i = 0; i < device_table_len; i++)
|
||||||
|
{
|
||||||
|
if (!strncmp(name, device_table[i]->name, FAL_DEV_NAME_MAX)) {
|
||||||
|
return device_table[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
|
@ -0,0 +1,525 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2006-2018, RT-Thread Development Team
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*
|
||||||
|
* Change Logs:
|
||||||
|
* Date Author Notes
|
||||||
|
* 2018-05-17 armink the first version
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <fal.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
/* partition magic word */
|
||||||
|
#define FAL_PART_MAGIC_WORD 0x45503130
|
||||||
|
#define FAL_PART_MAGIC_WORD_H 0x4550L
|
||||||
|
#define FAL_PART_MAGIC_WORD_L 0x3130L
|
||||||
|
|
||||||
|
struct part_flash_info
|
||||||
|
{
|
||||||
|
const struct fal_flash_dev *flash_dev;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* FAL partition table config has defined on 'fal_cfg.h'.
|
||||||
|
* When this option is disable, it will auto find the partition table on a specified location in flash partition.
|
||||||
|
*/
|
||||||
|
#ifdef FAL_PART_HAS_TABLE_CFG
|
||||||
|
|
||||||
|
/* check partition table definition */
|
||||||
|
#if !defined(FAL_PART_TABLE)
|
||||||
|
#error "You must defined FAL_PART_TABLE on 'fal_cfg.h'"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __CC_ARM /* ARM Compiler */
|
||||||
|
#define SECTION(x) __attribute__((section(x)))
|
||||||
|
#define USED __attribute__((used))
|
||||||
|
#elif defined (__IAR_SYSTEMS_ICC__) /* for IAR Compiler */
|
||||||
|
#define SECTION(x) @ x
|
||||||
|
#define USED __root
|
||||||
|
#elif defined (__GNUC__) /* GNU GCC Compiler */
|
||||||
|
#define SECTION(x) __attribute__((section(x)))
|
||||||
|
#define USED __attribute__((used))
|
||||||
|
#else
|
||||||
|
#error not supported tool chain
|
||||||
|
#endif /* __CC_ARM */
|
||||||
|
//USED static const struct fal_partition partition_table_def[] SECTION("FalPartTable") = FAL_PART_TABLE;
|
||||||
|
static const struct fal_partition partition_table_def[] = FAL_PART_TABLE;
|
||||||
|
static const struct fal_partition *partition_table = NULL;
|
||||||
|
/* partition and flash object information cache table */
|
||||||
|
static struct part_flash_info part_flash_cache[sizeof(partition_table_def) / sizeof(partition_table_def[0])] = { 0 };
|
||||||
|
|
||||||
|
#else /* FAL_PART_HAS_TABLE_CFG */
|
||||||
|
|
||||||
|
#if !defined(FAL_PART_TABLE_FLASH_DEV_NAME)
|
||||||
|
#error "You must defined FAL_PART_TABLE_FLASH_DEV_NAME on 'fal_cfg.h'"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* check partition table end offset address definition */
|
||||||
|
#if !defined(FAL_PART_TABLE_END_OFFSET)
|
||||||
|
#error "You must defined FAL_PART_TABLE_END_OFFSET on 'fal_cfg.h'"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static struct fal_partition *partition_table = NULL;
|
||||||
|
static struct part_flash_info *part_flash_cache = NULL;
|
||||||
|
#endif /* FAL_PART_HAS_TABLE_CFG */
|
||||||
|
|
||||||
|
static uint8_t init_ok = 0;
|
||||||
|
static size_t partition_table_len = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* print the partition table
|
||||||
|
*/
|
||||||
|
void fal_show_part_table(void)
|
||||||
|
{
|
||||||
|
char *item1 = "name", *item2 = "flash_dev";
|
||||||
|
size_t i, part_name_max = strlen(item1), flash_dev_name_max = strlen(item2);
|
||||||
|
const struct fal_partition *part;
|
||||||
|
|
||||||
|
if (partition_table_len)
|
||||||
|
{
|
||||||
|
for (i = 0; i < partition_table_len; i++)
|
||||||
|
{
|
||||||
|
part = &partition_table[i];
|
||||||
|
if (strlen(part->name) > part_name_max)
|
||||||
|
{
|
||||||
|
part_name_max = strlen(part->name);
|
||||||
|
}
|
||||||
|
if (strlen(part->flash_name) > flash_dev_name_max)
|
||||||
|
{
|
||||||
|
flash_dev_name_max = strlen(part->flash_name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
log_i("==================== FAL partition table ====================");
|
||||||
|
log_i("| %-*.*s | %-*.*s | offset | length |", part_name_max, FAL_DEV_NAME_MAX, item1, flash_dev_name_max,
|
||||||
|
FAL_DEV_NAME_MAX, item2);
|
||||||
|
log_i("-------------------------------------------------------------");
|
||||||
|
for (i = 0; i < partition_table_len; i++)
|
||||||
|
{
|
||||||
|
|
||||||
|
#ifdef FAL_PART_HAS_TABLE_CFG
|
||||||
|
part = &partition_table[i];
|
||||||
|
#else
|
||||||
|
part = &partition_table[partition_table_len - i - 1];
|
||||||
|
#endif
|
||||||
|
|
||||||
|
log_i("| %-*.*s | %-*.*s | 0x%08lx | 0x%08x |", part_name_max, FAL_DEV_NAME_MAX, part->name, flash_dev_name_max,
|
||||||
|
FAL_DEV_NAME_MAX, part->flash_name, part->offset, part->len);
|
||||||
|
}
|
||||||
|
log_i("=============================================================");
|
||||||
|
}
|
||||||
|
|
||||||
|
static int check_and_update_part_cache(const struct fal_partition *table, size_t len)
|
||||||
|
{
|
||||||
|
const struct fal_flash_dev *flash_dev = NULL;
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
#ifndef FAL_PART_HAS_TABLE_CFG
|
||||||
|
if (part_flash_cache)
|
||||||
|
{
|
||||||
|
FAL_FREE(part_flash_cache);
|
||||||
|
}
|
||||||
|
part_flash_cache = FAL_MALLOC(len * sizeof(struct part_flash_info));
|
||||||
|
if (part_flash_cache == NULL)
|
||||||
|
{
|
||||||
|
log_e("Initialize failed! No memory for partition table cache");
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
for (i = 0; i < len; i++)
|
||||||
|
{
|
||||||
|
flash_dev = fal_flash_device_find(table[i].flash_name);
|
||||||
|
if (flash_dev == NULL)
|
||||||
|
{
|
||||||
|
log_d("Warning: Do NOT found the flash device(%s).", table[i].flash_name);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (table[i].offset >= (long)flash_dev->len)
|
||||||
|
{
|
||||||
|
log_e("Initialize failed! Partition(%s) offset address(%ld) out of flash bound(<%d).",
|
||||||
|
table[i].name, table[i].offset, flash_dev->len);
|
||||||
|
partition_table_len = 0;
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
part_flash_cache[i].flash_dev = flash_dev;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize all flash partition on FAL partition table
|
||||||
|
*
|
||||||
|
* @return partitions total number
|
||||||
|
*/
|
||||||
|
int fal_partition_init(void)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (init_ok)
|
||||||
|
{
|
||||||
|
return partition_table_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef FAL_PART_HAS_TABLE_CFG
|
||||||
|
partition_table = &partition_table_def[0];
|
||||||
|
partition_table_len = sizeof(partition_table_def) / sizeof(partition_table_def[0]);
|
||||||
|
#else
|
||||||
|
/* load partition table from the end address FAL_PART_TABLE_END_OFFSET, error return 0 */
|
||||||
|
long part_table_offset = FAL_PART_TABLE_END_OFFSET;
|
||||||
|
size_t table_num = 0, table_item_size = 0;
|
||||||
|
uint8_t part_table_find_ok = 0;
|
||||||
|
uint32_t read_magic_word;
|
||||||
|
fal_partition_t new_part = NULL;
|
||||||
|
size_t i;
|
||||||
|
const struct fal_flash_dev *flash_dev = NULL;
|
||||||
|
|
||||||
|
flash_dev = fal_flash_device_find(FAL_PART_TABLE_FLASH_DEV_NAME);
|
||||||
|
if (flash_dev == NULL)
|
||||||
|
{
|
||||||
|
log_e("Initialize failed! Flash device (%s) NOT found.", FAL_PART_TABLE_FLASH_DEV_NAME);
|
||||||
|
goto _exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check partition table offset address */
|
||||||
|
if (part_table_offset < 0 || part_table_offset >= (long) flash_dev->len)
|
||||||
|
{
|
||||||
|
log_e("Setting partition table end offset address(%ld) out of flash bound(<%d).", part_table_offset, flash_dev->len);
|
||||||
|
goto _exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
table_item_size = sizeof(struct fal_partition);
|
||||||
|
new_part = (fal_partition_t)FAL_MALLOC(table_item_size);
|
||||||
|
if (new_part == NULL)
|
||||||
|
{
|
||||||
|
log_e("Initialize failed! No memory for table buffer.");
|
||||||
|
goto _exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* find partition table location */
|
||||||
|
{
|
||||||
|
uint8_t read_buf[64];
|
||||||
|
|
||||||
|
part_table_offset -= sizeof(read_buf);
|
||||||
|
while (part_table_offset >= 0)
|
||||||
|
{
|
||||||
|
if (flash_dev->ops.read(part_table_offset, read_buf, sizeof(read_buf)) > 0)
|
||||||
|
{
|
||||||
|
/* find magic word in read buf */
|
||||||
|
for (i = 0; i < sizeof(read_buf) - sizeof(read_magic_word) + 1; i++)
|
||||||
|
{
|
||||||
|
read_magic_word = read_buf[0 + i] + (read_buf[1 + i] << 8) + (read_buf[2 + i] << 16) + (read_buf[3 + i] << 24);
|
||||||
|
if (read_magic_word == ((FAL_PART_MAGIC_WORD_H << 16) + FAL_PART_MAGIC_WORD_L))
|
||||||
|
{
|
||||||
|
part_table_find_ok = 1;
|
||||||
|
part_table_offset += i;
|
||||||
|
log_d("Find the partition table on '%s' offset @0x%08lx.", FAL_PART_TABLE_FLASH_DEV_NAME,
|
||||||
|
part_table_offset);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* read failed */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (part_table_find_ok)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* calculate next read buf position */
|
||||||
|
if (part_table_offset >= (long)sizeof(read_buf))
|
||||||
|
{
|
||||||
|
part_table_offset -= sizeof(read_buf);
|
||||||
|
part_table_offset += (sizeof(read_magic_word) - 1);
|
||||||
|
}
|
||||||
|
else if (part_table_offset != 0)
|
||||||
|
{
|
||||||
|
part_table_offset = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* find failed */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* load partition table */
|
||||||
|
while (part_table_find_ok)
|
||||||
|
{
|
||||||
|
memset(new_part, 0x00, table_num);
|
||||||
|
if (flash_dev->ops.read(part_table_offset - table_item_size * (table_num), (uint8_t *) new_part,
|
||||||
|
table_item_size) < 0)
|
||||||
|
{
|
||||||
|
log_e("Initialize failed! Flash device (%s) read error!", flash_dev->name);
|
||||||
|
table_num = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (new_part->magic_word != ((FAL_PART_MAGIC_WORD_H << 16) + FAL_PART_MAGIC_WORD_L))
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
partition_table = (fal_partition_t) FAL_REALLOC(partition_table, table_item_size * (table_num + 1));
|
||||||
|
if (partition_table == NULL)
|
||||||
|
{
|
||||||
|
log_e("Initialize failed! No memory for partition table");
|
||||||
|
table_num = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(partition_table + table_num, new_part, table_item_size);
|
||||||
|
|
||||||
|
table_num++;
|
||||||
|
};
|
||||||
|
|
||||||
|
if (table_num == 0)
|
||||||
|
{
|
||||||
|
log_e("Partition table NOT found on flash: %s (len: %d) from offset: 0x%08x.", FAL_PART_TABLE_FLASH_DEV_NAME,
|
||||||
|
FAL_DEV_NAME_MAX, FAL_PART_TABLE_END_OFFSET);
|
||||||
|
goto _exit;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
partition_table_len = table_num;
|
||||||
|
}
|
||||||
|
#endif /* FAL_PART_HAS_TABLE_CFG */
|
||||||
|
|
||||||
|
/* check the partition table device exists */
|
||||||
|
if (check_and_update_part_cache(partition_table, partition_table_len) != 0)
|
||||||
|
{
|
||||||
|
goto _exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
init_ok = 1;
|
||||||
|
|
||||||
|
_exit:
|
||||||
|
|
||||||
|
#if FAL_DEBUG
|
||||||
|
fal_show_part_table();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef FAL_PART_HAS_TABLE_CFG
|
||||||
|
if (new_part)
|
||||||
|
{
|
||||||
|
FAL_FREE(new_part);
|
||||||
|
}
|
||||||
|
#endif /* !FAL_PART_HAS_TABLE_CFG */
|
||||||
|
|
||||||
|
return partition_table_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* find the partition by name
|
||||||
|
*
|
||||||
|
* @param name partition name
|
||||||
|
*
|
||||||
|
* @return != NULL: partition
|
||||||
|
* NULL: not found
|
||||||
|
*/
|
||||||
|
const struct fal_partition *fal_partition_find(const char *name)
|
||||||
|
{
|
||||||
|
assert(init_ok);
|
||||||
|
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
for (i = 0; i < partition_table_len; i++)
|
||||||
|
{
|
||||||
|
if (!strcmp(name, partition_table[i].name))
|
||||||
|
{
|
||||||
|
return &partition_table[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct fal_flash_dev *flash_device_find_by_part(const struct fal_partition *part)
|
||||||
|
{
|
||||||
|
assert(part >= partition_table);
|
||||||
|
assert(part <= &partition_table[partition_table_len - 1]);
|
||||||
|
|
||||||
|
return part_flash_cache[part - partition_table].flash_dev;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get the partition table
|
||||||
|
*
|
||||||
|
* @param len return the partition table length
|
||||||
|
*
|
||||||
|
* @return partition table
|
||||||
|
*/
|
||||||
|
const struct fal_partition *fal_get_partition_table(size_t *len)
|
||||||
|
{
|
||||||
|
assert(init_ok);
|
||||||
|
assert(len);
|
||||||
|
|
||||||
|
*len = partition_table_len;
|
||||||
|
|
||||||
|
return partition_table;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* set partition table temporarily
|
||||||
|
* This setting will modify the partition table temporarily, the setting will be lost after restart.
|
||||||
|
*
|
||||||
|
* @param table partition table
|
||||||
|
* @param len partition table length
|
||||||
|
*/
|
||||||
|
void fal_set_partition_table_temp(struct fal_partition *table, size_t len)
|
||||||
|
{
|
||||||
|
assert(init_ok);
|
||||||
|
assert(table);
|
||||||
|
|
||||||
|
check_and_update_part_cache(table, len);
|
||||||
|
|
||||||
|
partition_table_len = len;
|
||||||
|
partition_table = table;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* read data from partition
|
||||||
|
*
|
||||||
|
* @param part partition
|
||||||
|
* @param addr relative address for partition
|
||||||
|
* @param buf read buffer
|
||||||
|
* @param size read size
|
||||||
|
*
|
||||||
|
* @return >= 0: successful read data size
|
||||||
|
* -1: error
|
||||||
|
*/
|
||||||
|
int fal_partition_read(const struct fal_partition *part, uint32_t addr, uint8_t *buf, size_t size)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
const struct fal_flash_dev *flash_dev = NULL;
|
||||||
|
|
||||||
|
assert(part);
|
||||||
|
assert(buf);
|
||||||
|
|
||||||
|
if (addr + size > part->len)
|
||||||
|
{
|
||||||
|
log_e("Partition read error! Partition address out of bound.");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
flash_dev = flash_device_find_by_part(part);
|
||||||
|
if (flash_dev == NULL)
|
||||||
|
{
|
||||||
|
log_e("Partition read error! Don't found flash device(%s) of the partition(%s).", part->flash_name, part->name);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = flash_dev->ops.read(part->offset + addr, buf, size);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
log_e("Partition read error! Flash device(%s) read error!", part->flash_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* write data to partition
|
||||||
|
*
|
||||||
|
* @param part partition
|
||||||
|
* @param addr relative address for partition
|
||||||
|
* @param buf write buffer
|
||||||
|
* @param size write size
|
||||||
|
*
|
||||||
|
* @return >= 0: successful write data size
|
||||||
|
* -1: error
|
||||||
|
*/
|
||||||
|
int fal_partition_write(const struct fal_partition *part, uint32_t addr, const uint8_t *buf, size_t size)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
const struct fal_flash_dev *flash_dev = NULL;
|
||||||
|
|
||||||
|
assert(part);
|
||||||
|
assert(buf);
|
||||||
|
|
||||||
|
if (addr + size > part->len)
|
||||||
|
{
|
||||||
|
log_e("Partition write error! Partition address out of bound.");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
flash_dev = flash_device_find_by_part(part);
|
||||||
|
if (flash_dev == NULL)
|
||||||
|
{
|
||||||
|
log_e("Partition write error! Don't found flash device(%s) of the partition(%s).", part->flash_name, part->name);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = flash_dev->ops.write(part->offset + addr, buf, size);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
log_e("Partition write error! Flash device(%s) write error!", part->flash_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* erase partition data
|
||||||
|
*
|
||||||
|
* @param part partition
|
||||||
|
* @param addr relative address for partition
|
||||||
|
* @param size erase size
|
||||||
|
*
|
||||||
|
* @return >= 0: successful erased data size
|
||||||
|
* -1: error
|
||||||
|
*/
|
||||||
|
int fal_partition_erase(const struct fal_partition *part, uint32_t addr, size_t size)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
const struct fal_flash_dev *flash_dev = NULL;
|
||||||
|
|
||||||
|
assert(part);
|
||||||
|
|
||||||
|
if (addr + size > part->len)
|
||||||
|
{
|
||||||
|
log_e("Partition erase error! Partition address out of bound.");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
flash_dev = flash_device_find_by_part(part);
|
||||||
|
if (flash_dev == NULL)
|
||||||
|
{
|
||||||
|
log_e("Partition erase error! Don't found flash device(%s) of the partition(%s).", part->flash_name, part->name);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = flash_dev->ops.erase(part->offset + addr, size);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
log_e("Partition erase error! Flash device(%s) erase error!", part->flash_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* erase partition all data
|
||||||
|
*
|
||||||
|
* @param part partition
|
||||||
|
*
|
||||||
|
* @return >= 0: successful erased data size
|
||||||
|
* -1: error
|
||||||
|
*/
|
||||||
|
int fal_partition_erase_all(const struct fal_partition *part)
|
||||||
|
{
|
||||||
|
return fal_partition_erase(part, 0, part->len);
|
||||||
|
}
|
|
@ -0,0 +1,934 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2006-2018, RT-Thread Development Team
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*
|
||||||
|
* Change Logs:
|
||||||
|
* Date Author Notes
|
||||||
|
* 2018-06-23 armink the first version
|
||||||
|
* 2019-08-22 MurphyZhao adapt to none rt-thread case
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <fal.h>
|
||||||
|
|
||||||
|
#ifdef RT_VER_NUM
|
||||||
|
#include <rtthread.h>
|
||||||
|
#include <rtdevice.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
/* ========================== block device ======================== */
|
||||||
|
struct fal_blk_device
|
||||||
|
{
|
||||||
|
struct rt_device parent;
|
||||||
|
struct rt_device_blk_geometry geometry;
|
||||||
|
const struct fal_partition *fal_part;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* RT-Thread device interface */
|
||||||
|
#if RTTHREAD_VERSION >= 30000
|
||||||
|
static rt_err_t blk_dev_control(rt_device_t dev, int cmd, void *args)
|
||||||
|
#else
|
||||||
|
static rt_err_t blk_dev_control(rt_device_t dev, rt_uint8_t cmd, void *args)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
struct fal_blk_device *part = (struct fal_blk_device*) dev;
|
||||||
|
|
||||||
|
assert(part != RT_NULL);
|
||||||
|
|
||||||
|
if (cmd == RT_DEVICE_CTRL_BLK_GETGEOME)
|
||||||
|
{
|
||||||
|
struct rt_device_blk_geometry *geometry;
|
||||||
|
|
||||||
|
geometry = (struct rt_device_blk_geometry *) args;
|
||||||
|
if (geometry == RT_NULL)
|
||||||
|
{
|
||||||
|
return -RT_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(geometry, &part->geometry, sizeof(struct rt_device_blk_geometry));
|
||||||
|
}
|
||||||
|
else if (cmd == RT_DEVICE_CTRL_BLK_ERASE)
|
||||||
|
{
|
||||||
|
rt_uint32_t *addrs = (rt_uint32_t *) args, start_addr = addrs[0], end_addr = addrs[1], phy_start_addr;
|
||||||
|
rt_size_t phy_size;
|
||||||
|
|
||||||
|
if (addrs == RT_NULL || start_addr > end_addr)
|
||||||
|
{
|
||||||
|
return -RT_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (end_addr == start_addr)
|
||||||
|
{
|
||||||
|
end_addr++;
|
||||||
|
}
|
||||||
|
|
||||||
|
phy_start_addr = start_addr * part->geometry.bytes_per_sector;
|
||||||
|
phy_size = (end_addr - start_addr) * part->geometry.bytes_per_sector;
|
||||||
|
|
||||||
|
if (fal_partition_erase(part->fal_part, phy_start_addr, phy_size) < 0)
|
||||||
|
{
|
||||||
|
return -RT_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return RT_EOK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static rt_size_t blk_dev_read(rt_device_t dev, rt_off_t pos, void* buffer, rt_size_t size)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
struct fal_blk_device *part = (struct fal_blk_device*) dev;
|
||||||
|
|
||||||
|
assert(part != RT_NULL);
|
||||||
|
|
||||||
|
ret = fal_partition_read(part->fal_part, pos * part->geometry.block_size, buffer, size * part->geometry.block_size);
|
||||||
|
|
||||||
|
if (ret != (int)(size * part->geometry.block_size))
|
||||||
|
{
|
||||||
|
ret = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ret = size;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static rt_size_t blk_dev_write(rt_device_t dev, rt_off_t pos, const void* buffer, rt_size_t size)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
struct fal_blk_device *part;
|
||||||
|
rt_off_t phy_pos;
|
||||||
|
rt_size_t phy_size;
|
||||||
|
|
||||||
|
part = (struct fal_blk_device*) dev;
|
||||||
|
assert(part != RT_NULL);
|
||||||
|
|
||||||
|
/* change the block device's logic address to physical address */
|
||||||
|
phy_pos = pos * part->geometry.bytes_per_sector;
|
||||||
|
phy_size = size * part->geometry.bytes_per_sector;
|
||||||
|
|
||||||
|
ret = fal_partition_erase(part->fal_part, phy_pos, phy_size);
|
||||||
|
|
||||||
|
if (ret == (int) phy_size)
|
||||||
|
{
|
||||||
|
ret = fal_partition_write(part->fal_part, phy_pos, buffer, phy_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret != (int) phy_size)
|
||||||
|
{
|
||||||
|
ret = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ret = size;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef RT_USING_DEVICE_OPS
|
||||||
|
const static struct rt_device_ops blk_dev_ops =
|
||||||
|
{
|
||||||
|
RT_NULL,
|
||||||
|
RT_NULL,
|
||||||
|
RT_NULL,
|
||||||
|
blk_dev_read,
|
||||||
|
blk_dev_write,
|
||||||
|
blk_dev_control
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* create RT-Thread block device by specified partition
|
||||||
|
*
|
||||||
|
* @param parition_name partition name
|
||||||
|
*
|
||||||
|
* @return != NULL: created block device
|
||||||
|
* NULL: created failed
|
||||||
|
*/
|
||||||
|
struct rt_device *fal_blk_device_create(const char *parition_name)
|
||||||
|
{
|
||||||
|
struct fal_blk_device *blk_dev;
|
||||||
|
const struct fal_partition *fal_part = fal_partition_find(parition_name);
|
||||||
|
const struct fal_flash_dev *fal_flash = NULL;
|
||||||
|
|
||||||
|
if (!fal_part)
|
||||||
|
{
|
||||||
|
log_e("Error: the partition name (%s) is not found.", parition_name);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((fal_flash = fal_flash_device_find(fal_part->flash_name)) == NULL)
|
||||||
|
{
|
||||||
|
log_e("Error: the flash device name (%s) is not found.", fal_part->flash_name);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
blk_dev = (struct fal_blk_device*) rt_malloc(sizeof(struct fal_blk_device));
|
||||||
|
if (blk_dev)
|
||||||
|
{
|
||||||
|
blk_dev->fal_part = fal_part;
|
||||||
|
blk_dev->geometry.bytes_per_sector = fal_flash->blk_size;
|
||||||
|
blk_dev->geometry.block_size = fal_flash->blk_size;
|
||||||
|
blk_dev->geometry.sector_count = fal_part->len / fal_flash->blk_size;
|
||||||
|
|
||||||
|
/* register device */
|
||||||
|
blk_dev->parent.type = RT_Device_Class_Block;
|
||||||
|
|
||||||
|
#ifdef RT_USING_DEVICE_OPS
|
||||||
|
blk_dev->parent.ops = &blk_dev_ops;
|
||||||
|
#else
|
||||||
|
blk_dev->parent.init = NULL;
|
||||||
|
blk_dev->parent.open = NULL;
|
||||||
|
blk_dev->parent.close = NULL;
|
||||||
|
blk_dev->parent.read = blk_dev_read;
|
||||||
|
blk_dev->parent.write = blk_dev_write;
|
||||||
|
blk_dev->parent.control = blk_dev_control;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* no private */
|
||||||
|
blk_dev->parent.user_data = RT_NULL;
|
||||||
|
|
||||||
|
log_i("The FAL block device (%s) created successfully", fal_part->name);
|
||||||
|
rt_device_register(RT_DEVICE(blk_dev), fal_part->name, RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_STANDALONE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
log_e("Error: no memory for create FAL block device");
|
||||||
|
}
|
||||||
|
|
||||||
|
return RT_DEVICE(blk_dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ========================== MTD nor device ======================== */
|
||||||
|
#if defined(RT_USING_MTD_NOR)
|
||||||
|
|
||||||
|
struct fal_mtd_nor_device
|
||||||
|
{
|
||||||
|
struct rt_mtd_nor_device parent;
|
||||||
|
const struct fal_partition *fal_part;
|
||||||
|
};
|
||||||
|
|
||||||
|
static rt_size_t mtd_nor_dev_read(struct rt_mtd_nor_device* device, rt_off_t offset, rt_uint8_t* data, rt_uint32_t length)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
struct fal_mtd_nor_device *part = (struct fal_mtd_nor_device*) device;
|
||||||
|
|
||||||
|
assert(part != RT_NULL);
|
||||||
|
|
||||||
|
ret = fal_partition_read(part->fal_part, offset, data, length);
|
||||||
|
|
||||||
|
if (ret != (int)length)
|
||||||
|
{
|
||||||
|
ret = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ret = length;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static rt_size_t mtd_nor_dev_write(struct rt_mtd_nor_device* device, rt_off_t offset, const rt_uint8_t* data, rt_uint32_t length)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
struct fal_mtd_nor_device *part;
|
||||||
|
|
||||||
|
part = (struct fal_mtd_nor_device*) device;
|
||||||
|
assert(part != RT_NULL);
|
||||||
|
|
||||||
|
ret = fal_partition_write(part->fal_part, offset, data, length);
|
||||||
|
|
||||||
|
if (ret != (int) length)
|
||||||
|
{
|
||||||
|
ret = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ret = length;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static rt_err_t mtd_nor_dev_erase(struct rt_mtd_nor_device* device, rt_off_t offset, rt_uint32_t length)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
struct fal_mtd_nor_device *part;
|
||||||
|
|
||||||
|
part = (struct fal_mtd_nor_device*) device;
|
||||||
|
assert(part != RT_NULL);
|
||||||
|
|
||||||
|
ret = fal_partition_erase(part->fal_part, offset, length);
|
||||||
|
|
||||||
|
if (ret != length)
|
||||||
|
{
|
||||||
|
return -RT_ERROR;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return RT_EOK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct rt_mtd_nor_driver_ops _ops =
|
||||||
|
{
|
||||||
|
RT_NULL,
|
||||||
|
mtd_nor_dev_read,
|
||||||
|
mtd_nor_dev_write,
|
||||||
|
mtd_nor_dev_erase,
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* create RT-Thread MTD NOR device by specified partition
|
||||||
|
*
|
||||||
|
* @param parition_name partition name
|
||||||
|
*
|
||||||
|
* @return != NULL: created MTD NOR device
|
||||||
|
* NULL: created failed
|
||||||
|
*/
|
||||||
|
struct rt_device *fal_mtd_nor_device_create(const char *parition_name)
|
||||||
|
{
|
||||||
|
struct fal_mtd_nor_device *mtd_nor_dev;
|
||||||
|
const struct fal_partition *fal_part = fal_partition_find(parition_name);
|
||||||
|
const struct fal_flash_dev *fal_flash = NULL;
|
||||||
|
|
||||||
|
if (!fal_part)
|
||||||
|
{
|
||||||
|
log_e("Error: the partition name (%s) is not found.", parition_name);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((fal_flash = fal_flash_device_find(fal_part->flash_name)) == NULL)
|
||||||
|
{
|
||||||
|
log_e("Error: the flash device name (%s) is not found.", fal_part->flash_name);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
mtd_nor_dev = (struct fal_mtd_nor_device*) rt_malloc(sizeof(struct fal_mtd_nor_device));
|
||||||
|
if (mtd_nor_dev)
|
||||||
|
{
|
||||||
|
mtd_nor_dev->fal_part = fal_part;
|
||||||
|
|
||||||
|
mtd_nor_dev->parent.block_start = 0;
|
||||||
|
mtd_nor_dev->parent.block_end = fal_part->len / fal_flash->blk_size;
|
||||||
|
mtd_nor_dev->parent.block_size = fal_flash->blk_size;
|
||||||
|
|
||||||
|
/* set ops */
|
||||||
|
mtd_nor_dev->parent.ops = &_ops;
|
||||||
|
|
||||||
|
log_i("The FAL MTD NOR device (%s) created successfully", fal_part->name);
|
||||||
|
rt_mtd_nor_register_device(fal_part->name, &mtd_nor_dev->parent);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
log_e("Error: no memory for create FAL MTD NOR device");
|
||||||
|
}
|
||||||
|
|
||||||
|
return RT_DEVICE(&mtd_nor_dev->parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* defined(RT_USING_MTD_NOR) */
|
||||||
|
|
||||||
|
|
||||||
|
/* ========================== char device ======================== */
|
||||||
|
struct fal_char_device
|
||||||
|
{
|
||||||
|
struct rt_device parent;
|
||||||
|
const struct fal_partition *fal_part;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* RT-Thread device interface */
|
||||||
|
static rt_size_t char_dev_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
struct fal_char_device *part = (struct fal_char_device *) dev;
|
||||||
|
|
||||||
|
assert(part != RT_NULL);
|
||||||
|
|
||||||
|
if (pos + size > part->fal_part->len)
|
||||||
|
size = part->fal_part->len - pos;
|
||||||
|
|
||||||
|
ret = fal_partition_read(part->fal_part, pos, buffer, size);
|
||||||
|
|
||||||
|
if (ret != (int)(size))
|
||||||
|
ret = 0;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static rt_size_t char_dev_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
struct fal_char_device *part;
|
||||||
|
|
||||||
|
part = (struct fal_char_device *) dev;
|
||||||
|
assert(part != RT_NULL);
|
||||||
|
|
||||||
|
if (pos == 0)
|
||||||
|
{
|
||||||
|
fal_partition_erase_all(part->fal_part);
|
||||||
|
}
|
||||||
|
else if (pos + size > part->fal_part->len)
|
||||||
|
{
|
||||||
|
size = part->fal_part->len - pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = fal_partition_write(part->fal_part, pos, buffer, size);
|
||||||
|
|
||||||
|
if (ret != (int) size)
|
||||||
|
ret = 0;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef RT_USING_DEVICE_OPS
|
||||||
|
const static struct rt_device_ops char_dev_ops =
|
||||||
|
{
|
||||||
|
RT_NULL,
|
||||||
|
RT_NULL,
|
||||||
|
RT_NULL,
|
||||||
|
char_dev_read,
|
||||||
|
char_dev_write,
|
||||||
|
RT_NULL
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef RT_USING_POSIX
|
||||||
|
#include <dfs_posix.h>
|
||||||
|
|
||||||
|
/* RT-Thread device filesystem interface */
|
||||||
|
static int char_dev_fopen(struct dfs_fd *fd)
|
||||||
|
{
|
||||||
|
struct fal_char_device *part = (struct fal_char_device *) fd->data;
|
||||||
|
|
||||||
|
assert(part != RT_NULL);
|
||||||
|
|
||||||
|
switch (fd->flags & O_ACCMODE)
|
||||||
|
{
|
||||||
|
case O_RDONLY:
|
||||||
|
break;
|
||||||
|
case O_WRONLY:
|
||||||
|
case O_RDWR:
|
||||||
|
/* erase partition when device file open */
|
||||||
|
fal_partition_erase_all(part->fal_part);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
fd->pos = 0;
|
||||||
|
|
||||||
|
return RT_EOK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int char_dev_fread(struct dfs_fd *fd, void *buf, size_t count)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
struct fal_char_device *part = (struct fal_char_device *) fd->data;
|
||||||
|
|
||||||
|
assert(part != RT_NULL);
|
||||||
|
|
||||||
|
if (fd->pos + count > part->fal_part->len)
|
||||||
|
count = part->fal_part->len - fd->pos;
|
||||||
|
|
||||||
|
ret = fal_partition_read(part->fal_part, fd->pos, buf, count);
|
||||||
|
|
||||||
|
if (ret != (int)(count))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
fd->pos += ret;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int char_dev_fwrite(struct dfs_fd *fd, const void *buf, size_t count)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
struct fal_char_device *part = (struct fal_char_device *) fd->data;
|
||||||
|
|
||||||
|
assert(part != RT_NULL);
|
||||||
|
|
||||||
|
if (fd->pos + count > part->fal_part->len)
|
||||||
|
count = part->fal_part->len - fd->pos;
|
||||||
|
|
||||||
|
ret = fal_partition_write(part->fal_part, fd->pos, buf, count);
|
||||||
|
|
||||||
|
if (ret != (int) count)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
fd->pos += ret;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct dfs_file_ops char_dev_fops =
|
||||||
|
{
|
||||||
|
char_dev_fopen,
|
||||||
|
RT_NULL,
|
||||||
|
RT_NULL,
|
||||||
|
char_dev_fread,
|
||||||
|
char_dev_fwrite,
|
||||||
|
RT_NULL, /* flush */
|
||||||
|
RT_NULL, /* lseek */
|
||||||
|
RT_NULL, /* getdents */
|
||||||
|
RT_NULL,
|
||||||
|
};
|
||||||
|
#endif /* defined(RT_USING_POSIX) */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* create RT-Thread char device by specified partition
|
||||||
|
*
|
||||||
|
* @param parition_name partition name
|
||||||
|
*
|
||||||
|
* @return != NULL: created char device
|
||||||
|
* NULL: created failed
|
||||||
|
*/
|
||||||
|
struct rt_device *fal_char_device_create(const char *parition_name)
|
||||||
|
{
|
||||||
|
struct fal_char_device *char_dev;
|
||||||
|
const struct fal_partition *fal_part = fal_partition_find(parition_name);
|
||||||
|
|
||||||
|
if (!fal_part)
|
||||||
|
{
|
||||||
|
log_e("Error: the partition name (%s) is not found.", parition_name);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((fal_flash_device_find(fal_part->flash_name)) == NULL)
|
||||||
|
{
|
||||||
|
log_e("Error: the flash device name (%s) is not found.", fal_part->flash_name);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
char_dev = (struct fal_char_device *) rt_malloc(sizeof(struct fal_char_device));
|
||||||
|
if (char_dev)
|
||||||
|
{
|
||||||
|
char_dev->fal_part = fal_part;
|
||||||
|
|
||||||
|
/* register device */
|
||||||
|
char_dev->parent.type = RT_Device_Class_Char;
|
||||||
|
|
||||||
|
#ifdef RT_USING_DEVICE_OPS
|
||||||
|
char_dev->parent.ops = &char_dev_ops;
|
||||||
|
#else
|
||||||
|
char_dev->parent.init = NULL;
|
||||||
|
char_dev->parent.open = NULL;
|
||||||
|
char_dev->parent.close = NULL;
|
||||||
|
char_dev->parent.read = char_dev_read;
|
||||||
|
char_dev->parent.write = char_dev_write;
|
||||||
|
char_dev->parent.control = NULL;
|
||||||
|
/* no private */
|
||||||
|
char_dev->parent.user_data = NULL;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
rt_device_register(RT_DEVICE(char_dev), fal_part->name, RT_DEVICE_FLAG_RDWR);
|
||||||
|
log_i("The FAL char device (%s) created successfully", fal_part->name);
|
||||||
|
|
||||||
|
#ifdef RT_USING_POSIX
|
||||||
|
/* set fops */
|
||||||
|
char_dev->parent.fops = &char_dev_fops;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
log_e("Error: no memory for create FAL char device");
|
||||||
|
}
|
||||||
|
|
||||||
|
return RT_DEVICE(char_dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(RT_USING_FINSH) && defined(FINSH_USING_MSH)
|
||||||
|
|
||||||
|
#include <finsh.h>
|
||||||
|
extern int fal_init_check(void);
|
||||||
|
|
||||||
|
static void fal(uint8_t argc, char **argv) {
|
||||||
|
|
||||||
|
#define __is_print(ch) ((unsigned int)((ch) - ' ') < 127u - ' ')
|
||||||
|
#define HEXDUMP_WIDTH 16
|
||||||
|
#define CMD_PROBE_INDEX 0
|
||||||
|
#define CMD_READ_INDEX 1
|
||||||
|
#define CMD_WRITE_INDEX 2
|
||||||
|
#define CMD_ERASE_INDEX 3
|
||||||
|
#define CMD_BENCH_INDEX 4
|
||||||
|
|
||||||
|
int result;
|
||||||
|
static const struct fal_flash_dev *flash_dev = NULL;
|
||||||
|
static const struct fal_partition *part_dev = NULL;
|
||||||
|
size_t i = 0, j = 0;
|
||||||
|
|
||||||
|
const char* help_info[] =
|
||||||
|
{
|
||||||
|
[CMD_PROBE_INDEX] = "fal probe [dev_name|part_name] - probe flash device or partition by given name",
|
||||||
|
[CMD_READ_INDEX] = "fal read addr size - read 'size' bytes starting at 'addr'",
|
||||||
|
[CMD_WRITE_INDEX] = "fal write addr data1 ... dataN - write some bytes 'data' starting at 'addr'",
|
||||||
|
[CMD_ERASE_INDEX] = "fal erase addr size - erase 'size' bytes starting at 'addr'",
|
||||||
|
[CMD_BENCH_INDEX] = "fal bench <blk_size> - benchmark test with per block size",
|
||||||
|
};
|
||||||
|
|
||||||
|
if (fal_init_check() != 1)
|
||||||
|
{
|
||||||
|
rt_kprintf("\n[Warning] FAL is not initialized or failed to initialize!\n\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (argc < 2)
|
||||||
|
{
|
||||||
|
rt_kprintf("Usage:\n");
|
||||||
|
for (i = 0; i < sizeof(help_info) / sizeof(char*); i++)
|
||||||
|
{
|
||||||
|
rt_kprintf("%s\n", help_info[i]);
|
||||||
|
}
|
||||||
|
rt_kprintf("\n");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const char *operator = argv[1];
|
||||||
|
uint32_t addr, size;
|
||||||
|
|
||||||
|
if (!strcmp(operator, "probe"))
|
||||||
|
{
|
||||||
|
if (argc >= 3)
|
||||||
|
{
|
||||||
|
char *dev_name = argv[2];
|
||||||
|
if ((flash_dev = fal_flash_device_find(dev_name)) != NULL)
|
||||||
|
{
|
||||||
|
part_dev = NULL;
|
||||||
|
}
|
||||||
|
else if ((part_dev = fal_partition_find(dev_name)) != NULL)
|
||||||
|
{
|
||||||
|
flash_dev = NULL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rt_kprintf("Device %s NOT found. Probe failed.\n", dev_name);
|
||||||
|
flash_dev = NULL;
|
||||||
|
part_dev = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flash_dev)
|
||||||
|
{
|
||||||
|
rt_kprintf("Probed a flash device | %s | addr: %ld | len: %d |.\n", flash_dev->name,
|
||||||
|
flash_dev->addr, flash_dev->len);
|
||||||
|
}
|
||||||
|
else if (part_dev)
|
||||||
|
{
|
||||||
|
rt_kprintf("Probed a flash partition | %s | flash_dev: %s | offset: %ld | len: %d |.\n",
|
||||||
|
part_dev->name, part_dev->flash_name, part_dev->offset, part_dev->len);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rt_kprintf("No flash device or partition was probed.\n");
|
||||||
|
rt_kprintf("Usage: %s.\n", help_info[CMD_PROBE_INDEX]);
|
||||||
|
fal_show_part_table();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!flash_dev && !part_dev)
|
||||||
|
{
|
||||||
|
rt_kprintf("No flash device or partition was probed. Please run 'fal probe'.\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!rt_strcmp(operator, "read"))
|
||||||
|
{
|
||||||
|
if (argc < 4)
|
||||||
|
{
|
||||||
|
rt_kprintf("Usage: %s.\n", help_info[CMD_READ_INDEX]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
addr = strtol(argv[2], NULL, 0);
|
||||||
|
size = strtol(argv[3], NULL, 0);
|
||||||
|
uint8_t *data = rt_malloc(size);
|
||||||
|
if (data)
|
||||||
|
{
|
||||||
|
if (flash_dev)
|
||||||
|
{
|
||||||
|
result = flash_dev->ops.read(addr, data, size);
|
||||||
|
}
|
||||||
|
else if (part_dev)
|
||||||
|
{
|
||||||
|
result = fal_partition_read(part_dev, addr, data, size);
|
||||||
|
}
|
||||||
|
if (result >= 0)
|
||||||
|
{
|
||||||
|
rt_kprintf("Read data success. Start from 0x%08X, size is %ld. The data is:\n", addr,
|
||||||
|
size);
|
||||||
|
rt_kprintf("Offset (h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F\n");
|
||||||
|
for (i = 0; i < size; i += HEXDUMP_WIDTH)
|
||||||
|
{
|
||||||
|
rt_kprintf("[%08X] ", addr + i);
|
||||||
|
/* dump hex */
|
||||||
|
for (j = 0; j < HEXDUMP_WIDTH; j++)
|
||||||
|
{
|
||||||
|
if (i + j < size)
|
||||||
|
{
|
||||||
|
rt_kprintf("%02X ", data[i + j]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rt_kprintf(" ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* dump char for hex */
|
||||||
|
for (j = 0; j < HEXDUMP_WIDTH; j++)
|
||||||
|
{
|
||||||
|
if (i + j < size)
|
||||||
|
{
|
||||||
|
rt_kprintf("%c", __is_print(data[i + j]) ? data[i + j] : '.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rt_kprintf("\n");
|
||||||
|
}
|
||||||
|
rt_kprintf("\n");
|
||||||
|
}
|
||||||
|
rt_free(data);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rt_kprintf("Low memory!\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (!strcmp(operator, "write"))
|
||||||
|
{
|
||||||
|
if (argc < 4)
|
||||||
|
{
|
||||||
|
rt_kprintf("Usage: %s.\n", help_info[CMD_WRITE_INDEX]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
addr = strtol(argv[2], NULL, 0);
|
||||||
|
size = argc - 3;
|
||||||
|
uint8_t *data = rt_malloc(size);
|
||||||
|
if (data)
|
||||||
|
{
|
||||||
|
for (i = 0; i < size; i++)
|
||||||
|
{
|
||||||
|
data[i] = strtol(argv[3 + i], NULL, 0);
|
||||||
|
}
|
||||||
|
if (flash_dev)
|
||||||
|
{
|
||||||
|
result = flash_dev->ops.write(addr, data, size);
|
||||||
|
}
|
||||||
|
else if (part_dev)
|
||||||
|
{
|
||||||
|
result = fal_partition_write(part_dev, addr, data, size);
|
||||||
|
}
|
||||||
|
if (result >= 0)
|
||||||
|
{
|
||||||
|
rt_kprintf("Write data success. Start from 0x%08X, size is %ld.\n", addr, size);
|
||||||
|
rt_kprintf("Write data: ");
|
||||||
|
for (i = 0; i < size; i++)
|
||||||
|
{
|
||||||
|
rt_kprintf("%d ", data[i]);
|
||||||
|
}
|
||||||
|
rt_kprintf(".\n");
|
||||||
|
}
|
||||||
|
rt_free(data);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rt_kprintf("Low memory!\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (!rt_strcmp(operator, "erase"))
|
||||||
|
{
|
||||||
|
if (argc < 4)
|
||||||
|
{
|
||||||
|
rt_kprintf("Usage: %s.\n", help_info[CMD_ERASE_INDEX]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
addr = strtol(argv[2], NULL, 0);
|
||||||
|
size = strtol(argv[3], NULL, 0);
|
||||||
|
if (flash_dev)
|
||||||
|
{
|
||||||
|
result = flash_dev->ops.erase(addr, size);
|
||||||
|
}
|
||||||
|
else if (part_dev)
|
||||||
|
{
|
||||||
|
result = fal_partition_erase(part_dev, addr, size);
|
||||||
|
}
|
||||||
|
if (result >= 0)
|
||||||
|
{
|
||||||
|
rt_kprintf("Erase data success. Start from 0x%08X, size is %ld.\n", addr, size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (!strcmp(operator, "bench"))
|
||||||
|
{
|
||||||
|
if (argc < 3)
|
||||||
|
{
|
||||||
|
rt_kprintf("Usage: %s.\n", help_info[CMD_BENCH_INDEX]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if ((argc > 3 && strcmp(argv[3], "yes")) || argc < 4)
|
||||||
|
{
|
||||||
|
rt_kprintf("DANGER: It will erase full chip or partition! Please run 'fal bench %d yes'.\n", strtol(argv[2], NULL, 0));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
/* full chip benchmark test */
|
||||||
|
uint32_t start_time, time_cast;
|
||||||
|
size_t write_size = strtol(argv[2], NULL, 0), read_size = strtol(argv[2], NULL, 0), cur_op_size;
|
||||||
|
uint8_t *write_data = (uint8_t *)rt_malloc(write_size), *read_data = (uint8_t *)rt_malloc(read_size);
|
||||||
|
|
||||||
|
if (write_data && read_data)
|
||||||
|
{
|
||||||
|
for (i = 0; i < write_size; i ++) {
|
||||||
|
write_data[i] = i & 0xFF;
|
||||||
|
}
|
||||||
|
if (flash_dev)
|
||||||
|
{
|
||||||
|
size = flash_dev->len;
|
||||||
|
}
|
||||||
|
else if (part_dev)
|
||||||
|
{
|
||||||
|
size = part_dev->len;
|
||||||
|
}
|
||||||
|
/* benchmark testing */
|
||||||
|
rt_kprintf("Erasing %ld bytes data, waiting...\n", size);
|
||||||
|
start_time = rt_tick_get();
|
||||||
|
if (flash_dev)
|
||||||
|
{
|
||||||
|
result = flash_dev->ops.erase(0, size);
|
||||||
|
}
|
||||||
|
else if (part_dev)
|
||||||
|
{
|
||||||
|
result = fal_partition_erase(part_dev, 0, size);
|
||||||
|
}
|
||||||
|
if (result >= 0)
|
||||||
|
{
|
||||||
|
time_cast = rt_tick_get() - start_time;
|
||||||
|
rt_kprintf("Erase benchmark success, total time: %d.%03dS.\n", time_cast / RT_TICK_PER_SECOND,
|
||||||
|
time_cast % RT_TICK_PER_SECOND / ((RT_TICK_PER_SECOND * 1 + 999) / 1000));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rt_kprintf("Erase benchmark has an error. Error code: %d.\n", result);
|
||||||
|
}
|
||||||
|
/* write test */
|
||||||
|
rt_kprintf("Writing %ld bytes data, waiting...\n", size);
|
||||||
|
start_time = rt_tick_get();
|
||||||
|
for (i = 0; i < size; i += write_size)
|
||||||
|
{
|
||||||
|
if (i + write_size <= size)
|
||||||
|
{
|
||||||
|
cur_op_size = write_size;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cur_op_size = size - i;
|
||||||
|
}
|
||||||
|
if (flash_dev)
|
||||||
|
{
|
||||||
|
result = flash_dev->ops.write(i, write_data, cur_op_size);
|
||||||
|
}
|
||||||
|
else if (part_dev)
|
||||||
|
{
|
||||||
|
result = fal_partition_write(part_dev, i, write_data, cur_op_size);
|
||||||
|
}
|
||||||
|
if (result < 0)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (result >= 0)
|
||||||
|
{
|
||||||
|
time_cast = rt_tick_get() - start_time;
|
||||||
|
rt_kprintf("Write benchmark success, total time: %d.%03dS.\n", time_cast / RT_TICK_PER_SECOND,
|
||||||
|
time_cast % RT_TICK_PER_SECOND / ((RT_TICK_PER_SECOND * 1 + 999) / 1000));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rt_kprintf("Write benchmark has an error. Error code: %d.\n", result);
|
||||||
|
}
|
||||||
|
/* read test */
|
||||||
|
rt_kprintf("Reading %ld bytes data, waiting...\n", size);
|
||||||
|
start_time = rt_tick_get();
|
||||||
|
for (i = 0; i < size; i += read_size)
|
||||||
|
{
|
||||||
|
if (i + read_size <= size)
|
||||||
|
{
|
||||||
|
cur_op_size = read_size;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cur_op_size = size - i;
|
||||||
|
}
|
||||||
|
if (flash_dev)
|
||||||
|
{
|
||||||
|
result = flash_dev->ops.read(i, read_data, cur_op_size);
|
||||||
|
}
|
||||||
|
else if (part_dev)
|
||||||
|
{
|
||||||
|
result = fal_partition_read(part_dev, i, read_data, cur_op_size);
|
||||||
|
}
|
||||||
|
/* data check */
|
||||||
|
for (int index = 0; index < cur_op_size; index ++)
|
||||||
|
{
|
||||||
|
if (write_data[index] != read_data[index])
|
||||||
|
{
|
||||||
|
rt_kprintf("%d %d %02x %02x.\n", i, index, write_data[index], read_data[index]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (memcmp(write_data, read_data, cur_op_size))
|
||||||
|
{
|
||||||
|
result = -RT_ERROR;
|
||||||
|
rt_kprintf("Data check ERROR! Please check you flash by other command.\n");
|
||||||
|
}
|
||||||
|
/* has an error */
|
||||||
|
if (result < 0)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (result >= 0)
|
||||||
|
{
|
||||||
|
time_cast = rt_tick_get() - start_time;
|
||||||
|
rt_kprintf("Read benchmark success, total time: %d.%03dS.\n", time_cast / RT_TICK_PER_SECOND,
|
||||||
|
time_cast % RT_TICK_PER_SECOND / ((RT_TICK_PER_SECOND * 1 + 999) / 1000));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rt_kprintf("Read benchmark has an error. Error code: %d.\n", result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rt_kprintf("Low memory!\n");
|
||||||
|
}
|
||||||
|
rt_free(write_data);
|
||||||
|
rt_free(read_data);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rt_kprintf("Usage:\n");
|
||||||
|
for (i = 0; i < sizeof(help_info) / sizeof(char*); i++)
|
||||||
|
{
|
||||||
|
rt_kprintf("%s\n", help_info[i]);
|
||||||
|
}
|
||||||
|
rt_kprintf("\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (result < 0) {
|
||||||
|
rt_kprintf("This operate has an error. Error code: %d.\n", result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
MSH_CMD_EXPORT(fal, FAL (Flash Abstraction Layer) operate.);
|
||||||
|
|
||||||
|
#endif /* defined(RT_USING_FINSH) && defined(FINSH_USING_MSH) */
|
||||||
|
#endif /* RT_VER_NUM */
|
|
@ -0,0 +1,69 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2006-2018, RT-Thread Development Team
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*
|
||||||
|
* Change Logs:
|
||||||
|
* Date Author Notes
|
||||||
|
* 2018-01-26 armink the first version
|
||||||
|
*/
|
||||||
|
#include "eeprom_fm24.h"
|
||||||
|
#include <fal.h>
|
||||||
|
|
||||||
|
static int init(void);
|
||||||
|
static int erase(long offset, size_t size);
|
||||||
|
|
||||||
|
static int read(long offset, uint8_t *buf, size_t size);
|
||||||
|
static int write(long offset, const uint8_t *buf, size_t size);
|
||||||
|
|
||||||
|
// 1.定义 flash 设备
|
||||||
|
struct fal_flash_dev eeprom_fm24 =
|
||||||
|
{
|
||||||
|
.name = EEPROM_FM24_DEV_NAME,
|
||||||
|
.addr = 0,
|
||||||
|
.len = FM24_PAGE_SIZE,
|
||||||
|
.blk_size = EEPROM_FM24_BLOCK_SIZE,
|
||||||
|
.ops = {init, read, write, erase},
|
||||||
|
.write_gran = 1};
|
||||||
|
|
||||||
|
static int init(void)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int erase(long offset, size_t size)
|
||||||
|
{
|
||||||
|
// uint8_t erase_size = size > FAL_ERASE_SIZE ? FAL_ERASE_SIZE : size;
|
||||||
|
// uint8_t buf[FAL_ERASE_SIZE];
|
||||||
|
// osel_memset(buf, 0xFF, FAL_ERASE_SIZE);
|
||||||
|
|
||||||
|
// for (uint8_t i = 0; i < (size / FM24_PAGE_SIZE); i++)
|
||||||
|
// {
|
||||||
|
// uint32_t addr = eeprom_fm24.addr + offset + i * FM24_PAGE_SIZE;
|
||||||
|
// eeprom_fm24_write(addr, (uint8_t *)buf, erase_size);
|
||||||
|
// }
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int read(long offset, uint8_t *buf, size_t size)
|
||||||
|
{
|
||||||
|
/* You can add your code under here. */
|
||||||
|
if (size == 0)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
uint32_t addr = eeprom_fm24.addr + offset;
|
||||||
|
BOOL res = eeprom_fm24_read(addr, buf, size);
|
||||||
|
return res == TRUE ? size : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int write(long offset, const uint8_t *buf, size_t size)
|
||||||
|
{
|
||||||
|
if (size == 0)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
uint32_t addr = eeprom_fm24.addr + offset;
|
||||||
|
BOOL res = eeprom_fm24_write(addr, (uint8_t *)buf, size);
|
||||||
|
return res == TRUE ? (int)size : -1;
|
||||||
|
}
|
|
@ -0,0 +1,87 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2006-2018, RT-Thread Development Team
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*
|
||||||
|
* Change Logs:
|
||||||
|
* Date Author Notes
|
||||||
|
* 2018-01-26 armink the first version
|
||||||
|
*/
|
||||||
|
#include "eeprom_m95.h"
|
||||||
|
#include <fal.h>
|
||||||
|
|
||||||
|
static int init(void);
|
||||||
|
static int erase(long offset, size_t size);
|
||||||
|
|
||||||
|
static int read1(long offset, uint8_t *buf, size_t size);
|
||||||
|
static int read2(long offset, uint8_t *buf, size_t size);
|
||||||
|
static int write1(long offset, const uint8_t *buf, size_t size);
|
||||||
|
static int write2(long offset, const uint8_t *buf, size_t size);
|
||||||
|
|
||||||
|
// 1.定义 flash 设备
|
||||||
|
struct fal_flash_dev eeprom_m95_1 =
|
||||||
|
{
|
||||||
|
.name = EEPROM_M95_1_DEV_NAME,
|
||||||
|
.addr = 10 * M95_PAGE_SIZE_256,
|
||||||
|
.len = EEPROM_M95_1_SIZE - 10 * M95_PAGE_SIZE_256,
|
||||||
|
.blk_size = EEPROM_M95_1_BLOCK_SIZE,
|
||||||
|
.ops = {init, read1, write1, erase},
|
||||||
|
.write_gran = 1}; // 设置写粒度,单位 bit,EPPROM写粒度为1bit
|
||||||
|
|
||||||
|
struct fal_flash_dev eeprom_m95_2 =
|
||||||
|
{
|
||||||
|
.name = EEPROM_M95_2_DEV_NAME,
|
||||||
|
.addr = 0x000000,
|
||||||
|
.len = EEPROM_M95_2_SIZE,
|
||||||
|
.blk_size = EEPROM_M95_2_BLOCK_SIZE,
|
||||||
|
.ops = {init, read2, write2, erase},
|
||||||
|
.write_gran = 1};
|
||||||
|
|
||||||
|
static int init(void)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int erase(long offset, size_t size)
|
||||||
|
{
|
||||||
|
// uint8_t erase_size = size > FAL_ERASE_SIZE ? FAL_ERASE_SIZE : size;
|
||||||
|
// uint8_t buf[FAL_ERASE_SIZE];
|
||||||
|
// osel_memset(buf, 0xFF, FAL_ERASE_SIZE);
|
||||||
|
|
||||||
|
// for (uint8_t i = 0; i < (size / M95_PAGE_SIZE_256); i++)
|
||||||
|
// {
|
||||||
|
// uint32_t addr = eeprom_m95_1.addr + offset + i * M95_PAGE_SIZE_256;
|
||||||
|
// eeprom_m95_write(M95_1, addr, (uint8_t *)buf, erase_size);
|
||||||
|
// }
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int read1(long offset, uint8_t *buf, size_t size)
|
||||||
|
{
|
||||||
|
/* You can add your code under here. */
|
||||||
|
uint32_t addr = eeprom_m95_1.addr + offset;
|
||||||
|
BOOL res = eeprom_m95_read(M95_1, addr, buf, size);
|
||||||
|
return res == TRUE ? size : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int write1(long offset, const uint8_t *buf, size_t size)
|
||||||
|
{
|
||||||
|
uint32_t addr = eeprom_m95_1.addr + offset;
|
||||||
|
BOOL res = eeprom_m95_write(M95_1, addr, (uint8_t *)buf, size);
|
||||||
|
return res == TRUE ? (int)size : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int read2(long offset, uint8_t *buf, size_t size)
|
||||||
|
{
|
||||||
|
/* You can add your code under here. */
|
||||||
|
uint32_t addr = eeprom_m95_2.addr + offset;
|
||||||
|
BOOL res = eeprom_m95_read(M95_2, addr, buf, size);
|
||||||
|
return res == TRUE ? size : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int write2(long offset, const uint8_t *buf, size_t size)
|
||||||
|
{
|
||||||
|
uint32_t addr = eeprom_m95_2.addr + offset;
|
||||||
|
BOOL res = eeprom_m95_write(M95_2, addr, (uint8_t *)buf, size);
|
||||||
|
return res == TRUE ? (int)size : -1;
|
||||||
|
}
|
|
@ -0,0 +1,157 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2020, Armink, <armink.ztl@gmail.com>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* @brief Initialize interface.
|
||||||
|
*
|
||||||
|
* Some initialize interface for this library.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <flashdb.h>
|
||||||
|
#include <fdb_low_lvl.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <inttypes.h>
|
||||||
|
|
||||||
|
#ifdef FDB_USING_FILE_POSIX_MODE
|
||||||
|
#if !defined(_MSC_VER)
|
||||||
|
#include <unistd.h>
|
||||||
|
#endif
|
||||||
|
#endif /* FDB_USING_FILE_POSIX_MODE */
|
||||||
|
|
||||||
|
#define FDB_LOG_TAG ""
|
||||||
|
|
||||||
|
#if !defined(FDB_USING_FAL_MODE) && !defined(FDB_USING_FILE_MODE)
|
||||||
|
#error "Please defined the FDB_USING_FAL_MODE or FDB_USING_FILE_MODE macro"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
fdb_err_t _fdb_init_ex(fdb_db_t db, const char *name, const char *path, fdb_db_type type, void *user_data)
|
||||||
|
{
|
||||||
|
FDB_ASSERT(db);
|
||||||
|
FDB_ASSERT(name);
|
||||||
|
FDB_ASSERT(path);
|
||||||
|
|
||||||
|
if (db->init_ok) {
|
||||||
|
return FDB_NO_ERR;
|
||||||
|
}
|
||||||
|
|
||||||
|
db->name = name;
|
||||||
|
db->type = type;
|
||||||
|
db->user_data = user_data;
|
||||||
|
|
||||||
|
if (db->file_mode) {
|
||||||
|
#ifdef FDB_USING_FILE_MODE
|
||||||
|
memset(db->cur_file_sec, FDB_FAILED_ADDR, FDB_FILE_CACHE_TABLE_SIZE * sizeof(db->cur_file_sec[0]));
|
||||||
|
/* must set when using file mode */
|
||||||
|
FDB_ASSERT(db->sec_size != 0);
|
||||||
|
FDB_ASSERT(db->max_size != 0);
|
||||||
|
#ifdef FDB_USING_FILE_POSIX_MODE
|
||||||
|
memset(db->cur_file, -1, FDB_FILE_CACHE_TABLE_SIZE * sizeof(db->cur_file[0]));
|
||||||
|
#else
|
||||||
|
memset(db->cur_file, 0, FDB_FILE_CACHE_TABLE_SIZE * sizeof(db->cur_file[0]));
|
||||||
|
#endif
|
||||||
|
db->storage.dir = path;
|
||||||
|
FDB_ASSERT(strlen(path) != 0)
|
||||||
|
#endif
|
||||||
|
} else {
|
||||||
|
#ifdef FDB_USING_FAL_MODE
|
||||||
|
size_t block_size;
|
||||||
|
|
||||||
|
/* FAL (Flash Abstraction Layer) initialization */
|
||||||
|
fal_init();
|
||||||
|
/* check the flash partition */
|
||||||
|
if ((db->storage.part = fal_partition_find(path)) == NULL) {
|
||||||
|
FDB_INFO("Error: Partition (%s) not found.\n", path);
|
||||||
|
return FDB_PART_NOT_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
block_size = fal_flash_device_find(db->storage.part->flash_name)->blk_size;
|
||||||
|
if (db->sec_size == 0) {
|
||||||
|
db->sec_size = block_size;
|
||||||
|
} else {
|
||||||
|
/* must be aligned with block size */
|
||||||
|
if (db->sec_size % block_size != 0) {
|
||||||
|
FDB_INFO("Error: db sector size (%" PRIu32 ") MUST align with block size (%zu).\n", db->sec_size, block_size);
|
||||||
|
return FDB_INIT_FAILED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
db->max_size = db->storage.part->len;
|
||||||
|
#endif /* FDB_USING_FAL_MODE */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* the block size MUST to be the Nth power of 2 */
|
||||||
|
FDB_ASSERT((db->sec_size & (db->sec_size - 1)) == 0);
|
||||||
|
/* must align with sector size */
|
||||||
|
if (db->max_size % db->sec_size != 0) {
|
||||||
|
FDB_INFO("Error: db total size (%" PRIu32 ") MUST align with sector size (%" PRIu32 ").\n", db->max_size, db->sec_size);
|
||||||
|
return FDB_INIT_FAILED;
|
||||||
|
}
|
||||||
|
/* must has more than or equal 2 sectors */
|
||||||
|
if (db->max_size / db->sec_size < 2) {
|
||||||
|
FDB_INFO("Error: db MUST has more than or equal 2 sectors, current has %" PRIu32 " sector(s)\n", db->max_size / db->sec_size);
|
||||||
|
return FDB_INIT_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
return FDB_NO_ERR;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _fdb_init_finish(fdb_db_t db, fdb_err_t result)
|
||||||
|
{
|
||||||
|
static bool log_is_show = false;
|
||||||
|
if (result == FDB_NO_ERR) {
|
||||||
|
db->init_ok = true;
|
||||||
|
if (!log_is_show) {
|
||||||
|
FDB_INFO("FlashDB V%s is initialize success.\n", FDB_SW_VERSION);
|
||||||
|
FDB_INFO("You can get the latest version on https://github.com/armink/FlashDB .\n");
|
||||||
|
log_is_show = true;
|
||||||
|
}
|
||||||
|
} else if (!db->not_formatable) {
|
||||||
|
FDB_INFO("Error: %s (%s@%s) is initialize fail (%d).\n", db->type == FDB_DB_TYPE_KV ? "KVDB" : "TSDB",
|
||||||
|
db->name, _fdb_db_path(db), (int)result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void _fdb_deinit(fdb_db_t db)
|
||||||
|
{
|
||||||
|
FDB_ASSERT(db);
|
||||||
|
|
||||||
|
if (db->init_ok) {
|
||||||
|
#ifdef FDB_USING_FILE_MODE
|
||||||
|
for (int i = 0; i < FDB_FILE_CACHE_TABLE_SIZE; i++) {
|
||||||
|
#ifdef FDB_USING_FILE_POSIX_MODE
|
||||||
|
if (db->cur_file[i] > 0) {
|
||||||
|
close(db->cur_file[i]);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
if (db->cur_file[i] != 0) {
|
||||||
|
fclose(db->cur_file[i]);
|
||||||
|
}
|
||||||
|
#endif /* FDB_USING_FILE_POSIX_MODE */
|
||||||
|
}
|
||||||
|
#endif /* FDB_USING_FILE_MODE */
|
||||||
|
}
|
||||||
|
|
||||||
|
db->init_ok = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *_fdb_db_path(fdb_db_t db)
|
||||||
|
{
|
||||||
|
if (db->file_mode) {
|
||||||
|
#ifdef FDB_USING_FILE_MODE
|
||||||
|
return db->storage.dir;
|
||||||
|
#else
|
||||||
|
return NULL;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
#ifdef FDB_USING_FAL_MODE
|
||||||
|
return db->storage.part->name;
|
||||||
|
#else
|
||||||
|
return NULL;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,50 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2020, Armink, <armink.ztl@gmail.com>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* @brief configuration file
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _FDB_CFG_H_
|
||||||
|
#define _FDB_CFG_H_
|
||||||
|
|
||||||
|
/* using KVDB feature */
|
||||||
|
#define FDB_USING_KVDB
|
||||||
|
|
||||||
|
#ifdef FDB_USING_KVDB
|
||||||
|
/* Auto update KV to latest default when current KVDB version number is changed. @see fdb_kvdb.ver_num */
|
||||||
|
#define FDB_KV_AUTO_UPDATE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* using TSDB (Time series database) feature */
|
||||||
|
#define FDB_USING_TSDB
|
||||||
|
|
||||||
|
/* Using FAL storage mode */
|
||||||
|
#define FDB_USING_FAL_MODE
|
||||||
|
|
||||||
|
#ifdef FDB_USING_FAL_MODE
|
||||||
|
/* the flash write granularity, unit: bit
|
||||||
|
* only support 1(nor flash)/ 8(stm32f2/f4)/ 32(stm32f1)/ 64(stm32f7)/ 128(stm32h5) */
|
||||||
|
#define FDB_WRITE_GRAN 1 /* @note you must define it for a value */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Using file storage mode by LIBC file API, like fopen/fread/fwrte/fclose */
|
||||||
|
/* #define FDB_USING_FILE_LIBC_MODE */
|
||||||
|
|
||||||
|
/* Using file storage mode by POSIX file API, like open/read/write/close */
|
||||||
|
/* #define FDB_USING_FILE_POSIX_MODE */
|
||||||
|
|
||||||
|
/* MCU Endian Configuration, default is Little Endian Order. */
|
||||||
|
/* #define FDB_BIG_ENDIAN */
|
||||||
|
|
||||||
|
/* log print macro. default EF_PRINT macro is printf() */
|
||||||
|
/* #define FDB_PRINT(...) my_printf(__VA_ARGS__) */
|
||||||
|
|
||||||
|
/* print debug information */
|
||||||
|
// #define FDB_DEBUG_ENABLE
|
||||||
|
|
||||||
|
#endif /* _FDB_CFG_H_ */
|
|
@ -0,0 +1,385 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2020-2023, Armink, <armink.ztl@gmail.com>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* @brief Public definition.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _FDB_DEF_H_
|
||||||
|
#define _FDB_DEF_H_
|
||||||
|
|
||||||
|
#ifdef FDB_USING_NATIVE_ASSERT
|
||||||
|
#include <assert.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* software version number */
|
||||||
|
#define FDB_SW_VERSION "2.1.1"
|
||||||
|
#define FDB_SW_VERSION_NUM 0x20101
|
||||||
|
|
||||||
|
/* the KV max name length must less then it */
|
||||||
|
#ifndef FDB_KV_NAME_MAX
|
||||||
|
#define FDB_KV_NAME_MAX 64
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* the KV cache table size, it will improve KV search speed when using cache */
|
||||||
|
#ifndef FDB_KV_CACHE_TABLE_SIZE
|
||||||
|
#define FDB_KV_CACHE_TABLE_SIZE 64
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* the sector cache table size, it will improve KV save speed when using cache */
|
||||||
|
#ifndef FDB_SECTOR_CACHE_TABLE_SIZE
|
||||||
|
#define FDB_SECTOR_CACHE_TABLE_SIZE 8
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if (FDB_KV_CACHE_TABLE_SIZE > 0) && (FDB_SECTOR_CACHE_TABLE_SIZE > 0)
|
||||||
|
#define FDB_KV_USING_CACHE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(FDB_USING_FILE_LIBC_MODE) || defined(FDB_USING_FILE_POSIX_MODE)
|
||||||
|
#define FDB_USING_FILE_MODE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* the file cache table size, it will improve GC speed in file mode when using cache */
|
||||||
|
#ifndef FDB_FILE_CACHE_TABLE_SIZE
|
||||||
|
#define FDB_FILE_CACHE_TABLE_SIZE 4
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef FDB_WRITE_GRAN
|
||||||
|
#define FDB_WRITE_GRAN 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* log function. default FDB_PRINT macro is printf() */
|
||||||
|
// #ifndef FDB_PRINT
|
||||||
|
// #define FDB_PRINT(...) printf(__VA_ARGS__)
|
||||||
|
// #endif
|
||||||
|
#ifndef FDB_PRINT
|
||||||
|
#define FDB_PRINT(...)
|
||||||
|
#endif
|
||||||
|
#define FDB_LOG_PREFIX1() FDB_PRINT("[FlashDB]" FDB_LOG_TAG)
|
||||||
|
#define FDB_LOG_PREFIX2() FDB_PRINT(" ")
|
||||||
|
#define FDB_LOG_PREFIX() \
|
||||||
|
FDB_LOG_PREFIX1(); \
|
||||||
|
FDB_LOG_PREFIX2()
|
||||||
|
#ifdef FDB_DEBUG_ENABLE
|
||||||
|
#define FDB_DEBUG(...) \
|
||||||
|
FDB_LOG_PREFIX(); \
|
||||||
|
FDB_PRINT("(%s:%d) ", __FILE__, __LINE__); \
|
||||||
|
FDB_PRINT(__VA_ARGS__)
|
||||||
|
#else
|
||||||
|
#define FDB_DEBUG(...)
|
||||||
|
#endif
|
||||||
|
/* routine print function. Must be implement by user. */
|
||||||
|
#define FDB_INFO(...) \
|
||||||
|
FDB_LOG_PREFIX(); \
|
||||||
|
FDB_PRINT(__VA_ARGS__)
|
||||||
|
/* assert for developer. */
|
||||||
|
#ifdef FDB_USING_NATIVE_ASSERT
|
||||||
|
#define FDB_ASSERT(EXPR) assert(EXPR);
|
||||||
|
#else
|
||||||
|
#ifndef FDB_ASSERT
|
||||||
|
#define FDB_ASSERT(EXPR) \
|
||||||
|
if (!(EXPR)) \
|
||||||
|
{ \
|
||||||
|
FDB_INFO("(%s) has assert failed at %s.\n", #EXPR, __func__); \
|
||||||
|
while (1) \
|
||||||
|
; \
|
||||||
|
}
|
||||||
|
#endif /* FDB_ASSERT */
|
||||||
|
#endif /* FDB_USING_NATIVE_ASSERT */
|
||||||
|
|
||||||
|
#define FDB_KVDB_CTRL_SET_SEC_SIZE 0x00 /**< set sector size control command, this change MUST before database initialization */
|
||||||
|
#define FDB_KVDB_CTRL_GET_SEC_SIZE 0x01 /**< get sector size control command */
|
||||||
|
#define FDB_KVDB_CTRL_SET_LOCK 0x02 /**< set lock function control command */
|
||||||
|
#define FDB_KVDB_CTRL_SET_UNLOCK 0x03 /**< set unlock function control command */
|
||||||
|
#define FDB_KVDB_CTRL_SET_FILE_MODE 0x09 /**< set file mode control command, this change MUST before database initialization */
|
||||||
|
#define FDB_KVDB_CTRL_SET_MAX_SIZE 0x0A /**< set database max size in file mode control command, this change MUST before database initialization */
|
||||||
|
#define FDB_KVDB_CTRL_SET_NOT_FORMAT 0x0B /**< set database NOT format mode control command, this change MUST before database initialization */
|
||||||
|
|
||||||
|
#define FDB_TSDB_CTRL_SET_SEC_SIZE 0x00 /**< set sector size control command, this change MUST before database initialization */
|
||||||
|
#define FDB_TSDB_CTRL_GET_SEC_SIZE 0x01 /**< get sector size control command */
|
||||||
|
#define FDB_TSDB_CTRL_SET_LOCK 0x02 /**< set lock function control command */
|
||||||
|
#define FDB_TSDB_CTRL_SET_UNLOCK 0x03 /**< set unlock function control command */
|
||||||
|
#define FDB_TSDB_CTRL_SET_ROLLOVER 0x04 /**< set rollover control command, this change MUST after database initialization */
|
||||||
|
#define FDB_TSDB_CTRL_GET_ROLLOVER 0x05 /**< get rollover control command */
|
||||||
|
#define FDB_TSDB_CTRL_GET_LAST_TIME 0x06 /**< get last save time control command */
|
||||||
|
#define FDB_TSDB_CTRL_SET_FILE_MODE 0x09 /**< set file mode control command, this change MUST before database initialization */
|
||||||
|
#define FDB_TSDB_CTRL_SET_MAX_SIZE 0x0A /**< set database max size in file mode control command, this change MUST before database initialization */
|
||||||
|
#define FDB_TSDB_CTRL_SET_NOT_FORMAT 0x0B /**< set database NOT formatable mode control command, this change MUST before database initialization */
|
||||||
|
|
||||||
|
#ifdef FDB_USING_TIMESTAMP_64BIT
|
||||||
|
typedef int64_t fdb_time_t;
|
||||||
|
#else
|
||||||
|
typedef int32_t fdb_time_t;
|
||||||
|
#endif /* FDB_USING_TIMESTAMP_64BIT */
|
||||||
|
|
||||||
|
typedef fdb_time_t (*fdb_get_time)(void);
|
||||||
|
|
||||||
|
struct fdb_default_kv_node
|
||||||
|
{
|
||||||
|
char *key;
|
||||||
|
void *value;
|
||||||
|
size_t value_len;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct fdb_default_kv
|
||||||
|
{
|
||||||
|
struct fdb_default_kv_node *kvs;
|
||||||
|
size_t num;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* error code */
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
FDB_NO_ERR,
|
||||||
|
FDB_ERASE_ERR,
|
||||||
|
FDB_READ_ERR,
|
||||||
|
FDB_WRITE_ERR,
|
||||||
|
FDB_PART_NOT_FOUND,
|
||||||
|
FDB_KV_NAME_ERR,
|
||||||
|
FDB_KV_NAME_EXIST,
|
||||||
|
FDB_SAVED_FULL,
|
||||||
|
FDB_INIT_FAILED,
|
||||||
|
} fdb_err_t;
|
||||||
|
|
||||||
|
enum fdb_kv_status
|
||||||
|
{
|
||||||
|
FDB_KV_UNUSED,
|
||||||
|
FDB_KV_PRE_WRITE,
|
||||||
|
FDB_KV_WRITE,
|
||||||
|
FDB_KV_PRE_DELETE,
|
||||||
|
FDB_KV_DELETED,
|
||||||
|
FDB_KV_ERR_HDR,
|
||||||
|
#define FDB_KV_STATUS_NUM 6
|
||||||
|
};
|
||||||
|
typedef enum fdb_kv_status fdb_kv_status_t;
|
||||||
|
|
||||||
|
enum fdb_tsl_status
|
||||||
|
{
|
||||||
|
FDB_TSL_UNUSED,
|
||||||
|
FDB_TSL_PRE_WRITE,
|
||||||
|
FDB_TSL_WRITE,
|
||||||
|
FDB_TSL_USER_STATUS1,
|
||||||
|
FDB_TSL_DELETED,
|
||||||
|
FDB_TSL_USER_STATUS2,
|
||||||
|
#define FDB_TSL_STATUS_NUM 6
|
||||||
|
};
|
||||||
|
typedef enum fdb_tsl_status fdb_tsl_status_t;
|
||||||
|
|
||||||
|
/* key-value node object */
|
||||||
|
struct fdb_kv
|
||||||
|
{
|
||||||
|
fdb_kv_status_t status; /**< node status, @see fdb_kv_status_t */
|
||||||
|
bool crc_is_ok; /**< node CRC32 check is OK */
|
||||||
|
uint8_t name_len; /**< name length */
|
||||||
|
uint32_t magic; /**< magic word(`K`, `V`, `4`, `0`) */
|
||||||
|
uint32_t len; /**< node total length (header + name + value), must align by FDB_WRITE_GRAN */
|
||||||
|
uint32_t value_len; /**< value length */
|
||||||
|
char name[FDB_KV_NAME_MAX]; /**< name */
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
uint32_t start; /**< node start address */
|
||||||
|
uint32_t value; /**< value start address */
|
||||||
|
} addr;
|
||||||
|
};
|
||||||
|
typedef struct fdb_kv *fdb_kv_t;
|
||||||
|
|
||||||
|
struct fdb_kv_iterator
|
||||||
|
{
|
||||||
|
struct fdb_kv curr_kv; /**< Current KV we get from the iterator */
|
||||||
|
uint32_t iterated_cnt; /**< How many KVs have we iterated already */
|
||||||
|
size_t iterated_obj_bytes; /**< Total storage size of KVs we have iterated. */
|
||||||
|
size_t iterated_value_bytes; /**< Total value size of KVs we have iterated. */
|
||||||
|
uint32_t sector_addr; /**< Current sector address we're iterating. DO NOT touch it. */
|
||||||
|
uint32_t traversed_len; /**< Traversed sector total length. */
|
||||||
|
};
|
||||||
|
typedef struct fdb_kv_iterator *fdb_kv_iterator_t;
|
||||||
|
|
||||||
|
/* time series log node object */
|
||||||
|
struct fdb_tsl
|
||||||
|
{
|
||||||
|
fdb_tsl_status_t status; /**< node status, @see fdb_log_status_t */
|
||||||
|
fdb_time_t time; /**< node timestamp */
|
||||||
|
uint32_t log_len; /**< log length, must align by FDB_WRITE_GRAN */
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
uint32_t index; /**< node index address */
|
||||||
|
uint32_t log; /**< log data address */
|
||||||
|
} addr;
|
||||||
|
};
|
||||||
|
typedef struct fdb_tsl *fdb_tsl_t;
|
||||||
|
typedef bool (*fdb_tsl_cb)(fdb_tsl_t tsl, void *arg);
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
FDB_DB_TYPE_KV,
|
||||||
|
FDB_DB_TYPE_TS,
|
||||||
|
} fdb_db_type;
|
||||||
|
|
||||||
|
/* the flash sector store status */
|
||||||
|
enum fdb_sector_store_status
|
||||||
|
{
|
||||||
|
FDB_SECTOR_STORE_UNUSED,
|
||||||
|
FDB_SECTOR_STORE_EMPTY,
|
||||||
|
FDB_SECTOR_STORE_USING,
|
||||||
|
FDB_SECTOR_STORE_FULL,
|
||||||
|
#define FDB_SECTOR_STORE_STATUS_NUM 4
|
||||||
|
};
|
||||||
|
typedef enum fdb_sector_store_status fdb_sector_store_status_t;
|
||||||
|
|
||||||
|
/* the flash sector dirty status */
|
||||||
|
enum fdb_sector_dirty_status
|
||||||
|
{
|
||||||
|
FDB_SECTOR_DIRTY_UNUSED,
|
||||||
|
FDB_SECTOR_DIRTY_FALSE,
|
||||||
|
FDB_SECTOR_DIRTY_TRUE,
|
||||||
|
FDB_SECTOR_DIRTY_GC,
|
||||||
|
#define FDB_SECTOR_DIRTY_STATUS_NUM 4
|
||||||
|
};
|
||||||
|
typedef enum fdb_sector_dirty_status fdb_sector_dirty_status_t;
|
||||||
|
|
||||||
|
/* KVDB section information */
|
||||||
|
struct kvdb_sec_info
|
||||||
|
{
|
||||||
|
bool check_ok; /**< sector header check is OK */
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
fdb_sector_store_status_t store; /**< sector store status @see fdb_sector_store_status_t */
|
||||||
|
fdb_sector_dirty_status_t dirty; /**< sector dirty status @see sector_dirty_status_t */
|
||||||
|
} status;
|
||||||
|
uint32_t addr; /**< sector start address */
|
||||||
|
uint32_t magic; /**< magic word(`E`, `F`, `4`, `0`) */
|
||||||
|
uint32_t combined; /**< the combined next sector number, 0xFFFFFFFF: not combined */
|
||||||
|
size_t remain; /**< remain size */
|
||||||
|
uint32_t empty_kv; /**< the next empty KV node start address */
|
||||||
|
};
|
||||||
|
typedef struct kvdb_sec_info *kv_sec_info_t;
|
||||||
|
|
||||||
|
/* TSDB section information */
|
||||||
|
struct tsdb_sec_info
|
||||||
|
{
|
||||||
|
bool check_ok; /**< sector header check is OK */
|
||||||
|
fdb_sector_store_status_t status; /**< sector store status @see fdb_sector_store_status_t */
|
||||||
|
uint32_t addr; /**< sector start address */
|
||||||
|
uint32_t magic; /**< magic word(`T`, `S`, `L`, `0`) */
|
||||||
|
fdb_time_t start_time; /**< the first start node's timestamp, 0xFFFFFFFF: unused */
|
||||||
|
fdb_time_t end_time; /**< the last end node's timestamp, 0xFFFFFFFF: unused */
|
||||||
|
uint32_t end_idx; /**< the last end node's index, 0xFFFFFFFF: unused */
|
||||||
|
fdb_tsl_status_t end_info_stat[2]; /**< the last end node's info status */
|
||||||
|
size_t remain; /**< remain size */
|
||||||
|
uint32_t empty_idx; /**< the next empty node index address */
|
||||||
|
uint32_t empty_data; /**< the next empty node's data end address */
|
||||||
|
};
|
||||||
|
typedef struct tsdb_sec_info *tsdb_sec_info_t;
|
||||||
|
|
||||||
|
struct kv_cache_node
|
||||||
|
{
|
||||||
|
uint16_t name_crc; /**< KV name's CRC32 low 16bit value */
|
||||||
|
uint16_t active; /**< KV node access active degree */
|
||||||
|
uint32_t addr; /**< KV node address */
|
||||||
|
};
|
||||||
|
typedef struct kv_cache_node *kv_cache_node_t;
|
||||||
|
|
||||||
|
/* database structure */
|
||||||
|
typedef struct fdb_db *fdb_db_t;
|
||||||
|
struct fdb_db
|
||||||
|
{
|
||||||
|
const char *name; /**< database name */
|
||||||
|
fdb_db_type type; /**< database type */
|
||||||
|
union
|
||||||
|
{
|
||||||
|
#ifdef FDB_USING_FAL_MODE
|
||||||
|
const struct fal_partition *part; /**< flash partition for saving database */
|
||||||
|
#endif
|
||||||
|
#ifdef FDB_USING_FILE_MODE
|
||||||
|
const char *dir; /**< directory path for saving database */
|
||||||
|
#endif
|
||||||
|
} storage;
|
||||||
|
uint32_t sec_size; /**< flash section size. It's a multiple of block size */
|
||||||
|
uint32_t max_size; /**< database max size. It's a multiple of section size */
|
||||||
|
uint32_t oldest_addr; /**< the oldest sector start address */
|
||||||
|
bool init_ok; /**< initialized successfully */
|
||||||
|
bool file_mode; /**< is file mode, default is false */
|
||||||
|
bool not_formatable; /**< is can NOT be formated mode, default is false */
|
||||||
|
#ifdef FDB_USING_FILE_MODE
|
||||||
|
uint32_t cur_file_sec[FDB_FILE_CACHE_TABLE_SIZE]; /**< last operate sector address */
|
||||||
|
#if defined(FDB_USING_FILE_POSIX_MODE)
|
||||||
|
int cur_file[FDB_FILE_CACHE_TABLE_SIZE]; /**< current file object */
|
||||||
|
#elif defined(FDB_USING_FILE_LIBC_MODE)
|
||||||
|
FILE *cur_file[FDB_FILE_CACHE_TABLE_SIZE]; /**< current file object */
|
||||||
|
#endif /* FDB_USING_FILE_MODE */
|
||||||
|
uint32_t cur_sec; /**< current operate sector address */
|
||||||
|
#endif
|
||||||
|
void (*lock)(fdb_db_t db); /**< lock the database operate */
|
||||||
|
void (*unlock)(fdb_db_t db); /**< unlock the database operate */
|
||||||
|
|
||||||
|
void *user_data;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* KVDB structure */
|
||||||
|
struct fdb_kvdb
|
||||||
|
{
|
||||||
|
struct fdb_db parent; /**< inherit from fdb_db */
|
||||||
|
struct fdb_default_kv default_kvs; /**< default KV */
|
||||||
|
bool gc_request; /**< request a GC check */
|
||||||
|
bool in_recovery_check; /**< is in recovery check status when first reboot */
|
||||||
|
struct fdb_kv cur_kv;
|
||||||
|
struct kvdb_sec_info cur_sector;
|
||||||
|
bool last_is_complete_del;
|
||||||
|
|
||||||
|
#ifdef FDB_KV_USING_CACHE
|
||||||
|
/* KV cache table */
|
||||||
|
struct kv_cache_node kv_cache_table[FDB_KV_CACHE_TABLE_SIZE];
|
||||||
|
/* sector cache table, it caching the sector info which status is current using */
|
||||||
|
struct kvdb_sec_info sector_cache_table[FDB_SECTOR_CACHE_TABLE_SIZE];
|
||||||
|
#endif /* FDB_KV_USING_CACHE */
|
||||||
|
|
||||||
|
#ifdef FDB_KV_AUTO_UPDATE
|
||||||
|
uint32_t ver_num; /**< setting version number for update */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void *user_data;
|
||||||
|
};
|
||||||
|
typedef struct fdb_kvdb *fdb_kvdb_t;
|
||||||
|
|
||||||
|
/* TSDB structure */
|
||||||
|
struct fdb_tsdb
|
||||||
|
{
|
||||||
|
struct fdb_db parent; /**< inherit from fdb_db */
|
||||||
|
struct tsdb_sec_info cur_sec; /**< current using sector */
|
||||||
|
fdb_time_t last_time; /**< last TSL timestamp */
|
||||||
|
fdb_get_time get_time; /**< the current timestamp get function */
|
||||||
|
size_t max_len; /**< the maximum length of each log */
|
||||||
|
bool rollover; /**< the oldest data will rollover by newest data, default is true */
|
||||||
|
|
||||||
|
void *user_data;
|
||||||
|
};
|
||||||
|
typedef struct fdb_tsdb *fdb_tsdb_t;
|
||||||
|
|
||||||
|
/* blob structure */
|
||||||
|
struct fdb_blob
|
||||||
|
{
|
||||||
|
void *buf; /**< blob data buffer */
|
||||||
|
size_t size; /**< blob data buffer size */
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
uint32_t meta_addr; /**< saved KV or TSL index address */
|
||||||
|
uint32_t addr; /**< blob data saved address */
|
||||||
|
size_t len; /**< blob data saved length */
|
||||||
|
} saved;
|
||||||
|
};
|
||||||
|
typedef struct fdb_blob *fdb_blob_t;
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* _FDB_DEF_H_ */
|
|
@ -0,0 +1,318 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2020, Armink, <armink.ztl@gmail.com>
|
||||||
|
* Copyright (c) 2020, enkiller, <462747508@qq.com>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <flashdb.h>
|
||||||
|
#include <fdb_low_lvl.h>
|
||||||
|
|
||||||
|
#define FDB_LOG_TAG "[file]"
|
||||||
|
|
||||||
|
#ifdef FDB_USING_FILE_MODE
|
||||||
|
|
||||||
|
#define DB_PATH_MAX 256
|
||||||
|
|
||||||
|
static void get_db_file_path(fdb_db_t db, uint32_t addr, char *path, size_t size)
|
||||||
|
{
|
||||||
|
#define DB_NAME_MAX 8
|
||||||
|
|
||||||
|
/* from db_name.fdb.0 to db_name.fdb.n */
|
||||||
|
char file_name[DB_NAME_MAX + 4 + 10];
|
||||||
|
uint32_t sec_addr = FDB_ALIGN_DOWN(addr, db->sec_size);
|
||||||
|
int index = sec_addr / db->sec_size;
|
||||||
|
|
||||||
|
snprintf(file_name, sizeof(file_name), "%.*s.fdb.%d", DB_NAME_MAX, db->name, index);
|
||||||
|
if (strlen(db->storage.dir) + 1 + strlen(file_name) >= size) {
|
||||||
|
/* path is too long */
|
||||||
|
FDB_INFO("Error: db (%s) file path (%s) is too log.\n", file_name, db->storage.dir);
|
||||||
|
FDB_ASSERT(0)
|
||||||
|
}
|
||||||
|
snprintf(path, size, "%s/%s", db->storage.dir, file_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(FDB_USING_FILE_POSIX_MODE)
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#if !defined(_MSC_VER)
|
||||||
|
#include <unistd.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static int get_file_from_cache(fdb_db_t db, uint32_t sec_addr)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < FDB_FILE_CACHE_TABLE_SIZE; i++) {
|
||||||
|
if (db->cur_file_sec[i] == sec_addr)
|
||||||
|
return db->cur_file[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void update_file_cache(fdb_db_t db, uint32_t sec_addr, int fd)
|
||||||
|
{
|
||||||
|
int free_index = FDB_FILE_CACHE_TABLE_SIZE;
|
||||||
|
|
||||||
|
for (int i = 0; i < FDB_FILE_CACHE_TABLE_SIZE; i++) {
|
||||||
|
if (db->cur_file_sec[i] == sec_addr) {
|
||||||
|
db->cur_file[i] = fd;
|
||||||
|
return;
|
||||||
|
} else if (db->cur_file[i] == -1) {
|
||||||
|
free_index = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fd > 0) {
|
||||||
|
if (free_index < FDB_FILE_CACHE_TABLE_SIZE) {
|
||||||
|
db->cur_file[free_index] = fd;
|
||||||
|
db->cur_file_sec[free_index] = sec_addr;
|
||||||
|
} else {
|
||||||
|
/* cache is full, move to end */
|
||||||
|
for (int i = FDB_FILE_CACHE_TABLE_SIZE - 1; i > 0; i--) {
|
||||||
|
close(db->cur_file[i]);
|
||||||
|
memcpy(&db->cur_file[i], &db->cur_file[i - 1], sizeof(db->cur_file[0]));
|
||||||
|
memcpy(&db->cur_file_sec[i], &db->cur_file_sec[i - 1], sizeof(db->cur_file_sec[0]));
|
||||||
|
}
|
||||||
|
/* add to head */
|
||||||
|
db->cur_file[0] = fd;
|
||||||
|
db->cur_file_sec[0] = sec_addr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int open_db_file(fdb_db_t db, uint32_t addr, bool clean)
|
||||||
|
{
|
||||||
|
uint32_t sec_addr = FDB_ALIGN_DOWN(addr, db->sec_size);
|
||||||
|
int fd = get_file_from_cache(db, sec_addr);
|
||||||
|
char path[DB_PATH_MAX];
|
||||||
|
|
||||||
|
if (fd <= 0 || clean) {
|
||||||
|
get_db_file_path(db, addr, path, DB_PATH_MAX);
|
||||||
|
|
||||||
|
if (fd > 0) {
|
||||||
|
close(fd);
|
||||||
|
fd = -1;
|
||||||
|
update_file_cache(db, sec_addr, fd);
|
||||||
|
}
|
||||||
|
if (clean) {
|
||||||
|
/* clean the old file */
|
||||||
|
int clean_fd = open(path, O_RDWR | O_CREAT | O_TRUNC, 0777);
|
||||||
|
if (clean_fd <= 0) {
|
||||||
|
FDB_INFO("Error: open (%s) file failed.\n", path);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
close(clean_fd);
|
||||||
|
clean_fd = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (get_file_from_cache(db, sec_addr) < 0) {
|
||||||
|
/* open the database file */
|
||||||
|
fd = open(path, O_RDWR, 0777);
|
||||||
|
update_file_cache(db, sec_addr, fd);
|
||||||
|
}
|
||||||
|
db->cur_sec = sec_addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
fdb_err_t _fdb_file_read(fdb_db_t db, uint32_t addr, void *buf, size_t size)
|
||||||
|
{
|
||||||
|
fdb_err_t result = FDB_NO_ERR;
|
||||||
|
int fd = open_db_file(db, addr, false);
|
||||||
|
if (fd > 0) {
|
||||||
|
/* get the offset address is relative to the start of the current file */
|
||||||
|
addr = addr % db->sec_size;
|
||||||
|
|
||||||
|
if ((lseek(fd, addr, SEEK_SET) != (int32_t)addr) || (read(fd, buf, size) != (ssize_t)size))
|
||||||
|
result = FDB_READ_ERR;
|
||||||
|
} else {
|
||||||
|
result = FDB_READ_ERR;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
fdb_err_t _fdb_file_write(fdb_db_t db, uint32_t addr, const void *buf, size_t size, bool sync)
|
||||||
|
{
|
||||||
|
fdb_err_t result = FDB_NO_ERR;
|
||||||
|
int fd = open_db_file(db, addr, false);
|
||||||
|
if (fd > 0) {
|
||||||
|
/* get the offset address is relative to the start of the current file */
|
||||||
|
addr = addr % db->sec_size;
|
||||||
|
|
||||||
|
if ((lseek(fd, addr, SEEK_SET) != (int32_t)addr) || (write(fd, buf, size) != (ssize_t)size))
|
||||||
|
result = FDB_WRITE_ERR;
|
||||||
|
if(sync) {
|
||||||
|
fsync(fd);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
result = FDB_WRITE_ERR;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
fdb_err_t _fdb_file_erase(fdb_db_t db, uint32_t addr, size_t size)
|
||||||
|
{
|
||||||
|
fdb_err_t result = FDB_NO_ERR;
|
||||||
|
int fd = open_db_file(db, addr, true);
|
||||||
|
if (fd > 0) {
|
||||||
|
#define BUF_SIZE 32
|
||||||
|
uint8_t buf[BUF_SIZE];
|
||||||
|
size_t i;
|
||||||
|
lseek(fd, 0, SEEK_SET);
|
||||||
|
for (i = 0; i * BUF_SIZE < size; i++)
|
||||||
|
{
|
||||||
|
memset(buf, 0xFF, BUF_SIZE);
|
||||||
|
write(fd, buf, BUF_SIZE);
|
||||||
|
}
|
||||||
|
memset(buf, 0xFF, BUF_SIZE);
|
||||||
|
write(fd, buf, size - i * BUF_SIZE);
|
||||||
|
fsync(fd);
|
||||||
|
} else {
|
||||||
|
result = FDB_ERASE_ERR;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
#elif defined(FDB_USING_FILE_LIBC_MODE)
|
||||||
|
|
||||||
|
static FILE *get_file_from_cache(fdb_db_t db, uint32_t sec_addr)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < FDB_FILE_CACHE_TABLE_SIZE; i++) {
|
||||||
|
if (db->cur_file_sec[i] == sec_addr)
|
||||||
|
return db->cur_file[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void update_file_cache(fdb_db_t db, uint32_t sec_addr, FILE *fd)
|
||||||
|
{
|
||||||
|
int free_index = FDB_FILE_CACHE_TABLE_SIZE;
|
||||||
|
|
||||||
|
for (int i = 0; i < FDB_FILE_CACHE_TABLE_SIZE; i++) {
|
||||||
|
if (db->cur_file_sec[i] == sec_addr) {
|
||||||
|
db->cur_file[i] = fd;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if (db->cur_file[i] == 0) {
|
||||||
|
free_index = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fd) {
|
||||||
|
if (free_index < FDB_FILE_CACHE_TABLE_SIZE) {
|
||||||
|
db->cur_file[free_index] = fd;
|
||||||
|
db->cur_file_sec[free_index] = sec_addr;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* cache is full, move to end */
|
||||||
|
for (int i = FDB_FILE_CACHE_TABLE_SIZE - 1; i > 0; i--) {
|
||||||
|
fclose(db->cur_file[i]);
|
||||||
|
memcpy(&db->cur_file[i], &db->cur_file[i - 1], sizeof(db->cur_file[0]));
|
||||||
|
memcpy(&db->cur_file_sec[i], &db->cur_file_sec[i - 1], sizeof(db->cur_file_sec[0]));
|
||||||
|
}
|
||||||
|
/* add to head */
|
||||||
|
db->cur_file[0] = fd;
|
||||||
|
db->cur_file_sec[0] = sec_addr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static FILE *open_db_file(fdb_db_t db, uint32_t addr, bool clean)
|
||||||
|
{
|
||||||
|
uint32_t sec_addr = FDB_ALIGN_DOWN(addr, db->sec_size);
|
||||||
|
FILE *fd = get_file_from_cache(db, sec_addr);
|
||||||
|
char path[DB_PATH_MAX];
|
||||||
|
|
||||||
|
if (fd == NULL || clean) {
|
||||||
|
get_db_file_path(db, addr, path, DB_PATH_MAX);
|
||||||
|
|
||||||
|
if (fd) {
|
||||||
|
fclose(fd);
|
||||||
|
fd = NULL;
|
||||||
|
update_file_cache(db, sec_addr, fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (clean) {
|
||||||
|
/* clean the old file */
|
||||||
|
FILE *clean_fd = fopen(path, "wb+");
|
||||||
|
if (clean_fd == NULL) {
|
||||||
|
FDB_INFO("Error: open (%s) file failed.\n", path);
|
||||||
|
} else {
|
||||||
|
fclose(clean_fd);
|
||||||
|
clean_fd = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (get_file_from_cache(db, sec_addr) == NULL) {
|
||||||
|
/* open the database file */
|
||||||
|
fd = fopen(path, "rb+");
|
||||||
|
update_file_cache(db, sec_addr, fd);
|
||||||
|
}
|
||||||
|
db->cur_sec = sec_addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
fdb_err_t _fdb_file_read(fdb_db_t db, uint32_t addr, void *buf, size_t size)
|
||||||
|
{
|
||||||
|
fdb_err_t result = FDB_NO_ERR;
|
||||||
|
FILE *fp = open_db_file(db, addr, false);
|
||||||
|
if (fp) {
|
||||||
|
addr = addr % db->sec_size;
|
||||||
|
if ((fseek(fp, addr, SEEK_SET) != 0) || (fread(buf, size, 1, fp) != size))
|
||||||
|
result = FDB_READ_ERR;
|
||||||
|
} else {
|
||||||
|
result = FDB_READ_ERR;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
fdb_err_t _fdb_file_write(fdb_db_t db, uint32_t addr, const void *buf, size_t size, bool sync)
|
||||||
|
{
|
||||||
|
fdb_err_t result = FDB_NO_ERR;
|
||||||
|
FILE *fp = open_db_file(db, addr, false);
|
||||||
|
if (fp) {
|
||||||
|
addr = addr % db->sec_size;
|
||||||
|
if ((fseek(fp, addr, SEEK_SET) != 0) || (fwrite(buf, size, 1, fp) != size))
|
||||||
|
result = FDB_READ_ERR;
|
||||||
|
if(sync) {
|
||||||
|
fflush(fp);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
result = FDB_READ_ERR;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
fdb_err_t _fdb_file_erase(fdb_db_t db, uint32_t addr, size_t size)
|
||||||
|
{
|
||||||
|
fdb_err_t result = FDB_NO_ERR;
|
||||||
|
|
||||||
|
FILE *fp = open_db_file(db, addr, true);
|
||||||
|
if (fp != NULL) {
|
||||||
|
#define BUF_SIZE 32
|
||||||
|
uint8_t buf[BUF_SIZE];
|
||||||
|
size_t i;
|
||||||
|
fseek(fp, 0, SEEK_SET);
|
||||||
|
for (i = 0; i * BUF_SIZE < size; i++)
|
||||||
|
{
|
||||||
|
memset(buf, 0xFF, BUF_SIZE);
|
||||||
|
fwrite(buf, BUF_SIZE, 1, fp);
|
||||||
|
}
|
||||||
|
memset(buf, 0xFF, BUF_SIZE);
|
||||||
|
fwrite(buf, size - i * BUF_SIZE, 1, fp);
|
||||||
|
fflush(fp);
|
||||||
|
} else {
|
||||||
|
result = FDB_ERASE_ERR;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
#endif /* defined(FDB_USING_FILE_LIBC_MODE) */
|
||||||
|
|
||||||
|
#endif /* FDB_USING_FILE_MODE */
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,69 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2020, Armink, <armink.ztl@gmail.com>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* @brief low level API and definition
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _FDB_LOW_LVL_H_
|
||||||
|
#define _FDB_LOW_LVL_H_
|
||||||
|
|
||||||
|
#include <fdb_cfg.h>
|
||||||
|
#include <fdb_def.h>
|
||||||
|
|
||||||
|
#if (FDB_WRITE_GRAN == 1)
|
||||||
|
#define FDB_STATUS_TABLE_SIZE(status_number) ((status_number * FDB_WRITE_GRAN + 7)/8)
|
||||||
|
#else
|
||||||
|
#define FDB_STATUS_TABLE_SIZE(status_number) (((status_number - 1) * FDB_WRITE_GRAN + 7)/8)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* the data is erased */
|
||||||
|
#define FDB_BYTE_ERASED 0xFF
|
||||||
|
/* the data is written */
|
||||||
|
#define FDB_BYTE_WRITTEN 0x00
|
||||||
|
|
||||||
|
/* Return the most contiguous size aligned at specified width. RT_ALIGN(13, 4)
|
||||||
|
* would return 16.
|
||||||
|
*/
|
||||||
|
#define FDB_ALIGN(size, align) (((size) + (align) - 1) - (((size) + (align) -1) % (align)))
|
||||||
|
/* align by write granularity */
|
||||||
|
#define FDB_WG_ALIGN(size) (FDB_ALIGN(size, ((FDB_WRITE_GRAN + 7)/8)))
|
||||||
|
/**
|
||||||
|
* Return the down number of aligned at specified width. RT_ALIGN_DOWN(13, 4)
|
||||||
|
* would return 12.
|
||||||
|
*/
|
||||||
|
#define FDB_ALIGN_DOWN(size, align) (((size) / (align)) * (align))
|
||||||
|
/* align down by write granularity */
|
||||||
|
#define FDB_WG_ALIGN_DOWN(size) (FDB_ALIGN_DOWN(size, (FDB_WRITE_GRAN + 7)/8))
|
||||||
|
|
||||||
|
#define FDB_STORE_STATUS_TABLE_SIZE FDB_STATUS_TABLE_SIZE(FDB_SECTOR_STORE_STATUS_NUM)
|
||||||
|
#define FDB_DIRTY_STATUS_TABLE_SIZE FDB_STATUS_TABLE_SIZE(FDB_SECTOR_DIRTY_STATUS_NUM)
|
||||||
|
|
||||||
|
/* the data is unused */
|
||||||
|
#if (FDB_BYTE_ERASED == 0xFF)
|
||||||
|
#define FDB_DATA_UNUSED 0xFFFFFFFF
|
||||||
|
#else
|
||||||
|
#define FDB_DATA_UNUSED 0x00000000
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* invalid address */
|
||||||
|
#define FDB_FAILED_ADDR 0xFFFFFFFF
|
||||||
|
|
||||||
|
size_t _fdb_set_status(uint8_t status_table[], size_t status_num, size_t status_index);
|
||||||
|
size_t _fdb_get_status(uint8_t status_table[], size_t status_num);
|
||||||
|
uint32_t _fdb_continue_ff_addr(fdb_db_t db, uint32_t start, uint32_t end);
|
||||||
|
fdb_err_t _fdb_init_ex(fdb_db_t db, const char *name, const char *part_name, fdb_db_type type, void *user_data);
|
||||||
|
void _fdb_init_finish(fdb_db_t db, fdb_err_t result);
|
||||||
|
void _fdb_deinit(fdb_db_t db);
|
||||||
|
const char *_fdb_db_path(fdb_db_t db);
|
||||||
|
fdb_err_t _fdb_write_status(fdb_db_t db, uint32_t addr, uint8_t status_table[], size_t status_num, size_t status_index, bool sync);
|
||||||
|
size_t _fdb_read_status(fdb_db_t db, uint32_t addr, uint8_t status_table[], size_t total_num);
|
||||||
|
fdb_err_t _fdb_flash_read(fdb_db_t db, uint32_t addr, void *buf, size_t size);
|
||||||
|
fdb_err_t _fdb_flash_erase(fdb_db_t db, uint32_t addr, size_t size);
|
||||||
|
fdb_err_t _fdb_flash_write(fdb_db_t db, uint32_t addr, const void *buf, size_t size, bool sync);
|
||||||
|
|
||||||
|
#endif /* _FDB_LOW_LVL_H_ */
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,320 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2020, Armink, <armink.ztl@gmail.com>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* @brief utils
|
||||||
|
*
|
||||||
|
* Some utils for this library.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <flashdb.h>
|
||||||
|
#include <fdb_low_lvl.h>
|
||||||
|
|
||||||
|
#define FDB_LOG_TAG "[utils]"
|
||||||
|
|
||||||
|
static const uint32_t crc32_table[] =
|
||||||
|
{
|
||||||
|
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
|
||||||
|
0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
|
||||||
|
0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
|
||||||
|
0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
|
||||||
|
0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
|
||||||
|
0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
|
||||||
|
0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
|
||||||
|
0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
|
||||||
|
0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
|
||||||
|
0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
|
||||||
|
0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
|
||||||
|
0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
|
||||||
|
0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
|
||||||
|
0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
|
||||||
|
0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
|
||||||
|
0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
|
||||||
|
0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
|
||||||
|
0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
|
||||||
|
0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
|
||||||
|
0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
|
||||||
|
0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
|
||||||
|
0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
|
||||||
|
0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
|
||||||
|
0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
|
||||||
|
0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
|
||||||
|
0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
|
||||||
|
0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
|
||||||
|
0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
|
||||||
|
0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
|
||||||
|
0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
|
||||||
|
0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
|
||||||
|
0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
|
||||||
|
0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
|
||||||
|
0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
|
||||||
|
0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
|
||||||
|
0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
|
||||||
|
0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
|
||||||
|
0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
|
||||||
|
0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
|
||||||
|
0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
|
||||||
|
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
|
||||||
|
0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
|
||||||
|
0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculate the CRC32 value of a memory buffer.
|
||||||
|
*
|
||||||
|
* @param crc accumulated CRC32 value, must be 0 on first call
|
||||||
|
* @param buf buffer to calculate CRC32 value for
|
||||||
|
* @param size bytes in buffer
|
||||||
|
*
|
||||||
|
* @return calculated CRC32 value
|
||||||
|
*/
|
||||||
|
uint32_t fdb_calc_crc32(uint32_t crc, const void *buf, size_t size)
|
||||||
|
{
|
||||||
|
const uint8_t *p;
|
||||||
|
|
||||||
|
p = (const uint8_t *)buf;
|
||||||
|
crc = crc ^ ~0U;
|
||||||
|
|
||||||
|
while (size--) {
|
||||||
|
crc = crc32_table[(crc ^ *p++) & 0xFF] ^ (crc >> 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
return crc ^ ~0U;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t _fdb_set_status(uint8_t status_table[], size_t status_num, size_t status_index)
|
||||||
|
{
|
||||||
|
size_t byte_index = SIZE_MAX;
|
||||||
|
/*
|
||||||
|
* | write garn | status0 | status1 | status2 | status3 |
|
||||||
|
* ------------------------------------------------------------------------------------------------------
|
||||||
|
* | 1bit | 0xFF | 0x7F | 0x3F | 0x1F
|
||||||
|
* ------------------------------------------------------------------------------------------------------
|
||||||
|
* | 8bit | 0xFF FF FF | 0x00 FF FF | 0x00 00 FF | 0x00 00 00
|
||||||
|
* ------------------------------------------------------------------------------------------------------
|
||||||
|
* | 32bit | 0xFFFFFFFF FFFFFFFF | 0x00FFFFFF FFFFFFFF | 0x00FFFFFF 00FFFFFF | 0x00FFFFFF 00FFFFFF
|
||||||
|
* | | 0xFFFFFFFF | 0xFFFFFFFF | 0xFFFFFFFF | 0x00FFFFFF
|
||||||
|
* ------------------------------------------------------------------------------------------------------
|
||||||
|
* | | 0xFFFFFFFF FFFFFFFF | 0x00FFFFFF FFFFFFFF | 0x00FFFFFF FFFFFFFF | 0x00FFFFFF FFFFFFFF
|
||||||
|
* | 64bit | 0xFFFFFFFF FFFFFFFF | 0xFFFFFFFF FFFFFFFF | 0x00FFFFFF FFFFFFFF | 0x00FFFFFF FFFFFFFF
|
||||||
|
* | | 0xFFFFFFFF FFFFFFFF | 0xFFFFFFFF FFFFFFFF | 0xFFFFFFFF FFFFFFFF | 0x00FFFFFF FFFFFFFF
|
||||||
|
*/
|
||||||
|
memset(status_table, FDB_BYTE_ERASED, FDB_STATUS_TABLE_SIZE(status_num));
|
||||||
|
if (status_index > 0) {
|
||||||
|
#if (FDB_WRITE_GRAN == 1)
|
||||||
|
byte_index = (status_index - 1) / 8;
|
||||||
|
#if (FDB_BYTE_ERASED == 0xFF)
|
||||||
|
status_table[byte_index] &= (0x00ff >> (status_index % 8));
|
||||||
|
#else
|
||||||
|
status_table[byte_index] |= (0x00ff >> (status_index % 8));
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
byte_index = (status_index - 1) * (FDB_WRITE_GRAN / 8);
|
||||||
|
status_table[byte_index] = FDB_BYTE_WRITTEN;
|
||||||
|
#endif /* FDB_WRITE_GRAN == 1 */
|
||||||
|
}
|
||||||
|
|
||||||
|
return byte_index;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t _fdb_get_status(uint8_t status_table[], size_t status_num)
|
||||||
|
{
|
||||||
|
size_t i = 0, status_num_bak = --status_num;
|
||||||
|
|
||||||
|
while (status_num --) {
|
||||||
|
/* get the first 0 position from end address to start address */
|
||||||
|
#if (FDB_WRITE_GRAN == 1)
|
||||||
|
if ((status_table[status_num / 8] & (0x80 >> (status_num % 8))) == 0x00) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#else /* (FDB_WRITE_GRAN == 8) || (FDB_WRITE_GRAN == 32) || (FDB_WRITE_GRAN == 64) */
|
||||||
|
if (status_table[status_num * FDB_WRITE_GRAN / 8] == FDB_BYTE_WRITTEN) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#endif /* FDB_WRITE_GRAN == 1 */
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return status_num_bak - i;
|
||||||
|
}
|
||||||
|
|
||||||
|
fdb_err_t _fdb_write_status(fdb_db_t db, uint32_t addr, uint8_t status_table[], size_t status_num, size_t status_index, bool sync)
|
||||||
|
{
|
||||||
|
fdb_err_t result = FDB_NO_ERR;
|
||||||
|
size_t byte_index;
|
||||||
|
|
||||||
|
FDB_ASSERT(status_index < status_num);
|
||||||
|
FDB_ASSERT(status_table);
|
||||||
|
|
||||||
|
/* set the status first */
|
||||||
|
byte_index = _fdb_set_status(status_table, status_num, status_index);
|
||||||
|
|
||||||
|
/* the first status table value is all 1, so no need to write flash */
|
||||||
|
if (byte_index == SIZE_MAX) {
|
||||||
|
return FDB_NO_ERR;
|
||||||
|
}
|
||||||
|
#if (FDB_WRITE_GRAN == 1)
|
||||||
|
result = _fdb_flash_write(db, addr + byte_index, (uint32_t *)&status_table[byte_index], 1, sync);
|
||||||
|
#else /* (FDB_WRITE_GRAN == 8) || (FDB_WRITE_GRAN == 32) || (FDB_WRITE_GRAN == 64) */
|
||||||
|
/* write the status by write granularity
|
||||||
|
* some flash (like stm32 onchip) NOT supported repeated write before erase */
|
||||||
|
result = _fdb_flash_write(db, addr + byte_index, (uint32_t *) &status_table[byte_index], FDB_WRITE_GRAN / 8, sync);
|
||||||
|
#endif /* FDB_WRITE_GRAN == 1 */
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t _fdb_read_status(fdb_db_t db, uint32_t addr, uint8_t status_table[], size_t total_num)
|
||||||
|
{
|
||||||
|
FDB_ASSERT(status_table);
|
||||||
|
|
||||||
|
_fdb_flash_read(db, addr, (uint32_t *) status_table, FDB_STATUS_TABLE_SIZE(total_num));
|
||||||
|
|
||||||
|
return _fdb_get_status(status_table, total_num);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* find the continue 0xFF flash address to end address
|
||||||
|
*/
|
||||||
|
uint32_t _fdb_continue_ff_addr(fdb_db_t db, uint32_t start, uint32_t end)
|
||||||
|
{
|
||||||
|
uint8_t buf[32], last_data = FDB_BYTE_WRITTEN;
|
||||||
|
size_t i, addr = start, read_size;
|
||||||
|
|
||||||
|
for (; start < end; start += sizeof(buf)) {
|
||||||
|
if (start + sizeof(buf) < end) {
|
||||||
|
read_size = sizeof(buf);
|
||||||
|
} else {
|
||||||
|
read_size = end - start;
|
||||||
|
}
|
||||||
|
_fdb_flash_read(db, start, (uint32_t *) buf, read_size);
|
||||||
|
for (i = 0; i < read_size; i++) {
|
||||||
|
if (last_data != FDB_BYTE_ERASED && buf[i] == FDB_BYTE_ERASED) {
|
||||||
|
addr = start + i;
|
||||||
|
}
|
||||||
|
last_data = buf[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (last_data == FDB_BYTE_ERASED) {
|
||||||
|
return FDB_WG_ALIGN(addr);
|
||||||
|
} else {
|
||||||
|
return end;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Make a blob object.
|
||||||
|
*
|
||||||
|
* @param blob blob object
|
||||||
|
* @param value_buf value buffer
|
||||||
|
* @param buf_len buffer length
|
||||||
|
*
|
||||||
|
* @return new blob object
|
||||||
|
*/
|
||||||
|
fdb_blob_t fdb_blob_make(fdb_blob_t blob, const void *value_buf, size_t buf_len)
|
||||||
|
{
|
||||||
|
blob->buf = (void *)value_buf;
|
||||||
|
blob->size = buf_len;
|
||||||
|
|
||||||
|
return blob;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read the blob object in database.
|
||||||
|
*
|
||||||
|
* @param db database object
|
||||||
|
* @param blob blob object
|
||||||
|
*
|
||||||
|
* @return read length
|
||||||
|
*/
|
||||||
|
size_t fdb_blob_read(fdb_db_t db, fdb_blob_t blob)
|
||||||
|
{
|
||||||
|
size_t read_len = blob->size;
|
||||||
|
|
||||||
|
if (read_len > blob->saved.len) {
|
||||||
|
read_len = blob->saved.len;
|
||||||
|
}
|
||||||
|
if (_fdb_flash_read(db, blob->saved.addr, blob->buf, read_len) != FDB_NO_ERR) {
|
||||||
|
read_len = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return read_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef FDB_USING_FILE_MODE
|
||||||
|
extern fdb_err_t _fdb_file_read(fdb_db_t db, uint32_t addr, void *buf, size_t size);
|
||||||
|
extern fdb_err_t _fdb_file_write(fdb_db_t db, uint32_t addr, const void *buf, size_t size, bool sync);
|
||||||
|
extern fdb_err_t _fdb_file_erase(fdb_db_t db, uint32_t addr, size_t size);
|
||||||
|
#endif /* FDB_USING_FILE_LIBC */
|
||||||
|
|
||||||
|
fdb_err_t _fdb_flash_read(fdb_db_t db, uint32_t addr, void *buf, size_t size)
|
||||||
|
{
|
||||||
|
fdb_err_t result = FDB_NO_ERR;
|
||||||
|
|
||||||
|
if (db->file_mode) {
|
||||||
|
#ifdef FDB_USING_FILE_MODE
|
||||||
|
return _fdb_file_read(db, addr, buf, size);
|
||||||
|
#else
|
||||||
|
return FDB_READ_ERR;
|
||||||
|
#endif
|
||||||
|
} else {
|
||||||
|
#ifdef FDB_USING_FAL_MODE
|
||||||
|
if (fal_partition_read(db->storage.part, addr, (uint8_t *) buf, size) < 0) {
|
||||||
|
result = FDB_READ_ERR;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
fdb_err_t _fdb_flash_erase(fdb_db_t db, uint32_t addr, size_t size)
|
||||||
|
{
|
||||||
|
fdb_err_t result = FDB_NO_ERR;
|
||||||
|
|
||||||
|
if (db->file_mode) {
|
||||||
|
#ifdef FDB_USING_FILE_MODE
|
||||||
|
return _fdb_file_erase(db, addr, size);
|
||||||
|
#else
|
||||||
|
return FDB_ERASE_ERR;
|
||||||
|
#endif /* FDB_USING_FILE_MODE */
|
||||||
|
} else {
|
||||||
|
#ifdef FDB_USING_FAL_MODE
|
||||||
|
if (fal_partition_erase(db->storage.part, addr, size) < 0) {
|
||||||
|
result = FDB_ERASE_ERR;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
fdb_err_t _fdb_flash_write(fdb_db_t db, uint32_t addr, const void *buf, size_t size, bool sync)
|
||||||
|
{
|
||||||
|
fdb_err_t result = FDB_NO_ERR;
|
||||||
|
|
||||||
|
if (db->file_mode) {
|
||||||
|
#ifdef FDB_USING_FILE_MODE
|
||||||
|
return _fdb_file_write(db, addr, buf, size, sync);
|
||||||
|
#else
|
||||||
|
return FDB_WRITE_ERR;
|
||||||
|
#endif /* FDB_USING_FILE_MODE */
|
||||||
|
} else {
|
||||||
|
#ifdef FDB_USING_FAL_MODE
|
||||||
|
if (fal_partition_write(db->storage.part, addr, (uint8_t *)buf, size) < 0)
|
||||||
|
{
|
||||||
|
result = FDB_WRITE_ERR;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,79 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2020, Armink, <armink.ztl@gmail.com>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* @brief Public APIs.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _FLASHDB_H_
|
||||||
|
#define _FLASHDB_H_
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <fdb_cfg.h>
|
||||||
|
|
||||||
|
#ifdef FDB_USING_FAL_MODE
|
||||||
|
#include <fal.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <fdb_def.h>
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* FlashDB database API */
|
||||||
|
fdb_err_t fdb_kvdb_init (fdb_kvdb_t db, const char *name, const char *path, struct fdb_default_kv *default_kv,
|
||||||
|
void *user_data);
|
||||||
|
void fdb_kvdb_control(fdb_kvdb_t db, int cmd, void *arg);
|
||||||
|
fdb_err_t fdb_kvdb_check(fdb_kvdb_t db);
|
||||||
|
fdb_err_t fdb_kvdb_deinit(fdb_kvdb_t db);
|
||||||
|
fdb_err_t fdb_tsdb_init (fdb_tsdb_t db, const char *name, const char *path, fdb_get_time get_time, size_t max_len,
|
||||||
|
void *user_data);
|
||||||
|
void fdb_tsdb_control(fdb_tsdb_t db, int cmd, void *arg);
|
||||||
|
fdb_err_t fdb_tsdb_deinit(fdb_tsdb_t db);
|
||||||
|
|
||||||
|
/* blob API */
|
||||||
|
fdb_blob_t fdb_blob_make (fdb_blob_t blob, const void *value_buf, size_t buf_len);
|
||||||
|
size_t fdb_blob_read (fdb_db_t db, fdb_blob_t blob);
|
||||||
|
|
||||||
|
/* Key-Value API like a KV DB */
|
||||||
|
fdb_err_t fdb_kv_set (fdb_kvdb_t db, const char *key, const char *value);
|
||||||
|
char *fdb_kv_get (fdb_kvdb_t db, const char *key);
|
||||||
|
fdb_err_t fdb_kv_set_blob (fdb_kvdb_t db, const char *key, fdb_blob_t blob);
|
||||||
|
size_t fdb_kv_get_blob (fdb_kvdb_t db, const char *key, fdb_blob_t blob);
|
||||||
|
fdb_err_t fdb_kv_del (fdb_kvdb_t db, const char *key);
|
||||||
|
fdb_kv_t fdb_kv_get_obj (fdb_kvdb_t db, const char *key, fdb_kv_t kv);
|
||||||
|
fdb_blob_t fdb_kv_to_blob (fdb_kv_t kv, fdb_blob_t blob);
|
||||||
|
fdb_err_t fdb_kv_set_default (fdb_kvdb_t db);
|
||||||
|
void fdb_kv_print (fdb_kvdb_t db);
|
||||||
|
fdb_kv_iterator_t fdb_kv_iterator_init(fdb_kvdb_t db, fdb_kv_iterator_t itr);
|
||||||
|
bool fdb_kv_iterate (fdb_kvdb_t db, fdb_kv_iterator_t itr);
|
||||||
|
|
||||||
|
/* Time series log API like a TSDB */
|
||||||
|
fdb_err_t fdb_tsl_append (fdb_tsdb_t db, fdb_blob_t blob);
|
||||||
|
fdb_err_t fdb_tsl_append_with_ts(fdb_tsdb_t db, fdb_blob_t blob, fdb_time_t timestamp);
|
||||||
|
void fdb_tsl_iter (fdb_tsdb_t db, fdb_tsl_cb cb, void *cb_arg);
|
||||||
|
void fdb_tsl_iter_reverse(fdb_tsdb_t db, fdb_tsl_cb cb, void *cb_arg);
|
||||||
|
void fdb_tsl_iter_by_time(fdb_tsdb_t db, fdb_time_t from, fdb_time_t to, fdb_tsl_cb cb, void *cb_arg);
|
||||||
|
size_t fdb_tsl_query_count (fdb_tsdb_t db, fdb_time_t from, fdb_time_t to, fdb_tsl_status_t status);
|
||||||
|
fdb_err_t fdb_tsl_set_status (fdb_tsdb_t db, fdb_tsl_t tsl, fdb_tsl_status_t status);
|
||||||
|
void fdb_tsl_clean (fdb_tsdb_t db);
|
||||||
|
fdb_blob_t fdb_tsl_to_blob (fdb_tsl_t tsl, fdb_blob_t blob);
|
||||||
|
|
||||||
|
/* fdb_utils.c */
|
||||||
|
uint32_t fdb_calc_crc32(uint32_t crc, const void *buf, size_t size);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* _FLASHDB_H_ */
|
|
@ -0,0 +1,38 @@
|
||||||
|
# 移植说明
|
||||||
|
|
||||||
|
## 简介
|
||||||
|
|
||||||
|
[FlashDB](http://armink.gitee.io/flashdb/#/zh-cn/) 是一款超轻量级的嵌入式数据库,专注于提供嵌入式产品的数据存储方案。FlashDB 不仅支持传统的基于文件系统的数据库模式,而且结合了 Flash 的特性,具有较强的性能及可靠性。并在保证极低的资源占用前提下,尽可能延长 Flash 使用寿命。
|
||||||
|
|
||||||
|
|
||||||
|
## 使用场景
|
||||||
|
|
||||||
|
如今,物联网产品种类越来越多,运行时产生的数据种类及总量及也在不断变大。FlashDB 提供了多样化的数据存储方案,不仅资源占用小,并且存储容量大,非常适合用于物联网产品。下面是主要应用场景:
|
||||||
|
|
||||||
|
* **键值数据库** :
|
||||||
|
* 产品参数存储
|
||||||
|
* 用户配置信息存储
|
||||||
|
* 小文件管理
|
||||||
|
* **时序数据库** :
|
||||||
|
* 存储动态产生的结构化数据:如 温湿度传感器采集的环境监测信息,智能手环实时记录的人体健康信息等
|
||||||
|
* 记录运行日志:存储产品历史的运行日志,异常告警的记录等
|
||||||
|
|
||||||
|
本项目使用3块EPPROM
|
||||||
|
|
||||||
|
|
||||||
|
## 文件移植
|
||||||
|
|
||||||
|
项目地址 https://github.com/armink/FlashDB
|
||||||
|
|
||||||
|
引入目录中的文件
|
||||||
|
|
||||||
|
.\FlashDB\src
|
||||||
|
|
||||||
|
.\FlashDB\inc
|
||||||
|
|
||||||
|
.\FlashDB\port\fal\src
|
||||||
|
|
||||||
|
.\FlashDB\port\fal\inc
|
||||||
|
|
||||||
|
|
||||||
|
> fal_cfg.h 这个文件为用户自定义升级的时候不要覆盖
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue