├── ramdump-software
├── qn9022-ramdump
│ ├── update-loader.bat
│ ├── qn9022-ramdump.vcxproj.user
│ ├── qn9022-ramdump.vcxproj.filters
│ ├── crc16-ccitt-algorithm.h
│ ├── qn9022-ramdump.vcxproj
│ └── ramdump.c
└── qn9022-ramdump.sln
├── README.md
└── ramdump-firmware
├── link.ld
├── Makefile
├── launcher.S
├── main.c
└── cmsis
├── core_cm0.c
├── core_cmFunc.h
├── core_cmInstr.h
└── core_cm0.h
/ramdump-software/qn9022-ramdump/update-loader.bat:
--------------------------------------------------------------------------------
1 | del loader.bin
2 | copy .\..\..\ramdump-firmware\loader.bin .
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # qn902x-dump - dumping QN902x firmware despite of protection
2 |
3 | PoC of https://habr.com/ru/post/663312/
--------------------------------------------------------------------------------
/ramdump-firmware/link.ld:
--------------------------------------------------------------------------------
1 | _estack = 0x10002000;
2 |
3 | MEMORY
4 | {
5 | RAM ( rxw ) : ORIGIN = 0x10000000, LENGTH = 8K
6 | }
7 |
8 |
--------------------------------------------------------------------------------
/ramdump-software/qn9022-ramdump/qn9022-ramdump.vcxproj.user:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | COM7
5 | WindowsLocalDebugger
6 |
7 |
8 | COM7
9 | WindowsLocalDebugger
10 |
11 |
--------------------------------------------------------------------------------
/ramdump-firmware/Makefile:
--------------------------------------------------------------------------------
1 | .PHONY: all clean disasm
2 |
3 | all: loader.bin
4 |
5 | launcher.o: launcher.S
6 | arm-none-eabi-gcc -c -O0 -mcpu=cortex-m0 -mthumb -Wall launcher.S -o launcher.o
7 |
8 | main.o: main.c
9 | arm-none-eabi-gcc -mlittle-endian -mthumb -mcpu=cortex-m0 -nostdlib -O0 -Wall -Icmsis -c main.c -o main.o
10 |
11 | loader.elf: main.o launcher.o link.ld
12 | arm-none-eabi-gcc launcher.o main.o -mcpu=cortex-m0 -mthumb -Wall --specs=nosys.specs -nostdlib -lgcc -T./link.ld -o loader.elf
13 |
14 | loader.bin: loader.elf
15 | arm-none-eabi-objcopy -O binary loader.elf loader.bin
16 |
17 | disasm: loader.bin
18 | arm-none-eabi-objdump loader.bin -D -b binary -m arm -Mforce-thumb
19 | arm-none-eabi-objdump -d loader.elf -Mforce-thumb -l
20 |
21 | clean:
22 | rm -f launcher.o main.o loader.elf loader.bin
23 |
--------------------------------------------------------------------------------
/ramdump-software/qn9022-ramdump.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 16
4 | VisualStudioVersion = 16.0.31205.134
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "qn9022-ramdump", "qn9022-ramdump\qn9022-ramdump.vcxproj", "{D729D386-D6BB-4056-997A-B364D5FDCC4E}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|x86 = Debug|x86
11 | Release|x86 = Release|x86
12 | EndGlobalSection
13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
14 | {D729D386-D6BB-4056-997A-B364D5FDCC4E}.Debug|x86.ActiveCfg = Debug|Win32
15 | {D729D386-D6BB-4056-997A-B364D5FDCC4E}.Debug|x86.Build.0 = Debug|Win32
16 | {D729D386-D6BB-4056-997A-B364D5FDCC4E}.Release|x86.ActiveCfg = Release|Win32
17 | {D729D386-D6BB-4056-997A-B364D5FDCC4E}.Release|x86.Build.0 = Release|Win32
18 | EndGlobalSection
19 | GlobalSection(SolutionProperties) = preSolution
20 | HideSolutionNode = FALSE
21 | EndGlobalSection
22 | GlobalSection(ExtensibilityGlobals) = postSolution
23 | SolutionGuid = {78B64690-40D3-4186-BE34-1462D0A97B4F}
24 | EndGlobalSection
25 | EndGlobal
26 |
--------------------------------------------------------------------------------
/ramdump-software/qn9022-ramdump/qn9022-ramdump.vcxproj.filters:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
7 |
8 |
9 | {93995380-89BD-4b04-88EB-625FBE52EBFB}
10 | h;hh;hpp;hxx;hm;inl;inc;ipp;xsd
11 |
12 |
13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
15 |
16 |
17 |
18 |
19 | Source Files
20 |
21 |
22 |
23 |
24 | Header Files
25 |
26 |
27 |
--------------------------------------------------------------------------------
/ramdump-firmware/launcher.S:
--------------------------------------------------------------------------------
1 | .syntax unified
2 | .cpu cortex-m0
3 | .fpu softvfp
4 | .thumb
5 |
6 | .set SYS_MODE_REG, 0x40000080
7 | .set REMAP_BIT , 0x40000000
8 |
9 | .global vtable
10 | .global main
11 |
12 | .type vtable, %object
13 | vtable:
14 | .word _estack
15 | .word starter
16 | .size vtable, .-vtable
17 |
18 | starter:
19 | LDR R1, = SYS_MODE_REG
20 | LDR R0, [R1]
21 | LDR R2, = REMAP_BIT
22 | ORRS R0, R0, R2
23 | STR R0, [R1]
24 |
25 | LDR R0, = _estack
26 | MSR MSP, R0
27 |
28 | bl main
29 | inf:
30 | b inf
31 | nop
32 | bl starter
33 | bl starter
34 | bl starter
35 | bl starter
36 | bl starter
37 | bl starter
38 | bl starter
39 | bl starter
40 | bl starter
41 | bl starter
42 | bl starter
43 | bl starter
44 | bl starter
45 | bl starter
46 | bl starter
47 | bl starter
48 | bl starter
49 | bl starter
50 | bl starter
51 | bl starter
52 | bl starter
53 | bl starter
54 | bl starter
55 | bl starter
56 | bl starter
57 | bl starter
58 | bl starter
59 | bl starter
60 | bl starter
61 | bl starter
62 | bl starter
63 | bl starter
64 | bl starter
65 | bl starter
66 | bl starter
67 | bl starter
68 | bl starter
69 | bl starter
70 | bl starter
71 | bl starter
72 | bl starter
73 | bl starter
74 | bl starter
75 | bl starter
76 | bl starter
77 | bl starter
78 | bl starter
79 | bl starter
80 |
--------------------------------------------------------------------------------
/ramdump-software/qn9022-ramdump/crc16-ccitt-algorithm.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2014 Jonas Eriksson
3 | *
4 | * Permission is hereby granted, free of charge, to any person obtaining a copy
5 | * of this software and associated documentation files (the "Software"), to deal
6 | * in the Software without restriction, including without limitation the rights
7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | * copies of the Software, and to permit persons to whom the Software is
9 | * furnished to do so, subject to the following conditions:
10 | *
11 | * The above copyright notice and this permission notice shall be included in
12 | * all copies or substantial portions of the Software.
13 | *
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | * THE SOFTWARE.
21 | */
22 |
23 | #include
24 |
25 | static inline uint16_t crc16_ccitt_init(void)
26 | {
27 | return 0xFFFF;
28 | }
29 |
30 | static inline uint16_t crc16_ccitt_update(uint8_t byte, uint16_t crc)
31 | {
32 | int i;
33 | int xor_flag;
34 |
35 | /* For each bit in the data byte, starting from the leftmost bit */
36 | for (i = 7; i >= 0; i--)
37 | {
38 | /* If leftmost bit of the CRC is 1, we will XOR with
39 | * the polynomial later */
40 | xor_flag = crc & 0x8000;
41 |
42 | /* Shift the CRC, and append the next bit of the
43 | * message to the rightmost side of the CRC */
44 | crc <<= 1;
45 | crc |= (byte & (1 << i)) ? 1 : 0;
46 |
47 | /* Perform the XOR with the polynomial */
48 | if (xor_flag)
49 | crc ^= 0x1021;
50 | }
51 |
52 | return crc;
53 | }
54 |
55 | static inline uint16_t crc16_ccitt_finalize(uint16_t crc)
56 | {
57 | int i;
58 |
59 | /* Augment 16 zero-bits */
60 | for (i = 0; i < 2; i++)
61 | {
62 | crc = crc16_ccitt_update(0, crc);
63 | }
64 |
65 | return crc;
66 | }
67 |
--------------------------------------------------------------------------------
/ramdump-software/qn9022-ramdump/qn9022-ramdump.vcxproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | Win32
7 |
8 |
9 | Release
10 | Win32
11 |
12 |
13 |
14 | 15.0
15 | {D729D386-D6BB-4056-997A-B364D5FDCC4E}
16 | Win32Proj
17 | ramdump
18 | 10.0.17763.0
19 | qn9022-ramdump
20 |
21 |
22 |
23 | Application
24 | true
25 | v141
26 | Unicode
27 |
28 |
29 | Application
30 | false
31 | v141
32 | true
33 | Unicode
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 | true
49 |
50 |
51 | false
52 |
53 |
54 |
55 | Level3
56 | Disabled
57 | true
58 | _CRT_SECURE_NO_WARNINGS;USE_WINAPI_COM_PORT;FTD2XX_STATIC;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)
59 | true
60 | D:\libs\include
61 |
62 |
63 | Console
64 | true
65 | D:\libs\lib
66 | legacy_stdio_definitions.lib;ws2_32.lib;ftd2xx_static.lib;%(AdditionalDependencies)
67 |
68 |
69 |
70 |
71 | Level3
72 | MaxSpeed
73 | true
74 | true
75 | true
76 | _CRT_SECURE_NO_WARNINGS;USE_WINAPI_COM_PORT;FTD2XX_STATIC;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
77 | true
78 | D:\libs\include
79 |
80 |
81 | Console
82 | true
83 | true
84 | true
85 | D:\libs\lib
86 | legacy_stdio_definitions.lib;ws2_32.lib;ftd2xx_static.lib;%(AdditionalDependencies)
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
--------------------------------------------------------------------------------
/ramdump-firmware/main.c:
--------------------------------------------------------------------------------
1 | #include "QN9020.h"
2 | #include
3 |
4 | void setup_peripherials();
5 | void send_line(char *buffer);
6 | int get_line(char *buffer, int buffer_len);
7 | int parse_line(char *command, uint8_t *mode, uint32_t *address, uint32_t *data);
8 | void transmit_byte_as_ascii_space(uint8_t byte);
9 | void read_flash(uint32_t addr, uint32_t *pBuf, uint32_t nByte);
10 |
11 | int main (void)
12 | {
13 | setup_peripherials();
14 |
15 | char command[32];
16 | while(1)
17 | {
18 | if(!get_line(command, sizeof(command)))
19 | {
20 | continue;
21 | }
22 |
23 | uint8_t mode;//0 - read, 1 - write
24 | uint32_t address;//address
25 | uint32_t data;//count of bytes to read or data to write
26 |
27 | if(!parse_line(command, &mode, &address, &data))
28 | {
29 | continue;
30 | }
31 |
32 | if(mode == 1)
33 | {
34 | //write
35 | *((uint32_t*)address) = data;
36 | send_line("OK\n");
37 | }
38 | else if(mode == 0)
39 | {
40 | //read
41 | uint32_t *ptr = (uint32_t*)address;
42 | int i;
43 | uint32_t word;
44 | for(i=0; i>2; ++i)
45 | {
46 | word = ptr[i];
47 | transmit_byte_as_ascii_space((word >> 0) & 0xFF);
48 | transmit_byte_as_ascii_space((word >> 8) & 0xFF);
49 | transmit_byte_as_ascii_space((word >> 16) & 0xFF);
50 | transmit_byte_as_ascii_space((word >> 24) & 0xFF);
51 | }
52 |
53 | send_line("\n");
54 | }
55 | else if(mode == 2)
56 | {
57 | if(data <= 0x100)
58 | {
59 | int i;
60 | uint8_t buffer[0x100];
61 | read_flash(address, (uint32_t*)buffer, data);
62 |
63 | for(i=0; i> 4) & 0x0F];
84 | tb[1] = alphabet[(byte >> 0) & 0x0F];
85 | send_line(tb);
86 | }
87 |
88 | unsigned char char_to_nibble(char c)
89 | {
90 | if (c >= '0' && c <= '9')
91 | {
92 | return c - '0';
93 | }
94 | else if (c >= 'a' && c <= 'f')
95 | {
96 | return c - 'a' + 0x0a;
97 | }
98 | else if (c >= 'A' && c <= 'F')
99 | {
100 | return c - 'A' + 0x0a;
101 | }
102 | else
103 | {
104 | return 0xff;
105 | }
106 | }
107 |
108 | int parse_line(char* command, uint8_t* mode, uint32_t* address, uint32_t* data)
109 | {
110 | //command is like
111 | //r00000000.11111111 - read 0x11111111 bytes from address 0x00000000
112 | //w00000000.11111111 - write word 0x11111111 to address 0x00000000
113 | //f00000000.11111111 - read 0x11111111 bytes from flash address 0x00000000
114 |
115 | int pos = 0;
116 | if (command[pos] == 'r' || command[pos] == 'R')
117 | {
118 | *mode = 0;
119 | }
120 | else if (command[pos] == 'w' || command[pos] == 'W')
121 | {
122 | *mode = 1;
123 | }
124 | else if (command[pos] == 'f' || command[pos] == 'F')
125 | {
126 | *mode = 2;
127 | }
128 | else
129 | {
130 | return 0;
131 | }
132 |
133 | pos++;
134 |
135 | int sz;
136 | uint8_t orb;
137 |
138 | *address = 0;
139 | sz = 0;
140 | while (sz < 8)
141 | {
142 | orb = char_to_nibble(command[pos]);
143 | if (orb > 0x0f) break;
144 |
145 | *address <<= 4;
146 | *address |= orb;
147 |
148 | sz++;
149 | pos++;
150 | }
151 |
152 | if (sz == 0)
153 | {
154 | return 0;
155 | }
156 |
157 | if (command[pos] != '.')
158 | {
159 | return 0;
160 | }
161 | pos++;
162 |
163 | *data = 0;
164 | sz = 0;
165 |
166 | while (sz < 8)
167 | {
168 | orb = char_to_nibble(command[pos]);
169 | if (orb > 0x0f) break;
170 |
171 | *data <<= 4;
172 | *data |= orb;
173 |
174 | sz++;
175 | pos++;
176 | }
177 |
178 | if (command[pos] != '\n' && command[pos] != '\0')
179 | {
180 | return 0;
181 | }
182 |
183 | return 1;
184 | }
185 | int get_line(char *buffer, int buffer_len)
186 | {
187 | int i=0;
188 | while(iFLAG & UART_MASK_RX_IF));
191 | buffer[i]=QN_UART0->RXD;
192 | if(buffer[i] == '\n')
193 | {
194 | buffer[i+1] = '\0';
195 | return 1;
196 | }
197 | i++;
198 | }
199 | return 0;
200 | }
201 |
202 | void send_line(char *buffer)
203 | {
204 | int i = 0;
205 | while(buffer[i])
206 | {
207 | while(!(QN_UART0->FLAG & UART_MASK_TX_IF));
208 | QN_UART0->TXD = buffer[i++];
209 | }
210 | }
211 |
212 | void setup_peripherials()
213 | {
214 | QN_SYSCON->IVREF_X32 = SYSCON_MASK_DVDD12_SW_EN;
215 |
216 | QN_SYSCON->CRSS = 0xff7a0000;
217 |
218 | QN_SYSCON->CMDCR = 0;
219 | QN_SYSCON->CMDCR |= SYSCON_MASK_APB_DIV_BYPASS; //APB bypass divider
220 | QN_SYSCON->CMDCR |= SYSCON_MASK_USART0_DIV_BYPASS; //UART0 bypass divider
221 |
222 | QN_SYSCON->PMCR0 = P00_UART0_TXD_PIN_CTRL | P17_UART0_RXD_PIN_CTRL;//UART0 tx+rx to p0_0+p1_7
223 | QN_SYSCON->PPCR0 = 0x80000002;//pull-up P0_0 P1_7
224 |
225 | QN_SYSCON->CRSC = SYSCON_MASK_GATING_UART0 | SYSCON_MASK_GATING_SPI_AHB;//enable UART0 clock
226 |
227 | QN_UART0->BAUD = 0x00000416;//115200
228 | QN_UART0->CR = UART_MASK_UART_EN | UART_MASK_TX_EN | UART_MASK_RX_EN | UART_MASK_BIT_ORDER | UART_MASK_LEVEL_INV | UART_MASK_OVS;
229 | }
230 |
231 |
232 | #define RD_FLASH_ST_CMD 0x0500
233 |
234 | void sf_ctrl_SetCRWithMask(QN_SF_CTRL_TypeDef *SF_CTRL, uint32_t mask, uint32_t value)
235 | {
236 | SF_CTRL->CTRL_STAT = ((SF_CTRL->CTRL_STAT) & (~mask)) | (mask & value);
237 | }
238 |
239 | bool is_flash_busy(void)
240 | {
241 | uint32_t status;
242 |
243 | sf_ctrl_SetCRWithMask(QN_SF_CTRL, SF_CTRL_MASK_RD_STAT_CMD, RD_FLASH_ST_CMD);
244 |
245 | status = QN_SF_CTRL->FLASH_SR;
246 |
247 | return ((status & 0x01) == 0x1);
248 | }
249 |
250 |
251 | void read_flash(uint32_t addr, uint32_t *pBuf, uint32_t nByte)
252 | {
253 | addr += QN_FLASH_BASE; //get the data register address of flash control register
254 | while(is_flash_busy()); //wait the flash is free.
255 | QN_SF_CTRL->DATA_LEN = nByte;
256 | nByte >>= 2; //nByte must is 4 integer times
257 | while (nByte--)
258 | {
259 | *pBuf++ = *(uint32_t *)addr;
260 | addr += 4;
261 | }
262 | }
263 |
--------------------------------------------------------------------------------
/ramdump-firmware/cmsis/core_cm0.c:
--------------------------------------------------------------------------------
1 | /**************************************************************************//**
2 | * @file core_cm0.c
3 | * @brief CMSIS Cortex-M0 Core Peripheral Access Layer Source File
4 | * @version V2.00
5 | * @date 10. September 2010
6 | *
7 | * @note
8 | * Copyright (C) 2009-2010 ARM Limited. All rights reserved.
9 | *
10 | * @par
11 | * ARM Limited (ARM) is supplying this software for use with Cortex-M
12 | * processor based microcontrollers. This file can be freely distributed
13 | * within development tools that are supporting such ARM based processors.
14 | *
15 | * @par
16 | * THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED
17 | * OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
18 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
19 | * ARM SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR
20 | * CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
21 | *
22 | ******************************************************************************/
23 |
24 | #include
25 |
26 | /* define compiler specific symbols */
27 | #if defined ( __CC_ARM )
28 | #define __ASM __asm /*!< asm keyword for ARM Compiler */
29 | #define __INLINE __inline /*!< inline keyword for ARM Compiler */
30 |
31 | #elif defined ( __ICCARM__ )
32 | #define __ASM __asm /*!< asm keyword for IAR Compiler */
33 | #define __INLINE inline /*!< inline keyword for IAR Compiler. Only avaiable in High optimization mode! */
34 |
35 | #elif defined ( __GNUC__ )
36 | #define __ASM __asm /*!< asm keyword for GNU Compiler */
37 | #define __INLINE inline /*!< inline keyword for GNU Compiler */
38 |
39 | #elif defined ( __TASKING__ )
40 | #define __ASM __asm /*!< asm keyword for TASKING Compiler */
41 | #define __INLINE inline /*!< inline keyword for TASKING Compiler */
42 |
43 | #endif
44 |
45 |
46 | /* ########################## Core Instruction Access ######################### */
47 |
48 | #if defined ( __CC_ARM ) /*------------------ RealView Compiler ----------------*/
49 |
50 | /** \brief Reverse byte order (16 bit)
51 |
52 | This function reverses the byte order in two unsigned short values.
53 |
54 | \param [in] value Value to reverse
55 | \return Reversed value
56 | */
57 | #if (__ARMCC_VERSION < 400677)
58 | __ASM uint32_t __REV16(uint32_t value)
59 | {
60 | rev16 r0, r0
61 | bx lr
62 | }
63 | #endif /* __ARMCC_VERSION */
64 |
65 |
66 | /** \brief Reverse byte order in signed short value
67 |
68 | This function reverses the byte order in a signed short value with sign extension to integer.
69 |
70 | \param [in] value Value to reverse
71 | \return Reversed value
72 | */
73 | #if (__ARMCC_VERSION < 400677)
74 | __ASM int32_t __REVSH(int32_t value)
75 | {
76 | revsh r0, r0
77 | bx lr
78 | }
79 | #endif /* __ARMCC_VERSION */
80 |
81 |
82 | /** \brief Remove the exclusive lock
83 |
84 | This function removes the exclusive lock which is created by LDREX.
85 |
86 | */
87 | #if (__ARMCC_VERSION < 400000)
88 | __ASM void __CLREX(void)
89 | {
90 | clrex
91 | }
92 | #endif /* __ARMCC_VERSION */
93 |
94 |
95 | #elif (defined (__ICCARM__)) /*---------------- ICC Compiler ---------------------*/
96 | /* obsolete */
97 | #elif (defined (__GNUC__)) /*------------------ GNU Compiler ---------------------*/
98 | /* obsolete */
99 | #elif (defined (__TASKING__)) /*--------------- TASKING Compiler -----------------*/
100 | /* obsolete */
101 | #endif
102 |
103 |
104 | /* ########################### Core Function Access ########################### */
105 |
106 | #if defined ( __CC_ARM ) /*------------------ RealView Compiler ----------------*/
107 |
108 | /** \brief Get Control Register
109 |
110 | This function returns the content of the Control Register.
111 |
112 | \return Control Register value
113 | */
114 | #if (__ARMCC_VERSION < 400000)
115 | __ASM uint32_t __get_CONTROL(void)
116 | {
117 | mrs r0, control
118 | bx lr
119 | }
120 | #endif /* __ARMCC_VERSION */
121 |
122 |
123 | /** \brief Set Control Register
124 |
125 | This function writes the given value to the Control Register.
126 |
127 | \param [in] control Control Register value to set
128 | */
129 | #if (__ARMCC_VERSION < 400000)
130 | __ASM void __set_CONTROL(uint32_t control)
131 | {
132 | msr control, r0
133 | bx lr
134 | }
135 | #endif /* __ARMCC_VERSION */
136 |
137 |
138 | /** \brief Get ISPR Register
139 |
140 | This function returns the content of the ISPR Register.
141 |
142 | \return ISPR Register value
143 | */
144 | #if (__ARMCC_VERSION < 400000)
145 | __ASM uint32_t __get_IPSR(void)
146 | {
147 | mrs r0, ipsr
148 | bx lr
149 | }
150 | #endif /* __ARMCC_VERSION */
151 |
152 |
153 | /** \brief Get APSR Register
154 |
155 | This function returns the content of the APSR Register.
156 |
157 | \return APSR Register value
158 | */
159 | #if (__ARMCC_VERSION < 400000)
160 | __ASM uint32_t __get_APSR(void)
161 | {
162 | mrs r0, apsr
163 | bx lr
164 | }
165 | #endif /* __ARMCC_VERSION */
166 |
167 |
168 | /** \brief Get xPSR Register
169 |
170 | This function returns the content of the xPSR Register.
171 |
172 | \return xPSR Register value
173 | */
174 | #if (__ARMCC_VERSION < 400000)
175 | __ASM uint32_t __get_xPSR(void)
176 | {
177 | mrs r0, xpsr
178 | bx lr
179 | }
180 | #endif /* __ARMCC_VERSION */
181 |
182 |
183 | /** \brief Get Process Stack Pointer
184 |
185 | This function returns the current value of the Process Stack Pointer (PSP).
186 |
187 | \return PSP Register value
188 | */
189 | #if (__ARMCC_VERSION < 400000)
190 | __ASM uint32_t __get_PSP(void)
191 | {
192 | mrs r0, psp
193 | bx lr
194 | }
195 | #endif /* __ARMCC_VERSION */
196 |
197 |
198 | /** \brief Set Process Stack Pointer
199 |
200 | This function assigns the given value to the Process Stack Pointer (PSP).
201 |
202 | \param [in] topOfProcStack Process Stack Pointer value to set
203 | */
204 | #if (__ARMCC_VERSION < 400000)
205 | __ASM void __set_PSP(uint32_t topOfProcStack)
206 | {
207 | msr psp, r0
208 | bx lr
209 | }
210 | #endif /* __ARMCC_VERSION */
211 |
212 |
213 | /** \brief Get Main Stack Pointer
214 |
215 | This function returns the current value of the Main Stack Pointer (MSP).
216 |
217 | \return MSP Register value
218 | */
219 | #if (__ARMCC_VERSION < 400000)
220 | __ASM uint32_t __get_MSP(void)
221 | {
222 | mrs r0, msp
223 | bx lr
224 | }
225 | #endif /* __ARMCC_VERSION */
226 |
227 |
228 | /** \brief Set Main Stack Pointer
229 |
230 | This function assigns the given value to the Main Stack Pointer (MSP).
231 |
232 | \param [in] topOfMainStack Main Stack Pointer value to set
233 | */
234 | #if (__ARMCC_VERSION < 400000)
235 | __ASM void __set_MSP(uint32_t mainStackPointer)
236 | {
237 | msr msp, r0
238 | bx lr
239 | }
240 | #endif /* __ARMCC_VERSION */
241 |
242 |
243 | /** \brief Get Priority Mask
244 |
245 | This function returns the current state of the priority mask bit from the Priority Mask Register.
246 |
247 | \return Priority Mask value
248 | */
249 | #if (__ARMCC_VERSION < 400000)
250 | __ASM uint32_t __get_PRIMASK(void)
251 | {
252 | mrs r0, primask
253 | bx lr
254 | }
255 | #endif /* __ARMCC_VERSION */
256 |
257 |
258 | /** \brief Set Priority Mask
259 |
260 | This function assigns the given value to the Priority Mask Register.
261 |
262 | \param [in] priMask Priority Mask
263 | */
264 | #if (__ARMCC_VERSION < 400000)
265 | __ASM void __set_PRIMASK(uint32_t priMask)
266 | {
267 | msr primask, r0
268 | bx lr
269 | }
270 | #endif /* __ARMCC_VERSION */
271 |
272 |
273 | #elif (defined (__ICCARM__)) /*---------------- ICC Compiler ---------------------*/
274 | /* obsolete */
275 | #elif (defined (__GNUC__)) /*------------------ GNU Compiler ---------------------*/
276 | /* obsolete */
277 | #elif (defined (__TASKING__)) /*--------------- TASKING Compiler -----------------*/
278 | /* obsolete */
279 | #endif
280 |
--------------------------------------------------------------------------------
/ramdump-firmware/cmsis/core_cmFunc.h:
--------------------------------------------------------------------------------
1 | /**************************************************************************//**
2 | * @file core_cmFunc.h
3 | * @brief CMSIS Cortex-M Core Function Access Header File
4 | * @version V3.01
5 | * @date 06. March 2012
6 | *
7 | * @note
8 | * Copyright (C) 2009-2012 ARM Limited. All rights reserved.
9 | *
10 | * @par
11 | * ARM Limited (ARM) is supplying this software for use with Cortex-M
12 | * processor based microcontrollers. This file can be freely distributed
13 | * within development tools that are supporting such ARM based processors.
14 | *
15 | * @par
16 | * THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED
17 | * OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
18 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
19 | * ARM SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR
20 | * CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
21 | *
22 | ******************************************************************************/
23 |
24 | #ifndef __CORE_CMFUNC_H
25 | #define __CORE_CMFUNC_H
26 |
27 |
28 | /* ########################### Core Function Access ########################### */
29 | /** \ingroup CMSIS_Core_FunctionInterface
30 | \defgroup CMSIS_Core_RegAccFunctions CMSIS Core Register Access Functions
31 | @{
32 | */
33 |
34 | #if defined ( __CC_ARM ) /*------------------RealView Compiler -----------------*/
35 | /* ARM armcc specific functions */
36 |
37 | #if (__ARMCC_VERSION < 400677)
38 | #error "Please use ARM Compiler Toolchain V4.0.677 or later!"
39 | #endif
40 |
41 | /* intrinsic void __enable_irq(); */
42 | /* intrinsic void __disable_irq(); */
43 |
44 | /** \brief Get Control Register
45 |
46 | This function returns the content of the Control Register.
47 |
48 | \return Control Register value
49 | */
50 | __STATIC_INLINE uint32_t __get_CONTROL(void)
51 | {
52 | register uint32_t __regControl __ASM("control");
53 | return(__regControl);
54 | }
55 |
56 |
57 | /** \brief Set Control Register
58 |
59 | This function writes the given value to the Control Register.
60 |
61 | \param [in] control Control Register value to set
62 | */
63 | __STATIC_INLINE void __set_CONTROL(uint32_t control)
64 | {
65 | register uint32_t __regControl __ASM("control");
66 | __regControl = control;
67 | }
68 |
69 |
70 | /** \brief Get IPSR Register
71 |
72 | This function returns the content of the IPSR Register.
73 |
74 | \return IPSR Register value
75 | */
76 | __STATIC_INLINE uint32_t __get_IPSR(void)
77 | {
78 | register uint32_t __regIPSR __ASM("ipsr");
79 | return(__regIPSR);
80 | }
81 |
82 |
83 | /** \brief Get APSR Register
84 |
85 | This function returns the content of the APSR Register.
86 |
87 | \return APSR Register value
88 | */
89 | __STATIC_INLINE uint32_t __get_APSR(void)
90 | {
91 | register uint32_t __regAPSR __ASM("apsr");
92 | return(__regAPSR);
93 | }
94 |
95 |
96 | /** \brief Get xPSR Register
97 |
98 | This function returns the content of the xPSR Register.
99 |
100 | \return xPSR Register value
101 | */
102 | __STATIC_INLINE uint32_t __get_xPSR(void)
103 | {
104 | register uint32_t __regXPSR __ASM("xpsr");
105 | return(__regXPSR);
106 | }
107 |
108 |
109 | /** \brief Get Process Stack Pointer
110 |
111 | This function returns the current value of the Process Stack Pointer (PSP).
112 |
113 | \return PSP Register value
114 | */
115 | __STATIC_INLINE uint32_t __get_PSP(void)
116 | {
117 | register uint32_t __regProcessStackPointer __ASM("psp");
118 | return(__regProcessStackPointer);
119 | }
120 |
121 |
122 | /** \brief Set Process Stack Pointer
123 |
124 | This function assigns the given value to the Process Stack Pointer (PSP).
125 |
126 | \param [in] topOfProcStack Process Stack Pointer value to set
127 | */
128 | __STATIC_INLINE void __set_PSP(uint32_t topOfProcStack)
129 | {
130 | register uint32_t __regProcessStackPointer __ASM("psp");
131 | __regProcessStackPointer = topOfProcStack;
132 | }
133 |
134 |
135 | /** \brief Get Main Stack Pointer
136 |
137 | This function returns the current value of the Main Stack Pointer (MSP).
138 |
139 | \return MSP Register value
140 | */
141 | __STATIC_INLINE uint32_t __get_MSP(void)
142 | {
143 | register uint32_t __regMainStackPointer __ASM("msp");
144 | return(__regMainStackPointer);
145 | }
146 |
147 |
148 | /** \brief Set Main Stack Pointer
149 |
150 | This function assigns the given value to the Main Stack Pointer (MSP).
151 |
152 | \param [in] topOfMainStack Main Stack Pointer value to set
153 | */
154 | __STATIC_INLINE void __set_MSP(uint32_t topOfMainStack)
155 | {
156 | register uint32_t __regMainStackPointer __ASM("msp");
157 | __regMainStackPointer = topOfMainStack;
158 | }
159 |
160 |
161 | /** \brief Get Priority Mask
162 |
163 | This function returns the current state of the priority mask bit from the Priority Mask Register.
164 |
165 | \return Priority Mask value
166 | */
167 | __STATIC_INLINE uint32_t __get_PRIMASK(void)
168 | {
169 | register uint32_t __regPriMask __ASM("primask");
170 | return(__regPriMask);
171 | }
172 |
173 |
174 | /** \brief Set Priority Mask
175 |
176 | This function assigns the given value to the Priority Mask Register.
177 |
178 | \param [in] priMask Priority Mask
179 | */
180 | __STATIC_INLINE void __set_PRIMASK(uint32_t priMask)
181 | {
182 | register uint32_t __regPriMask __ASM("primask");
183 | __regPriMask = (priMask);
184 | }
185 |
186 |
187 | #if (__CORTEX_M >= 0x03)
188 |
189 | /** \brief Enable FIQ
190 |
191 | This function enables FIQ interrupts by clearing the F-bit in the CPSR.
192 | Can only be executed in Privileged modes.
193 | */
194 | #define __enable_fault_irq __enable_fiq
195 |
196 |
197 | /** \brief Disable FIQ
198 |
199 | This function disables FIQ interrupts by setting the F-bit in the CPSR.
200 | Can only be executed in Privileged modes.
201 | */
202 | #define __disable_fault_irq __disable_fiq
203 |
204 |
205 | /** \brief Get Base Priority
206 |
207 | This function returns the current value of the Base Priority register.
208 |
209 | \return Base Priority register value
210 | */
211 | __STATIC_INLINE uint32_t __get_BASEPRI(void)
212 | {
213 | register uint32_t __regBasePri __ASM("basepri");
214 | return(__regBasePri);
215 | }
216 |
217 |
218 | /** \brief Set Base Priority
219 |
220 | This function assigns the given value to the Base Priority register.
221 |
222 | \param [in] basePri Base Priority value to set
223 | */
224 | __STATIC_INLINE void __set_BASEPRI(uint32_t basePri)
225 | {
226 | register uint32_t __regBasePri __ASM("basepri");
227 | __regBasePri = (basePri & 0xff);
228 | }
229 |
230 |
231 | /** \brief Get Fault Mask
232 |
233 | This function returns the current value of the Fault Mask register.
234 |
235 | \return Fault Mask register value
236 | */
237 | __STATIC_INLINE uint32_t __get_FAULTMASK(void)
238 | {
239 | register uint32_t __regFaultMask __ASM("faultmask");
240 | return(__regFaultMask);
241 | }
242 |
243 |
244 | /** \brief Set Fault Mask
245 |
246 | This function assigns the given value to the Fault Mask register.
247 |
248 | \param [in] faultMask Fault Mask value to set
249 | */
250 | __STATIC_INLINE void __set_FAULTMASK(uint32_t faultMask)
251 | {
252 | register uint32_t __regFaultMask __ASM("faultmask");
253 | __regFaultMask = (faultMask & (uint32_t)1);
254 | }
255 |
256 | #endif /* (__CORTEX_M >= 0x03) */
257 |
258 |
259 | #if (__CORTEX_M == 0x04)
260 |
261 | /** \brief Get FPSCR
262 |
263 | This function returns the current value of the Floating Point Status/Control register.
264 |
265 | \return Floating Point Status/Control register value
266 | */
267 | __STATIC_INLINE uint32_t __get_FPSCR(void)
268 | {
269 | #if (__FPU_PRESENT == 1) && (__FPU_USED == 1)
270 | register uint32_t __regfpscr __ASM("fpscr");
271 | return(__regfpscr);
272 | #else
273 | return(0);
274 | #endif
275 | }
276 |
277 |
278 | /** \brief Set FPSCR
279 |
280 | This function assigns the given value to the Floating Point Status/Control register.
281 |
282 | \param [in] fpscr Floating Point Status/Control value to set
283 | */
284 | __STATIC_INLINE void __set_FPSCR(uint32_t fpscr)
285 | {
286 | #if (__FPU_PRESENT == 1) && (__FPU_USED == 1)
287 | register uint32_t __regfpscr __ASM("fpscr");
288 | __regfpscr = (fpscr);
289 | #endif
290 | }
291 |
292 | #endif /* (__CORTEX_M == 0x04) */
293 |
294 |
295 | #elif defined ( __ICCARM__ ) /*------------------ ICC Compiler -------------------*/
296 | /* IAR iccarm specific functions */
297 |
298 | #include
299 |
300 |
301 | #elif defined ( __TMS470__ ) /*---------------- TI CCS Compiler ------------------*/
302 | /* TI CCS specific functions */
303 |
304 | #include
305 |
306 |
307 | #elif defined ( __GNUC__ ) /*------------------ GNU Compiler ---------------------*/
308 | /* GNU gcc specific functions */
309 |
310 | /** \brief Enable IRQ Interrupts
311 |
312 | This function enables IRQ interrupts by clearing the I-bit in the CPSR.
313 | Can only be executed in Privileged modes.
314 | */
315 | __attribute__( ( always_inline ) ) __STATIC_INLINE void __enable_irq(void)
316 | {
317 | __ASM volatile ("cpsie i");
318 | }
319 |
320 |
321 | /** \brief Disable IRQ Interrupts
322 |
323 | This function disables IRQ interrupts by setting the I-bit in the CPSR.
324 | Can only be executed in Privileged modes.
325 | */
326 | __attribute__( ( always_inline ) ) __STATIC_INLINE void __disable_irq(void)
327 | {
328 | __ASM volatile ("cpsid i");
329 | }
330 |
331 |
332 | /** \brief Get Control Register
333 |
334 | This function returns the content of the Control Register.
335 |
336 | \return Control Register value
337 | */
338 | __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_CONTROL(void)
339 | {
340 | uint32_t result;
341 |
342 | __ASM volatile ("MRS %0, control" : "=r" (result) );
343 | return(result);
344 | }
345 |
346 |
347 | /** \brief Set Control Register
348 |
349 | This function writes the given value to the Control Register.
350 |
351 | \param [in] control Control Register value to set
352 | */
353 | __attribute__( ( always_inline ) ) __STATIC_INLINE void __set_CONTROL(uint32_t control)
354 | {
355 | __ASM volatile ("MSR control, %0" : : "r" (control) );
356 | }
357 |
358 |
359 | /** \brief Get IPSR Register
360 |
361 | This function returns the content of the IPSR Register.
362 |
363 | \return IPSR Register value
364 | */
365 | __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_IPSR(void)
366 | {
367 | uint32_t result;
368 |
369 | __ASM volatile ("MRS %0, ipsr" : "=r" (result) );
370 | return(result);
371 | }
372 |
373 |
374 | /** \brief Get APSR Register
375 |
376 | This function returns the content of the APSR Register.
377 |
378 | \return APSR Register value
379 | */
380 | __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_APSR(void)
381 | {
382 | uint32_t result;
383 |
384 | __ASM volatile ("MRS %0, apsr" : "=r" (result) );
385 | return(result);
386 | }
387 |
388 |
389 | /** \brief Get xPSR Register
390 |
391 | This function returns the content of the xPSR Register.
392 |
393 | \return xPSR Register value
394 | */
395 | __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_xPSR(void)
396 | {
397 | uint32_t result;
398 |
399 | __ASM volatile ("MRS %0, xpsr" : "=r" (result) );
400 | return(result);
401 | }
402 |
403 |
404 | /** \brief Get Process Stack Pointer
405 |
406 | This function returns the current value of the Process Stack Pointer (PSP).
407 |
408 | \return PSP Register value
409 | */
410 | __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_PSP(void)
411 | {
412 | register uint32_t result;
413 |
414 | __ASM volatile ("MRS %0, psp\n" : "=r" (result) );
415 | return(result);
416 | }
417 |
418 |
419 | /** \brief Set Process Stack Pointer
420 |
421 | This function assigns the given value to the Process Stack Pointer (PSP).
422 |
423 | \param [in] topOfProcStack Process Stack Pointer value to set
424 | */
425 | __attribute__( ( always_inline ) ) __STATIC_INLINE void __set_PSP(uint32_t topOfProcStack)
426 | {
427 | __ASM volatile ("MSR psp, %0\n" : : "r" (topOfProcStack) );
428 | }
429 |
430 |
431 | /** \brief Get Main Stack Pointer
432 |
433 | This function returns the current value of the Main Stack Pointer (MSP).
434 |
435 | \return MSP Register value
436 | */
437 | __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_MSP(void)
438 | {
439 | register uint32_t result;
440 |
441 | __ASM volatile ("MRS %0, msp\n" : "=r" (result) );
442 | return(result);
443 | }
444 |
445 |
446 | /** \brief Set Main Stack Pointer
447 |
448 | This function assigns the given value to the Main Stack Pointer (MSP).
449 |
450 | \param [in] topOfMainStack Main Stack Pointer value to set
451 | */
452 | __attribute__( ( always_inline ) ) __STATIC_INLINE void __set_MSP(uint32_t topOfMainStack)
453 | {
454 | __ASM volatile ("MSR msp, %0\n" : : "r" (topOfMainStack) );
455 | }
456 |
457 |
458 | /** \brief Get Priority Mask
459 |
460 | This function returns the current state of the priority mask bit from the Priority Mask Register.
461 |
462 | \return Priority Mask value
463 | */
464 | __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_PRIMASK(void)
465 | {
466 | uint32_t result;
467 |
468 | __ASM volatile ("MRS %0, primask" : "=r" (result) );
469 | return(result);
470 | }
471 |
472 |
473 | /** \brief Set Priority Mask
474 |
475 | This function assigns the given value to the Priority Mask Register.
476 |
477 | \param [in] priMask Priority Mask
478 | */
479 | __attribute__( ( always_inline ) ) __STATIC_INLINE void __set_PRIMASK(uint32_t priMask)
480 | {
481 | __ASM volatile ("MSR primask, %0" : : "r" (priMask) );
482 | }
483 |
484 |
485 | #if (__CORTEX_M >= 0x03)
486 |
487 | /** \brief Enable FIQ
488 |
489 | This function enables FIQ interrupts by clearing the F-bit in the CPSR.
490 | Can only be executed in Privileged modes.
491 | */
492 | __attribute__( ( always_inline ) ) __STATIC_INLINE void __enable_fault_irq(void)
493 | {
494 | __ASM volatile ("cpsie f");
495 | }
496 |
497 |
498 | /** \brief Disable FIQ
499 |
500 | This function disables FIQ interrupts by setting the F-bit in the CPSR.
501 | Can only be executed in Privileged modes.
502 | */
503 | __attribute__( ( always_inline ) ) __STATIC_INLINE void __disable_fault_irq(void)
504 | {
505 | __ASM volatile ("cpsid f");
506 | }
507 |
508 |
509 | /** \brief Get Base Priority
510 |
511 | This function returns the current value of the Base Priority register.
512 |
513 | \return Base Priority register value
514 | */
515 | __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_BASEPRI(void)
516 | {
517 | uint32_t result;
518 |
519 | __ASM volatile ("MRS %0, basepri_max" : "=r" (result) );
520 | return(result);
521 | }
522 |
523 |
524 | /** \brief Set Base Priority
525 |
526 | This function assigns the given value to the Base Priority register.
527 |
528 | \param [in] basePri Base Priority value to set
529 | */
530 | __attribute__( ( always_inline ) ) __STATIC_INLINE void __set_BASEPRI(uint32_t value)
531 | {
532 | __ASM volatile ("MSR basepri, %0" : : "r" (value) );
533 | }
534 |
535 |
536 | /** \brief Get Fault Mask
537 |
538 | This function returns the current value of the Fault Mask register.
539 |
540 | \return Fault Mask register value
541 | */
542 | __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_FAULTMASK(void)
543 | {
544 | uint32_t result;
545 |
546 | __ASM volatile ("MRS %0, faultmask" : "=r" (result) );
547 | return(result);
548 | }
549 |
550 |
551 | /** \brief Set Fault Mask
552 |
553 | This function assigns the given value to the Fault Mask register.
554 |
555 | \param [in] faultMask Fault Mask value to set
556 | */
557 | __attribute__( ( always_inline ) ) __STATIC_INLINE void __set_FAULTMASK(uint32_t faultMask)
558 | {
559 | __ASM volatile ("MSR faultmask, %0" : : "r" (faultMask) );
560 | }
561 |
562 | #endif /* (__CORTEX_M >= 0x03) */
563 |
564 |
565 | #if (__CORTEX_M == 0x04)
566 |
567 | /** \brief Get FPSCR
568 |
569 | This function returns the current value of the Floating Point Status/Control register.
570 |
571 | \return Floating Point Status/Control register value
572 | */
573 | __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_FPSCR(void)
574 | {
575 | #if (__FPU_PRESENT == 1) && (__FPU_USED == 1)
576 | uint32_t result;
577 |
578 | __ASM volatile ("VMRS %0, fpscr" : "=r" (result) );
579 | return(result);
580 | #else
581 | return(0);
582 | #endif
583 | }
584 |
585 |
586 | /** \brief Set FPSCR
587 |
588 | This function assigns the given value to the Floating Point Status/Control register.
589 |
590 | \param [in] fpscr Floating Point Status/Control value to set
591 | */
592 | __attribute__( ( always_inline ) ) __STATIC_INLINE void __set_FPSCR(uint32_t fpscr)
593 | {
594 | #if (__FPU_PRESENT == 1) && (__FPU_USED == 1)
595 | __ASM volatile ("VMSR fpscr, %0" : : "r" (fpscr) );
596 | #endif
597 | }
598 |
599 | #endif /* (__CORTEX_M == 0x04) */
600 |
601 |
602 | #elif defined ( __TASKING__ ) /*------------------ TASKING Compiler --------------*/
603 | /* TASKING carm specific functions */
604 |
605 | /*
606 | * The CMSIS functions have been implemented as intrinsics in the compiler.
607 | * Please use "carm -?i" to get an up to date list of all instrinsics,
608 | * Including the CMSIS ones.
609 | */
610 |
611 | #endif
612 |
613 | /*@} end of CMSIS_Core_RegAccFunctions */
614 |
615 |
616 | #endif /* __CORE_CMFUNC_H */
617 |
--------------------------------------------------------------------------------
/ramdump-firmware/cmsis/core_cmInstr.h:
--------------------------------------------------------------------------------
1 | /**************************************************************************//**
2 | * @file core_cmInstr.h
3 | * @brief CMSIS Cortex-M Core Instruction Access Header File
4 | * @version V3.01
5 | * @date 06. March 2012
6 | *
7 | * @note
8 | * Copyright (C) 2009-2012 ARM Limited. All rights reserved.
9 | *
10 | * @par
11 | * ARM Limited (ARM) is supplying this software for use with Cortex-M
12 | * processor based microcontrollers. This file can be freely distributed
13 | * within development tools that are supporting such ARM based processors.
14 | *
15 | * @par
16 | * THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED
17 | * OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
18 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
19 | * ARM SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR
20 | * CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
21 | *
22 | ******************************************************************************/
23 |
24 | #ifndef __CORE_CMINSTR_H
25 | #define __CORE_CMINSTR_H
26 |
27 |
28 | /* ########################## Core Instruction Access ######################### */
29 | /** \defgroup CMSIS_Core_InstructionInterface CMSIS Core Instruction Interface
30 | Access to dedicated instructions
31 | @{
32 | */
33 |
34 | #if defined ( __CC_ARM ) /*------------------RealView Compiler -----------------*/
35 | /* ARM armcc specific functions */
36 |
37 | #if (__ARMCC_VERSION < 400677)
38 | #error "Please use ARM Compiler Toolchain V4.0.677 or later!"
39 | #endif
40 |
41 |
42 | /** \brief No Operation
43 |
44 | No Operation does nothing. This instruction can be used for code alignment purposes.
45 | */
46 | #define __NOP __nop
47 |
48 |
49 | /** \brief Wait For Interrupt
50 |
51 | Wait For Interrupt is a hint instruction that suspends execution
52 | until one of a number of events occurs.
53 | */
54 | #define __WFI __wfi
55 |
56 |
57 | /** \brief Wait For Event
58 |
59 | Wait For Event is a hint instruction that permits the processor to enter
60 | a low-power state until one of a number of events occurs.
61 | */
62 | #define __WFE __wfe
63 |
64 |
65 | /** \brief Send Event
66 |
67 | Send Event is a hint instruction. It causes an event to be signaled to the CPU.
68 | */
69 | #define __SEV __sev
70 |
71 |
72 | /** \brief Instruction Synchronization Barrier
73 |
74 | Instruction Synchronization Barrier flushes the pipeline in the processor,
75 | so that all instructions following the ISB are fetched from cache or
76 | memory, after the instruction has been completed.
77 | */
78 | #define __ISB() __isb(0xF)
79 |
80 |
81 | /** \brief Data Synchronization Barrier
82 |
83 | This function acts as a special kind of Data Memory Barrier.
84 | It completes when all explicit memory accesses before this instruction complete.
85 | */
86 | #define __DSB() __dsb(0xF)
87 |
88 |
89 | /** \brief Data Memory Barrier
90 |
91 | This function ensures the apparent order of the explicit memory operations before
92 | and after the instruction, without ensuring their completion.
93 | */
94 | #define __DMB() __dmb(0xF)
95 |
96 |
97 | /** \brief Reverse byte order (32 bit)
98 |
99 | This function reverses the byte order in integer value.
100 |
101 | \param [in] value Value to reverse
102 | \return Reversed value
103 | */
104 | #define __REV __rev
105 |
106 |
107 | /** \brief Reverse byte order (16 bit)
108 |
109 | This function reverses the byte order in two unsigned short values.
110 |
111 | \param [in] value Value to reverse
112 | \return Reversed value
113 | */
114 | __attribute__((section(".rev16_text"))) __STATIC_INLINE __ASM uint32_t __REV16(uint32_t value)
115 | {
116 | rev16 r0, r0
117 | bx lr
118 | }
119 |
120 |
121 | /** \brief Reverse byte order in signed short value
122 |
123 | This function reverses the byte order in a signed short value with sign extension to integer.
124 |
125 | \param [in] value Value to reverse
126 | \return Reversed value
127 | */
128 | __attribute__((section(".revsh_text"))) __STATIC_INLINE __ASM int32_t __REVSH(int32_t value)
129 | {
130 | revsh r0, r0
131 | bx lr
132 | }
133 |
134 |
135 | /** \brief Rotate Right in unsigned value (32 bit)
136 |
137 | This function Rotate Right (immediate) provides the value of the contents of a register rotated by a variable number of bits.
138 |
139 | \param [in] value Value to rotate
140 | \param [in] value Number of Bits to rotate
141 | \return Rotated value
142 | */
143 | #define __ROR __ror
144 |
145 |
146 | #if (__CORTEX_M >= 0x03)
147 |
148 | /** \brief Reverse bit order of value
149 |
150 | This function reverses the bit order of the given value.
151 |
152 | \param [in] value Value to reverse
153 | \return Reversed value
154 | */
155 | #define __RBIT __rbit
156 |
157 |
158 | /** \brief LDR Exclusive (8 bit)
159 |
160 | This function performs a exclusive LDR command for 8 bit value.
161 |
162 | \param [in] ptr Pointer to data
163 | \return value of type uint8_t at (*ptr)
164 | */
165 | #define __LDREXB(ptr) ((uint8_t ) __ldrex(ptr))
166 |
167 |
168 | /** \brief LDR Exclusive (16 bit)
169 |
170 | This function performs a exclusive LDR command for 16 bit values.
171 |
172 | \param [in] ptr Pointer to data
173 | \return value of type uint16_t at (*ptr)
174 | */
175 | #define __LDREXH(ptr) ((uint16_t) __ldrex(ptr))
176 |
177 |
178 | /** \brief LDR Exclusive (32 bit)
179 |
180 | This function performs a exclusive LDR command for 32 bit values.
181 |
182 | \param [in] ptr Pointer to data
183 | \return value of type uint32_t at (*ptr)
184 | */
185 | #define __LDREXW(ptr) ((uint32_t ) __ldrex(ptr))
186 |
187 |
188 | /** \brief STR Exclusive (8 bit)
189 |
190 | This function performs a exclusive STR command for 8 bit values.
191 |
192 | \param [in] value Value to store
193 | \param [in] ptr Pointer to location
194 | \return 0 Function succeeded
195 | \return 1 Function failed
196 | */
197 | #define __STREXB(value, ptr) __strex(value, ptr)
198 |
199 |
200 | /** \brief STR Exclusive (16 bit)
201 |
202 | This function performs a exclusive STR command for 16 bit values.
203 |
204 | \param [in] value Value to store
205 | \param [in] ptr Pointer to location
206 | \return 0 Function succeeded
207 | \return 1 Function failed
208 | */
209 | #define __STREXH(value, ptr) __strex(value, ptr)
210 |
211 |
212 | /** \brief STR Exclusive (32 bit)
213 |
214 | This function performs a exclusive STR command for 32 bit values.
215 |
216 | \param [in] value Value to store
217 | \param [in] ptr Pointer to location
218 | \return 0 Function succeeded
219 | \return 1 Function failed
220 | */
221 | #define __STREXW(value, ptr) __strex(value, ptr)
222 |
223 |
224 | /** \brief Remove the exclusive lock
225 |
226 | This function removes the exclusive lock which is created by LDREX.
227 |
228 | */
229 | #define __CLREX __clrex
230 |
231 |
232 | /** \brief Signed Saturate
233 |
234 | This function saturates a signed value.
235 |
236 | \param [in] value Value to be saturated
237 | \param [in] sat Bit position to saturate to (1..32)
238 | \return Saturated value
239 | */
240 | #define __SSAT __ssat
241 |
242 |
243 | /** \brief Unsigned Saturate
244 |
245 | This function saturates an unsigned value.
246 |
247 | \param [in] value Value to be saturated
248 | \param [in] sat Bit position to saturate to (0..31)
249 | \return Saturated value
250 | */
251 | #define __USAT __usat
252 |
253 |
254 | /** \brief Count leading zeros
255 |
256 | This function counts the number of leading zeros of a data value.
257 |
258 | \param [in] value Value to count the leading zeros
259 | \return number of leading zeros in value
260 | */
261 | #define __CLZ __clz
262 |
263 | #endif /* (__CORTEX_M >= 0x03) */
264 |
265 |
266 |
267 | #elif defined ( __ICCARM__ ) /*------------------ ICC Compiler -------------------*/
268 | /* IAR iccarm specific functions */
269 |
270 | #include
271 |
272 |
273 | #elif defined ( __TMS470__ ) /*---------------- TI CCS Compiler ------------------*/
274 | /* TI CCS specific functions */
275 |
276 | #include
277 |
278 |
279 | #elif defined ( __GNUC__ ) /*------------------ GNU Compiler ---------------------*/
280 | /* GNU gcc specific functions */
281 |
282 | /** \brief No Operation
283 |
284 | No Operation does nothing. This instruction can be used for code alignment purposes.
285 | */
286 | __attribute__( ( always_inline ) ) __STATIC_INLINE void __NOP(void)
287 | {
288 | __ASM volatile ("nop");
289 | }
290 |
291 |
292 | /** \brief Wait For Interrupt
293 |
294 | Wait For Interrupt is a hint instruction that suspends execution
295 | until one of a number of events occurs.
296 | */
297 | __attribute__( ( always_inline ) ) __STATIC_INLINE void __WFI(void)
298 | {
299 | __ASM volatile ("wfi");
300 | }
301 |
302 |
303 | /** \brief Wait For Event
304 |
305 | Wait For Event is a hint instruction that permits the processor to enter
306 | a low-power state until one of a number of events occurs.
307 | */
308 | __attribute__( ( always_inline ) ) __STATIC_INLINE void __WFE(void)
309 | {
310 | __ASM volatile ("wfe");
311 | }
312 |
313 |
314 | /** \brief Send Event
315 |
316 | Send Event is a hint instruction. It causes an event to be signaled to the CPU.
317 | */
318 | __attribute__( ( always_inline ) ) __STATIC_INLINE void __SEV(void)
319 | {
320 | __ASM volatile ("sev");
321 | }
322 |
323 |
324 | /** \brief Instruction Synchronization Barrier
325 |
326 | Instruction Synchronization Barrier flushes the pipeline in the processor,
327 | so that all instructions following the ISB are fetched from cache or
328 | memory, after the instruction has been completed.
329 | */
330 | __attribute__( ( always_inline ) ) __STATIC_INLINE void __ISB(void)
331 | {
332 | __ASM volatile ("isb");
333 | }
334 |
335 |
336 | /** \brief Data Synchronization Barrier
337 |
338 | This function acts as a special kind of Data Memory Barrier.
339 | It completes when all explicit memory accesses before this instruction complete.
340 | */
341 | __attribute__( ( always_inline ) ) __STATIC_INLINE void __DSB(void)
342 | {
343 | __ASM volatile ("dsb");
344 | }
345 |
346 |
347 | /** \brief Data Memory Barrier
348 |
349 | This function ensures the apparent order of the explicit memory operations before
350 | and after the instruction, without ensuring their completion.
351 | */
352 | __attribute__( ( always_inline ) ) __STATIC_INLINE void __DMB(void)
353 | {
354 | __ASM volatile ("dmb");
355 | }
356 |
357 |
358 | /** \brief Reverse byte order (32 bit)
359 |
360 | This function reverses the byte order in integer value.
361 |
362 | \param [in] value Value to reverse
363 | \return Reversed value
364 | */
365 | __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __REV(uint32_t value)
366 | {
367 | uint32_t result;
368 |
369 | __ASM volatile ("rev %0, %1" : "=r" (result) : "r" (value) );
370 | return(result);
371 | }
372 |
373 |
374 | /** \brief Reverse byte order (16 bit)
375 |
376 | This function reverses the byte order in two unsigned short values.
377 |
378 | \param [in] value Value to reverse
379 | \return Reversed value
380 | */
381 | __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __REV16(uint32_t value)
382 | {
383 | uint32_t result;
384 |
385 | __ASM volatile ("rev16 %0, %1" : "=r" (result) : "r" (value) );
386 | return(result);
387 | }
388 |
389 |
390 | /** \brief Reverse byte order in signed short value
391 |
392 | This function reverses the byte order in a signed short value with sign extension to integer.
393 |
394 | \param [in] value Value to reverse
395 | \return Reversed value
396 | */
397 | __attribute__( ( always_inline ) ) __STATIC_INLINE int32_t __REVSH(int32_t value)
398 | {
399 | uint32_t result;
400 |
401 | __ASM volatile ("revsh %0, %1" : "=r" (result) : "r" (value) );
402 | return(result);
403 | }
404 |
405 |
406 | /** \brief Rotate Right in unsigned value (32 bit)
407 |
408 | This function Rotate Right (immediate) provides the value of the contents of a register rotated by a variable number of bits.
409 |
410 | \param [in] value Value to rotate
411 | \param [in] value Number of Bits to rotate
412 | \return Rotated value
413 | */
414 | __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __ROR(uint32_t op1, uint32_t op2)
415 | {
416 |
417 | __ASM volatile ("ror %0, %0, %1" : "+r" (op1) : "r" (op2) );
418 | return(op1);
419 | }
420 |
421 |
422 | #if (__CORTEX_M >= 0x03)
423 |
424 | /** \brief Reverse bit order of value
425 |
426 | This function reverses the bit order of the given value.
427 |
428 | \param [in] value Value to reverse
429 | \return Reversed value
430 | */
431 | __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __RBIT(uint32_t value)
432 | {
433 | uint32_t result;
434 |
435 | __ASM volatile ("rbit %0, %1" : "=r" (result) : "r" (value) );
436 | return(result);
437 | }
438 |
439 |
440 | /** \brief LDR Exclusive (8 bit)
441 |
442 | This function performs a exclusive LDR command for 8 bit value.
443 |
444 | \param [in] ptr Pointer to data
445 | \return value of type uint8_t at (*ptr)
446 | */
447 | __attribute__( ( always_inline ) ) __STATIC_INLINE uint8_t __LDREXB(volatile uint8_t *addr)
448 | {
449 | uint8_t result;
450 |
451 | __ASM volatile ("ldrexb %0, [%1]" : "=r" (result) : "r" (addr) );
452 | return(result);
453 | }
454 |
455 |
456 | /** \brief LDR Exclusive (16 bit)
457 |
458 | This function performs a exclusive LDR command for 16 bit values.
459 |
460 | \param [in] ptr Pointer to data
461 | \return value of type uint16_t at (*ptr)
462 | */
463 | __attribute__( ( always_inline ) ) __STATIC_INLINE uint16_t __LDREXH(volatile uint16_t *addr)
464 | {
465 | uint16_t result;
466 |
467 | __ASM volatile ("ldrexh %0, [%1]" : "=r" (result) : "r" (addr) );
468 | return(result);
469 | }
470 |
471 |
472 | /** \brief LDR Exclusive (32 bit)
473 |
474 | This function performs a exclusive LDR command for 32 bit values.
475 |
476 | \param [in] ptr Pointer to data
477 | \return value of type uint32_t at (*ptr)
478 | */
479 | __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __LDREXW(volatile uint32_t *addr)
480 | {
481 | uint32_t result;
482 |
483 | __ASM volatile ("ldrex %0, [%1]" : "=r" (result) : "r" (addr) );
484 | return(result);
485 | }
486 |
487 |
488 | /** \brief STR Exclusive (8 bit)
489 |
490 | This function performs a exclusive STR command for 8 bit values.
491 |
492 | \param [in] value Value to store
493 | \param [in] ptr Pointer to location
494 | \return 0 Function succeeded
495 | \return 1 Function failed
496 | */
497 | __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __STREXB(uint8_t value, volatile uint8_t *addr)
498 | {
499 | uint32_t result;
500 |
501 | __ASM volatile ("strexb %0, %2, [%1]" : "=&r" (result) : "r" (addr), "r" (value) );
502 | return(result);
503 | }
504 |
505 |
506 | /** \brief STR Exclusive (16 bit)
507 |
508 | This function performs a exclusive STR command for 16 bit values.
509 |
510 | \param [in] value Value to store
511 | \param [in] ptr Pointer to location
512 | \return 0 Function succeeded
513 | \return 1 Function failed
514 | */
515 | __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __STREXH(uint16_t value, volatile uint16_t *addr)
516 | {
517 | uint32_t result;
518 |
519 | __ASM volatile ("strexh %0, %2, [%1]" : "=&r" (result) : "r" (addr), "r" (value) );
520 | return(result);
521 | }
522 |
523 |
524 | /** \brief STR Exclusive (32 bit)
525 |
526 | This function performs a exclusive STR command for 32 bit values.
527 |
528 | \param [in] value Value to store
529 | \param [in] ptr Pointer to location
530 | \return 0 Function succeeded
531 | \return 1 Function failed
532 | */
533 | __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __STREXW(uint32_t value, volatile uint32_t *addr)
534 | {
535 | uint32_t result;
536 |
537 | __ASM volatile ("strex %0, %2, [%1]" : "=&r" (result) : "r" (addr), "r" (value) );
538 | return(result);
539 | }
540 |
541 |
542 | /** \brief Remove the exclusive lock
543 |
544 | This function removes the exclusive lock which is created by LDREX.
545 |
546 | */
547 | __attribute__( ( always_inline ) ) __STATIC_INLINE void __CLREX(void)
548 | {
549 | __ASM volatile ("clrex");
550 | }
551 |
552 |
553 | /** \brief Signed Saturate
554 |
555 | This function saturates a signed value.
556 |
557 | \param [in] value Value to be saturated
558 | \param [in] sat Bit position to saturate to (1..32)
559 | \return Saturated value
560 | */
561 | #define __SSAT(ARG1,ARG2) \
562 | ({ \
563 | uint32_t __RES, __ARG1 = (ARG1); \
564 | __ASM ("ssat %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \
565 | __RES; \
566 | })
567 |
568 |
569 | /** \brief Unsigned Saturate
570 |
571 | This function saturates an unsigned value.
572 |
573 | \param [in] value Value to be saturated
574 | \param [in] sat Bit position to saturate to (0..31)
575 | \return Saturated value
576 | */
577 | #define __USAT(ARG1,ARG2) \
578 | ({ \
579 | uint32_t __RES, __ARG1 = (ARG1); \
580 | __ASM ("usat %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \
581 | __RES; \
582 | })
583 |
584 |
585 | /** \brief Count leading zeros
586 |
587 | This function counts the number of leading zeros of a data value.
588 |
589 | \param [in] value Value to count the leading zeros
590 | \return number of leading zeros in value
591 | */
592 | __attribute__( ( always_inline ) ) __STATIC_INLINE uint8_t __CLZ(uint32_t value)
593 | {
594 | uint8_t result;
595 |
596 | __ASM volatile ("clz %0, %1" : "=r" (result) : "r" (value) );
597 | return(result);
598 | }
599 |
600 | #endif /* (__CORTEX_M >= 0x03) */
601 |
602 |
603 |
604 |
605 | #elif defined ( __TASKING__ ) /*------------------ TASKING Compiler --------------*/
606 | /* TASKING carm specific functions */
607 |
608 | /*
609 | * The CMSIS functions have been implemented as intrinsics in the compiler.
610 | * Please use "carm -?i" to get an up to date list of all intrinsics,
611 | * Including the CMSIS ones.
612 | */
613 |
614 | #endif
615 |
616 | /*@}*/ /* end of group CMSIS_Core_InstructionInterface */
617 |
618 | #endif /* __CORE_CMINSTR_H */
619 |
--------------------------------------------------------------------------------
/ramdump-firmware/cmsis/core_cm0.h:
--------------------------------------------------------------------------------
1 | /**************************************************************************//**
2 | * @file core_cm0.h
3 | * @brief CMSIS Cortex-M0 Core Peripheral Access Layer Header File
4 | * @version V3.01
5 | * @date 13. March 2012
6 | *
7 | * @note
8 | * Copyright (C) 2009-2012 ARM Limited. All rights reserved.
9 | *
10 | * @par
11 | * ARM Limited (ARM) is supplying this software for use with Cortex-M
12 | * processor based microcontrollers. This file can be freely distributed
13 | * within development tools that are supporting such ARM based processors.
14 | *
15 | * @par
16 | * THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED
17 | * OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
18 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
19 | * ARM SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR
20 | * CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
21 | *
22 | ******************************************************************************/
23 | #if defined ( __ICCARM__ )
24 | #pragma system_include /* treat file as system include file for MISRA check */
25 | #endif
26 |
27 | #ifdef __cplusplus
28 | extern "C" {
29 | #endif
30 |
31 | #ifndef __CORE_CM0_H_GENERIC
32 | #define __CORE_CM0_H_GENERIC
33 |
34 | /** \page CMSIS_MISRA_Exceptions MISRA-C:2004 Compliance Exceptions
35 | CMSIS violates the following MISRA-C:2004 rules:
36 |
37 | \li Required Rule 8.5, object/function definition in header file.
38 | Function definitions in header files are used to allow 'inlining'.
39 |
40 | \li Required Rule 18.4, declaration of union type or object of union type: '{...}'.
41 | Unions are used for effective representation of core registers.
42 |
43 | \li Advisory Rule 19.7, Function-like macro defined.
44 | Function-like macros are used to allow more efficient code.
45 | */
46 |
47 |
48 | /*******************************************************************************
49 | * CMSIS definitions
50 | ******************************************************************************/
51 | /** \ingroup Cortex_M0
52 | @{
53 | */
54 |
55 | /* CMSIS CM0 definitions */
56 | #define __CM0_CMSIS_VERSION_MAIN (0x03) /*!< [31:16] CMSIS HAL main version */
57 | #define __CM0_CMSIS_VERSION_SUB (0x01) /*!< [15:0] CMSIS HAL sub version */
58 | #define __CM0_CMSIS_VERSION ((__CM0_CMSIS_VERSION_MAIN << 16) | \
59 | __CM0_CMSIS_VERSION_SUB ) /*!< CMSIS HAL version number */
60 |
61 | #define __CORTEX_M (0x00) /*!< Cortex-M Core */
62 |
63 |
64 | #if defined ( __CC_ARM )
65 | #define __ASM __asm /*!< asm keyword for ARM Compiler */
66 | #define __INLINE __inline /*!< inline keyword for ARM Compiler */
67 | #define __STATIC_INLINE static __inline
68 |
69 | #elif defined ( __ICCARM__ )
70 | #define __ASM __asm /*!< asm keyword for IAR Compiler */
71 | #define __INLINE inline /*!< inline keyword for IAR Compiler. Only available in High optimization mode! */
72 | #define __STATIC_INLINE static inline
73 |
74 | #elif defined ( __GNUC__ )
75 | #define __ASM __asm /*!< asm keyword for GNU Compiler */
76 | #define __INLINE inline /*!< inline keyword for GNU Compiler */
77 | #define __STATIC_INLINE static inline
78 |
79 | #elif defined ( __TASKING__ )
80 | #define __ASM __asm /*!< asm keyword for TASKING Compiler */
81 | #define __INLINE inline /*!< inline keyword for TASKING Compiler */
82 | #define __STATIC_INLINE static inline
83 |
84 | #endif
85 |
86 | /** __FPU_USED indicates whether an FPU is used or not. This core does not support an FPU at all
87 | */
88 | #define __FPU_USED 0
89 |
90 | #if defined ( __CC_ARM )
91 | #if defined __TARGET_FPU_VFP
92 | #warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
93 | #endif
94 |
95 | #elif defined ( __ICCARM__ )
96 | #if defined __ARMVFP__
97 | #warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
98 | #endif
99 |
100 | #elif defined ( __GNUC__ )
101 | #if defined (__VFP_FP__) && !defined(__SOFTFP__)
102 | #warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
103 | #endif
104 |
105 | #elif defined ( __TASKING__ )
106 | #if defined __FPU_VFP__
107 | #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
108 | #endif
109 | #endif
110 |
111 | #include /* standard types definitions */
112 | #include /* Core Instruction Access */
113 | #include /* Core Function Access */
114 |
115 | #endif /* __CORE_CM0_H_GENERIC */
116 |
117 | #ifndef __CMSIS_GENERIC
118 |
119 | #ifndef __CORE_CM0_H_DEPENDANT
120 | #define __CORE_CM0_H_DEPENDANT
121 |
122 | /* check device defines and use defaults */
123 | #if defined __CHECK_DEVICE_DEFINES
124 | #ifndef __CM0_REV
125 | #define __CM0_REV 0x0000
126 | #warning "__CM0_REV not defined in device header file; using default!"
127 | #endif
128 |
129 | #ifndef __NVIC_PRIO_BITS
130 | #define __NVIC_PRIO_BITS 2
131 | #warning "__NVIC_PRIO_BITS not defined in device header file; using default!"
132 | #endif
133 |
134 | #ifndef __Vendor_SysTickConfig
135 | #define __Vendor_SysTickConfig 0
136 | #warning "__Vendor_SysTickConfig not defined in device header file; using default!"
137 | #endif
138 | #endif
139 |
140 | /* IO definitions (access restrictions to peripheral registers) */
141 | /**
142 | \defgroup CMSIS_glob_defs CMSIS Global Defines
143 |
144 | IO Type Qualifiers are used
145 | \li to specify the access to peripheral variables.
146 | \li for automatic generation of peripheral register debug information.
147 | */
148 | #ifdef __cplusplus
149 | #define __I volatile /*!< Defines 'read only' permissions */
150 | #else
151 | #define __I volatile const /*!< Defines 'read only' permissions */
152 | #endif
153 | #define __O volatile /*!< Defines 'write only' permissions */
154 | #define __IO volatile /*!< Defines 'read / write' permissions */
155 |
156 | /*@} end of group Cortex_M0 */
157 |
158 |
159 |
160 | /*******************************************************************************
161 | * Register Abstraction
162 | Core Register contain:
163 | - Core Register
164 | - Core NVIC Register
165 | - Core SCB Register
166 | - Core SysTick Register
167 | ******************************************************************************/
168 | /** \defgroup CMSIS_core_register Defines and Type Definitions
169 | \brief Type definitions and defines for Cortex-M processor based devices.
170 | */
171 |
172 | /** \ingroup CMSIS_core_register
173 | \defgroup CMSIS_CORE Status and Control Registers
174 | \brief Core Register type definitions.
175 | @{
176 | */
177 |
178 | /** \brief Union type to access the Application Program Status Register (APSR).
179 | */
180 | typedef union
181 | {
182 | struct
183 | {
184 | #if (__CORTEX_M != 0x04)
185 | uint32_t _reserved0:27; /*!< bit: 0..26 Reserved */
186 | #else
187 | uint32_t _reserved0:16; /*!< bit: 0..15 Reserved */
188 | uint32_t GE:4; /*!< bit: 16..19 Greater than or Equal flags */
189 | uint32_t _reserved1:7; /*!< bit: 20..26 Reserved */
190 | #endif
191 | uint32_t Q:1; /*!< bit: 27 Saturation condition flag */
192 | uint32_t V:1; /*!< bit: 28 Overflow condition code flag */
193 | uint32_t C:1; /*!< bit: 29 Carry condition code flag */
194 | uint32_t Z:1; /*!< bit: 30 Zero condition code flag */
195 | uint32_t N:1; /*!< bit: 31 Negative condition code flag */
196 | } b; /*!< Structure used for bit access */
197 | uint32_t w; /*!< Type used for word access */
198 | } APSR_Type;
199 |
200 |
201 | /** \brief Union type to access the Interrupt Program Status Register (IPSR).
202 | */
203 | typedef union
204 | {
205 | struct
206 | {
207 | uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */
208 | uint32_t _reserved0:23; /*!< bit: 9..31 Reserved */
209 | } b; /*!< Structure used for bit access */
210 | uint32_t w; /*!< Type used for word access */
211 | } IPSR_Type;
212 |
213 |
214 | /** \brief Union type to access the Special-Purpose Program Status Registers (xPSR).
215 | */
216 | typedef union
217 | {
218 | struct
219 | {
220 | uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */
221 | #if (__CORTEX_M != 0x04)
222 | uint32_t _reserved0:15; /*!< bit: 9..23 Reserved */
223 | #else
224 | uint32_t _reserved0:7; /*!< bit: 9..15 Reserved */
225 | uint32_t GE:4; /*!< bit: 16..19 Greater than or Equal flags */
226 | uint32_t _reserved1:4; /*!< bit: 20..23 Reserved */
227 | #endif
228 | uint32_t T:1; /*!< bit: 24 Thumb bit (read 0) */
229 | uint32_t IT:2; /*!< bit: 25..26 saved IT state (read 0) */
230 | uint32_t Q:1; /*!< bit: 27 Saturation condition flag */
231 | uint32_t V:1; /*!< bit: 28 Overflow condition code flag */
232 | uint32_t C:1; /*!< bit: 29 Carry condition code flag */
233 | uint32_t Z:1; /*!< bit: 30 Zero condition code flag */
234 | uint32_t N:1; /*!< bit: 31 Negative condition code flag */
235 | } b; /*!< Structure used for bit access */
236 | uint32_t w; /*!< Type used for word access */
237 | } xPSR_Type;
238 |
239 |
240 | /** \brief Union type to access the Control Registers (CONTROL).
241 | */
242 | typedef union
243 | {
244 | struct
245 | {
246 | uint32_t nPRIV:1; /*!< bit: 0 Execution privilege in Thread mode */
247 | uint32_t SPSEL:1; /*!< bit: 1 Stack to be used */
248 | uint32_t FPCA:1; /*!< bit: 2 FP extension active flag */
249 | uint32_t _reserved0:29; /*!< bit: 3..31 Reserved */
250 | } b; /*!< Structure used for bit access */
251 | uint32_t w; /*!< Type used for word access */
252 | } CONTROL_Type;
253 |
254 | /*@} end of group CMSIS_CORE */
255 |
256 |
257 | /** \ingroup CMSIS_core_register
258 | \defgroup CMSIS_NVIC Nested Vectored Interrupt Controller (NVIC)
259 | \brief Type definitions for the NVIC Registers
260 | @{
261 | */
262 |
263 | /** \brief Structure type to access the Nested Vectored Interrupt Controller (NVIC).
264 | */
265 | typedef struct
266 | {
267 | __IO uint32_t ISER[1]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */
268 | uint32_t RESERVED0[31];
269 | __IO uint32_t ICER[1]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */
270 | uint32_t RSERVED1[31];
271 | __IO uint32_t ISPR[1]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */
272 | uint32_t RESERVED2[31];
273 | __IO uint32_t ICPR[1]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */
274 | uint32_t RESERVED3[31];
275 | uint32_t RESERVED4[64];
276 | __IO uint32_t IP[8]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register */
277 | } NVIC_Type;
278 |
279 | /*@} end of group CMSIS_NVIC */
280 |
281 |
282 | /** \ingroup CMSIS_core_register
283 | \defgroup CMSIS_SCB System Control Block (SCB)
284 | \brief Type definitions for the System Control Block Registers
285 | @{
286 | */
287 |
288 | /** \brief Structure type to access the System Control Block (SCB).
289 | */
290 | typedef struct
291 | {
292 | __I uint32_t CPUID; /*!< Offset: 0x000 (R/ ) CPUID Base Register */
293 | __IO uint32_t ICSR; /*!< Offset: 0x004 (R/W) Interrupt Control and State Register */
294 | uint32_t RESERVED0;
295 | __IO uint32_t AIRCR; /*!< Offset: 0x00C (R/W) Application Interrupt and Reset Control Register */
296 | __IO uint32_t SCR; /*!< Offset: 0x010 (R/W) System Control Register */
297 | __IO uint32_t CCR; /*!< Offset: 0x014 (R/W) Configuration Control Register */
298 | uint32_t RESERVED1;
299 | __IO uint32_t SHP[2]; /*!< Offset: 0x01C (R/W) System Handlers Priority Registers. [0] is RESERVED */
300 | __IO uint32_t SHCSR; /*!< Offset: 0x024 (R/W) System Handler Control and State Register */
301 | } SCB_Type;
302 |
303 | /* SCB CPUID Register Definitions */
304 | #define SCB_CPUID_IMPLEMENTER_Pos 24 /*!< SCB CPUID: IMPLEMENTER Position */
305 | #define SCB_CPUID_IMPLEMENTER_Msk (0xFFUL << SCB_CPUID_IMPLEMENTER_Pos) /*!< SCB CPUID: IMPLEMENTER Mask */
306 |
307 | #define SCB_CPUID_VARIANT_Pos 20 /*!< SCB CPUID: VARIANT Position */
308 | #define SCB_CPUID_VARIANT_Msk (0xFUL << SCB_CPUID_VARIANT_Pos) /*!< SCB CPUID: VARIANT Mask */
309 |
310 | #define SCB_CPUID_ARCHITECTURE_Pos 16 /*!< SCB CPUID: ARCHITECTURE Position */
311 | #define SCB_CPUID_ARCHITECTURE_Msk (0xFUL << SCB_CPUID_ARCHITECTURE_Pos) /*!< SCB CPUID: ARCHITECTURE Mask */
312 |
313 | #define SCB_CPUID_PARTNO_Pos 4 /*!< SCB CPUID: PARTNO Position */
314 | #define SCB_CPUID_PARTNO_Msk (0xFFFUL << SCB_CPUID_PARTNO_Pos) /*!< SCB CPUID: PARTNO Mask */
315 |
316 | #define SCB_CPUID_REVISION_Pos 0 /*!< SCB CPUID: REVISION Position */
317 | #define SCB_CPUID_REVISION_Msk (0xFUL << SCB_CPUID_REVISION_Pos) /*!< SCB CPUID: REVISION Mask */
318 |
319 | /* SCB Interrupt Control State Register Definitions */
320 | #define SCB_ICSR_NMIPENDSET_Pos 31 /*!< SCB ICSR: NMIPENDSET Position */
321 | #define SCB_ICSR_NMIPENDSET_Msk (1UL << SCB_ICSR_NMIPENDSET_Pos) /*!< SCB ICSR: NMIPENDSET Mask */
322 |
323 | #define SCB_ICSR_PENDSVSET_Pos 28 /*!< SCB ICSR: PENDSVSET Position */
324 | #define SCB_ICSR_PENDSVSET_Msk (1UL << SCB_ICSR_PENDSVSET_Pos) /*!< SCB ICSR: PENDSVSET Mask */
325 |
326 | #define SCB_ICSR_PENDSVCLR_Pos 27 /*!< SCB ICSR: PENDSVCLR Position */
327 | #define SCB_ICSR_PENDSVCLR_Msk (1UL << SCB_ICSR_PENDSVCLR_Pos) /*!< SCB ICSR: PENDSVCLR Mask */
328 |
329 | #define SCB_ICSR_PENDSTSET_Pos 26 /*!< SCB ICSR: PENDSTSET Position */
330 | #define SCB_ICSR_PENDSTSET_Msk (1UL << SCB_ICSR_PENDSTSET_Pos) /*!< SCB ICSR: PENDSTSET Mask */
331 |
332 | #define SCB_ICSR_PENDSTCLR_Pos 25 /*!< SCB ICSR: PENDSTCLR Position */
333 | #define SCB_ICSR_PENDSTCLR_Msk (1UL << SCB_ICSR_PENDSTCLR_Pos) /*!< SCB ICSR: PENDSTCLR Mask */
334 |
335 | #define SCB_ICSR_ISRPREEMPT_Pos 23 /*!< SCB ICSR: ISRPREEMPT Position */
336 | #define SCB_ICSR_ISRPREEMPT_Msk (1UL << SCB_ICSR_ISRPREEMPT_Pos) /*!< SCB ICSR: ISRPREEMPT Mask */
337 |
338 | #define SCB_ICSR_ISRPENDING_Pos 22 /*!< SCB ICSR: ISRPENDING Position */
339 | #define SCB_ICSR_ISRPENDING_Msk (1UL << SCB_ICSR_ISRPENDING_Pos) /*!< SCB ICSR: ISRPENDING Mask */
340 |
341 | #define SCB_ICSR_VECTPENDING_Pos 12 /*!< SCB ICSR: VECTPENDING Position */
342 | #define SCB_ICSR_VECTPENDING_Msk (0x1FFUL << SCB_ICSR_VECTPENDING_Pos) /*!< SCB ICSR: VECTPENDING Mask */
343 |
344 | #define SCB_ICSR_VECTACTIVE_Pos 0 /*!< SCB ICSR: VECTACTIVE Position */
345 | #define SCB_ICSR_VECTACTIVE_Msk (0x1FFUL << SCB_ICSR_VECTACTIVE_Pos) /*!< SCB ICSR: VECTACTIVE Mask */
346 |
347 | /* SCB Application Interrupt and Reset Control Register Definitions */
348 | #define SCB_AIRCR_VECTKEY_Pos 16 /*!< SCB AIRCR: VECTKEY Position */
349 | #define SCB_AIRCR_VECTKEY_Msk (0xFFFFUL << SCB_AIRCR_VECTKEY_Pos) /*!< SCB AIRCR: VECTKEY Mask */
350 |
351 | #define SCB_AIRCR_VECTKEYSTAT_Pos 16 /*!< SCB AIRCR: VECTKEYSTAT Position */
352 | #define SCB_AIRCR_VECTKEYSTAT_Msk (0xFFFFUL << SCB_AIRCR_VECTKEYSTAT_Pos) /*!< SCB AIRCR: VECTKEYSTAT Mask */
353 |
354 | #define SCB_AIRCR_ENDIANESS_Pos 15 /*!< SCB AIRCR: ENDIANESS Position */
355 | #define SCB_AIRCR_ENDIANESS_Msk (1UL << SCB_AIRCR_ENDIANESS_Pos) /*!< SCB AIRCR: ENDIANESS Mask */
356 |
357 | #define SCB_AIRCR_SYSRESETREQ_Pos 2 /*!< SCB AIRCR: SYSRESETREQ Position */
358 | #define SCB_AIRCR_SYSRESETREQ_Msk (1UL << SCB_AIRCR_SYSRESETREQ_Pos) /*!< SCB AIRCR: SYSRESETREQ Mask */
359 |
360 | #define SCB_AIRCR_VECTCLRACTIVE_Pos 1 /*!< SCB AIRCR: VECTCLRACTIVE Position */
361 | #define SCB_AIRCR_VECTCLRACTIVE_Msk (1UL << SCB_AIRCR_VECTCLRACTIVE_Pos) /*!< SCB AIRCR: VECTCLRACTIVE Mask */
362 |
363 | /* SCB System Control Register Definitions */
364 | #define SCB_SCR_SEVONPEND_Pos 4 /*!< SCB SCR: SEVONPEND Position */
365 | #define SCB_SCR_SEVONPEND_Msk (1UL << SCB_SCR_SEVONPEND_Pos) /*!< SCB SCR: SEVONPEND Mask */
366 |
367 | #define SCB_SCR_SLEEPDEEP_Pos 2 /*!< SCB SCR: SLEEPDEEP Position */
368 | #define SCB_SCR_SLEEPDEEP_Msk (1UL << SCB_SCR_SLEEPDEEP_Pos) /*!< SCB SCR: SLEEPDEEP Mask */
369 |
370 | #define SCB_SCR_SLEEPONEXIT_Pos 1 /*!< SCB SCR: SLEEPONEXIT Position */
371 | #define SCB_SCR_SLEEPONEXIT_Msk (1UL << SCB_SCR_SLEEPONEXIT_Pos) /*!< SCB SCR: SLEEPONEXIT Mask */
372 |
373 | /* SCB Configuration Control Register Definitions */
374 | #define SCB_CCR_STKALIGN_Pos 9 /*!< SCB CCR: STKALIGN Position */
375 | #define SCB_CCR_STKALIGN_Msk (1UL << SCB_CCR_STKALIGN_Pos) /*!< SCB CCR: STKALIGN Mask */
376 |
377 | #define SCB_CCR_UNALIGN_TRP_Pos 3 /*!< SCB CCR: UNALIGN_TRP Position */
378 | #define SCB_CCR_UNALIGN_TRP_Msk (1UL << SCB_CCR_UNALIGN_TRP_Pos) /*!< SCB CCR: UNALIGN_TRP Mask */
379 |
380 | /* SCB System Handler Control and State Register Definitions */
381 | #define SCB_SHCSR_SVCALLPENDED_Pos 15 /*!< SCB SHCSR: SVCALLPENDED Position */
382 | #define SCB_SHCSR_SVCALLPENDED_Msk (1UL << SCB_SHCSR_SVCALLPENDED_Pos) /*!< SCB SHCSR: SVCALLPENDED Mask */
383 |
384 | /*@} end of group CMSIS_SCB */
385 |
386 |
387 | /** \ingroup CMSIS_core_register
388 | \defgroup CMSIS_SysTick System Tick Timer (SysTick)
389 | \brief Type definitions for the System Timer Registers.
390 | @{
391 | */
392 |
393 | /** \brief Structure type to access the System Timer (SysTick).
394 | */
395 | typedef struct
396 | {
397 | __IO uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */
398 | __IO uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */
399 | __IO uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */
400 | __I uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */
401 | } SysTick_Type;
402 |
403 | /* SysTick Control / Status Register Definitions */
404 | #define SysTick_CTRL_COUNTFLAG_Pos 16 /*!< SysTick CTRL: COUNTFLAG Position */
405 | #define SysTick_CTRL_COUNTFLAG_Msk (1UL << SysTick_CTRL_COUNTFLAG_Pos) /*!< SysTick CTRL: COUNTFLAG Mask */
406 |
407 | #define SysTick_CTRL_CLKSOURCE_Pos 2 /*!< SysTick CTRL: CLKSOURCE Position */
408 | #define SysTick_CTRL_CLKSOURCE_Msk (1UL << SysTick_CTRL_CLKSOURCE_Pos) /*!< SysTick CTRL: CLKSOURCE Mask */
409 |
410 | #define SysTick_CTRL_TICKINT_Pos 1 /*!< SysTick CTRL: TICKINT Position */
411 | #define SysTick_CTRL_TICKINT_Msk (1UL << SysTick_CTRL_TICKINT_Pos) /*!< SysTick CTRL: TICKINT Mask */
412 |
413 | #define SysTick_CTRL_ENABLE_Pos 0 /*!< SysTick CTRL: ENABLE Position */
414 | #define SysTick_CTRL_ENABLE_Msk (1UL << SysTick_CTRL_ENABLE_Pos) /*!< SysTick CTRL: ENABLE Mask */
415 |
416 | /* SysTick Reload Register Definitions */
417 | #define SysTick_LOAD_RELOAD_Pos 0 /*!< SysTick LOAD: RELOAD Position */
418 | #define SysTick_LOAD_RELOAD_Msk (0xFFFFFFUL << SysTick_LOAD_RELOAD_Pos) /*!< SysTick LOAD: RELOAD Mask */
419 |
420 | /* SysTick Current Register Definitions */
421 | #define SysTick_VAL_CURRENT_Pos 0 /*!< SysTick VAL: CURRENT Position */
422 | #define SysTick_VAL_CURRENT_Msk (0xFFFFFFUL << SysTick_VAL_CURRENT_Pos) /*!< SysTick VAL: CURRENT Mask */
423 |
424 | /* SysTick Calibration Register Definitions */
425 | #define SysTick_CALIB_NOREF_Pos 31 /*!< SysTick CALIB: NOREF Position */
426 | #define SysTick_CALIB_NOREF_Msk (1UL << SysTick_CALIB_NOREF_Pos) /*!< SysTick CALIB: NOREF Mask */
427 |
428 | #define SysTick_CALIB_SKEW_Pos 30 /*!< SysTick CALIB: SKEW Position */
429 | #define SysTick_CALIB_SKEW_Msk (1UL << SysTick_CALIB_SKEW_Pos) /*!< SysTick CALIB: SKEW Mask */
430 |
431 | #define SysTick_CALIB_TENMS_Pos 0 /*!< SysTick CALIB: TENMS Position */
432 | #define SysTick_CALIB_TENMS_Msk (0xFFFFFFUL << SysTick_VAL_CURRENT_Pos) /*!< SysTick CALIB: TENMS Mask */
433 |
434 | /*@} end of group CMSIS_SysTick */
435 |
436 |
437 | /** \ingroup CMSIS_core_register
438 | \defgroup CMSIS_CoreDebug Core Debug Registers (CoreDebug)
439 | \brief Cortex-M0 Core Debug Registers (DCB registers, SHCSR, and DFSR)
440 | are only accessible over DAP and not via processor. Therefore
441 | they are not covered by the Cortex-M0 header file.
442 | @{
443 | */
444 | /*@} end of group CMSIS_CoreDebug */
445 |
446 |
447 | /** \ingroup CMSIS_core_register
448 | \defgroup CMSIS_core_base Core Definitions
449 | \brief Definitions for base addresses, unions, and structures.
450 | @{
451 | */
452 |
453 | /* Memory mapping of Cortex-M0 Hardware */
454 | #define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */
455 | #define SysTick_BASE (SCS_BASE + 0x0010UL) /*!< SysTick Base Address */
456 | #define NVIC_BASE (SCS_BASE + 0x0100UL) /*!< NVIC Base Address */
457 | #define SCB_BASE (SCS_BASE + 0x0D00UL) /*!< System Control Block Base Address */
458 |
459 | #define SCB ((SCB_Type *) SCB_BASE ) /*!< SCB configuration struct */
460 | #define SysTick ((SysTick_Type *) SysTick_BASE ) /*!< SysTick configuration struct */
461 | #define NVIC ((NVIC_Type *) NVIC_BASE ) /*!< NVIC configuration struct */
462 |
463 |
464 | /*@} */
465 |
466 |
467 |
468 | /*******************************************************************************
469 | * Hardware Abstraction Layer
470 | Core Function Interface contains:
471 | - Core NVIC Functions
472 | - Core SysTick Functions
473 | - Core Register Access Functions
474 | ******************************************************************************/
475 | /** \defgroup CMSIS_Core_FunctionInterface Functions and Instructions Reference
476 | */
477 |
478 |
479 |
480 | /* ########################## NVIC functions #################################### */
481 | /** \ingroup CMSIS_Core_FunctionInterface
482 | \defgroup CMSIS_Core_NVICFunctions NVIC Functions
483 | \brief Functions that manage interrupts and exceptions via the NVIC.
484 | @{
485 | */
486 |
487 | /* Interrupt Priorities are WORD accessible only under ARMv6M */
488 | /* The following MACROS handle generation of the register offset and byte masks */
489 | #define _BIT_SHIFT(IRQn) ( (((uint32_t)(IRQn) ) & 0x03) * 8 )
490 | #define _SHP_IDX(IRQn) ( ((((uint32_t)(IRQn) & 0x0F)-8) >> 2) )
491 | #define _IP_IDX(IRQn) ( ((uint32_t)(IRQn) >> 2) )
492 |
493 |
494 | /** \brief Enable External Interrupt
495 |
496 | The function enables a device-specific interrupt in the NVIC interrupt controller.
497 |
498 | \param [in] IRQn External interrupt number. Value cannot be negative.
499 | */
500 | __STATIC_INLINE void NVIC_EnableIRQ(IRQn_Type IRQn)
501 | {
502 | NVIC->ISER[0] = (1 << ((uint32_t)(IRQn) & 0x1F));
503 | }
504 |
505 |
506 | /** \brief Disable External Interrupt
507 |
508 | The function disables a device-specific interrupt in the NVIC interrupt controller.
509 |
510 | \param [in] IRQn External interrupt number. Value cannot be negative.
511 | */
512 | __STATIC_INLINE void NVIC_DisableIRQ(IRQn_Type IRQn)
513 | {
514 | NVIC->ICER[0] = (1 << ((uint32_t)(IRQn) & 0x1F));
515 | }
516 |
517 |
518 | /** \brief Get Pending Interrupt
519 |
520 | The function reads the pending register in the NVIC and returns the pending bit
521 | for the specified interrupt.
522 |
523 | \param [in] IRQn Interrupt number.
524 |
525 | \return 0 Interrupt status is not pending.
526 | \return 1 Interrupt status is pending.
527 | */
528 | __STATIC_INLINE uint32_t NVIC_GetPendingIRQ(IRQn_Type IRQn)
529 | {
530 | return((uint32_t) ((NVIC->ISPR[0] & (1 << ((uint32_t)(IRQn) & 0x1F)))?1:0));
531 | }
532 |
533 |
534 | /** \brief Set Pending Interrupt
535 |
536 | The function sets the pending bit of an external interrupt.
537 |
538 | \param [in] IRQn Interrupt number. Value cannot be negative.
539 | */
540 | __STATIC_INLINE void NVIC_SetPendingIRQ(IRQn_Type IRQn)
541 | {
542 | NVIC->ISPR[0] = (1 << ((uint32_t)(IRQn) & 0x1F));
543 | }
544 |
545 |
546 | /** \brief Clear Pending Interrupt
547 |
548 | The function clears the pending bit of an external interrupt.
549 |
550 | \param [in] IRQn External interrupt number. Value cannot be negative.
551 | */
552 | __STATIC_INLINE void NVIC_ClearPendingIRQ(IRQn_Type IRQn)
553 | {
554 | NVIC->ICPR[0] = (1 << ((uint32_t)(IRQn) & 0x1F)); /* Clear pending interrupt */
555 | }
556 |
557 |
558 | /** \brief Set Interrupt Priority
559 |
560 | The function sets the priority of an interrupt.
561 |
562 | \note The priority cannot be set for every core interrupt.
563 |
564 | \param [in] IRQn Interrupt number.
565 | \param [in] priority Priority to set.
566 | */
567 | __STATIC_INLINE void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority)
568 | {
569 | if(IRQn < 0) {
570 | SCB->SHP[_SHP_IDX(IRQn)] = (SCB->SHP[_SHP_IDX(IRQn)] & ~(0xFF << _BIT_SHIFT(IRQn))) |
571 | (((priority << (8 - __NVIC_PRIO_BITS)) & 0xFF) << _BIT_SHIFT(IRQn)); }
572 | else {
573 | NVIC->IP[_IP_IDX(IRQn)] = (NVIC->IP[_IP_IDX(IRQn)] & ~(0xFF << _BIT_SHIFT(IRQn))) |
574 | (((priority << (8 - __NVIC_PRIO_BITS)) & 0xFF) << _BIT_SHIFT(IRQn)); }
575 | }
576 |
577 |
578 | /** \brief Get Interrupt Priority
579 |
580 | The function reads the priority of an interrupt. The interrupt
581 | number can be positive to specify an external (device specific)
582 | interrupt, or negative to specify an internal (core) interrupt.
583 |
584 |
585 | \param [in] IRQn Interrupt number.
586 | \return Interrupt Priority. Value is aligned automatically to the implemented
587 | priority bits of the microcontroller.
588 | */
589 | __STATIC_INLINE uint32_t NVIC_GetPriority(IRQn_Type IRQn)
590 | {
591 |
592 | if(IRQn < 0) {
593 | return((uint32_t)((SCB->SHP[_SHP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) >> (8 - __NVIC_PRIO_BITS))); } /* get priority for Cortex-M0 system interrupts */
594 | else {
595 | return((uint32_t)((NVIC->IP[ _IP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) >> (8 - __NVIC_PRIO_BITS))); } /* get priority for device specific interrupts */
596 | }
597 |
598 |
599 | /** \brief System Reset
600 |
601 | The function initiates a system reset request to reset the MCU.
602 | */
603 | __STATIC_INLINE void NVIC_SystemReset(void)
604 | {
605 | __DSB(); /* Ensure all outstanding memory accesses included
606 | buffered write are completed before reset */
607 | SCB->AIRCR = ((0x5FA << SCB_AIRCR_VECTKEY_Pos) |
608 | SCB_AIRCR_SYSRESETREQ_Msk);
609 | __DSB(); /* Ensure completion of memory access */
610 | while(1); /* wait until reset */
611 | }
612 |
613 | /*@} end of CMSIS_Core_NVICFunctions */
614 |
615 |
616 |
617 | /* ################################## SysTick function ############################################ */
618 | /** \ingroup CMSIS_Core_FunctionInterface
619 | \defgroup CMSIS_Core_SysTickFunctions SysTick Functions
620 | \brief Functions that configure the System.
621 | @{
622 | */
623 |
624 | #if (__Vendor_SysTickConfig == 0)
625 |
626 | /** \brief System Tick Configuration
627 |
628 | The function initializes the System Timer and its interrupt, and starts the System Tick Timer.
629 | Counter is in free running mode to generate periodic interrupts.
630 |
631 | \param [in] ticks Number of ticks between two interrupts.
632 |
633 | \return 0 Function succeeded.
634 | \return 1 Function failed.
635 |
636 | \note When the variable __Vendor_SysTickConfig is set to 1, then the
637 | function SysTick_Config is not included. In this case, the file device.h
638 | must contain a vendor-specific implementation of this function.
639 |
640 | */
641 | __STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks)
642 | {
643 | if (ticks > SysTick_LOAD_RELOAD_Msk) return (1); /* Reload value impossible */
644 |
645 | SysTick->LOAD = (ticks & SysTick_LOAD_RELOAD_Msk) - 1; /* set reload register */
646 | NVIC_SetPriority (SysTick_IRQn, (1<<__NVIC_PRIO_BITS) - 1); /* set Priority for Systick Interrupt */
647 | SysTick->VAL = 0; /* Load the SysTick Counter Value */
648 | SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk |
649 | SysTick_CTRL_TICKINT_Msk |
650 | SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */
651 | return (0); /* Function successful */
652 | }
653 |
654 | #endif
655 |
656 | /*@} end of CMSIS_Core_SysTickFunctions */
657 |
658 |
659 |
660 |
661 | #endif /* __CORE_CM0_H_DEPENDANT */
662 |
663 | #endif /* __CMSIS_GENERIC */
664 |
665 | #ifdef __cplusplus
666 | }
667 | #endif
668 |
--------------------------------------------------------------------------------
/ramdump-software/qn9022-ramdump/ramdump.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include
7 | #include "crc16-ccitt-algorithm.h"
8 |
9 | #ifdef __unix__
10 | #include
11 | #include
12 | #define Sleep(x) usleep(x*1000)
13 | #elif WIN32
14 | #include
15 | #else
16 | #define no sleep function
17 | #endif
18 |
19 | #define BOORLOADER_HEADCODE 0x71
20 |
21 | #define B_C_CMD 0x33
22 | #define SET_BR_CMD 0x34
23 | #define SET_FLASH_CLK_CMD 0x35
24 | #define RD_BL_VER_CMD 0x36
25 | #define RD_CHIP_ID_CMD 0x37
26 | #define RD_FLASH_ID_CMD 0x38
27 | #define SET_APP_LOC_CMD 0x39
28 | #define SETUP_FLASH_CMD 0x3A
29 | #define SET_ST_ADDR_CMD 0x3B
30 | #define SET_APP_SIZE_CMD 0x3C
31 | #define SET_APP_CRC_CMD 0x3E
32 | #define SET_APP_IN_FLASH_ADDR_CMD 0x40
33 | #define SE_FLASH_CMD 0x42
34 | #define BE_FLASH_CMD 0x43
35 | #define CE_FLASH_CMD 0x44
36 | #define PROGRAM_CMD 0x45
37 | #define RD_CMD 0x46
38 | #define VERIFY_CMD 0x47
39 | #define PROTECT_CMD 0x48
40 | #define RUN_APP_CMD 0x49
41 | #define REBOOT_CMD 0x4A
42 | #define WR_RANDOM_DATA_CMD 0x4B
43 | #define SET_APP_IN_RAM_ADDR_CMD 0x4C
44 | #define SET_APP_RESET_ADDR_CMD 0x4D
45 |
46 | #define BOOTLOADER_CONFIRM_OK 0x01
47 | #define BOOTLOADER_CONFIRM_FAIL 0x02
48 |
49 | #define BOOTLOADER_RESULT_SUCCESS 0x03
50 | #define BOOTLOADER_RESULT_FAIL 0x04
51 |
52 | #define APP_RESET_ADDRESS 0x10000000
53 | #define RAM_OFFSET 0x00000000
54 | #define FAILFALSE(x) if(!(x)){printf("Fail at line %d, error: %s (%s)\n", __LINE__, #x, strerror(errno)); return false;}
55 |
56 | typedef void* TRANSPORT;
57 |
58 | bool QN902x_bl_EnableProtection(TRANSPORT device);
59 | bool QN902x_bl_ReadBlVersion(TRANSPORT device, uint32_t *ver);
60 | bool QN902x_bl_ReadFlashId(TRANSPORT device, uint32_t *id);
61 | bool QN902x_bl_ReadChipId(TRANSPORT device, uint32_t *id);
62 | bool QN902x_bl_ReadNvds(TRANSPORT device, uint8_t *buffer, uint32_t size);
63 | bool QN902x_bl_SetAppResetAddress(TRANSPORT device, uint32_t addr);
64 | bool QN902x_bl_SetStartAddress(TRANSPORT device, uint32_t addr);
65 | bool QN902x_bl_SetAppInRamAddress(TRANSPORT device, uint32_t addr);
66 | bool QN902x_bl_SetBaudRate(TRANSPORT device, uint32_t baud);
67 | bool QN902x_bl_SetAppCrc(TRANSPORT device, uint32_t crc);
68 | bool QN902x_bl_SetAppSize(TRANSPORT device, uint32_t size);
69 | bool QN902x_bl_Verify(TRANSPORT device);
70 | bool QN902x_bl_RunApp(TRANSPORT device);
71 | bool QN902x_bl_Reboot(TRANSPORT device);
72 | bool QN902x_bl_ChipErase(TRANSPORT device);
73 | bool QN902x_bl_SetAppLocation(TRANSPORT device, bool shoudUseFlash);
74 | bool QN902x_bl_Program(TRANSPORT device, uint8_t *data, uint16_t size);
75 | bool QN902x_bl_SetupFlashCmd(TRANSPORT device, uint8_t commands[8]);
76 | bool QN902x_bl_WriteRandomData(TRANSPORT device, uint8_t commands[12]);
77 |
78 | bool QN902x_bl_command(TRANSPORT device, uint8_t command, uint32_t send_length, uint8_t *send, uint32_t *recv_length, uint8_t *recv, bool check_exe_result);
79 | bool QN902x_bl_InvokeBootloader(TRANSPORT device);
80 | uint16_t QN902x_bl_crc(size_t data_len, uint8_t *data);
81 |
82 | bool readout_binary(char *name, size_t *outsize, uint8_t **data);
83 |
84 | bool QN902x_subbl_RamLoadLaunchBinaryProtectFlash(TRANSPORT device, uint8_t * image, size_t image_sz);
85 | bool QN902x_subbl_NvdsDump(TRANSPORT device);
86 |
87 | bool QN902x_ramdump_Write(TRANSPORT device, uint32_t addr, uint32_t data);
88 | bool QN902x_ramdump_Read(TRANSPORT device, uint32_t addr, uint32_t read_bytes, uint8_t *buffer);
89 | bool QN902x_ramdump_ReadFlash(TRANSPORT device, uint32_t addr, uint32_t read_bytes, uint8_t * buffer);
90 | bool QN902x_ramdump_DumpRam(TRANSPORT device, uint32_t addr, uint32_t length, char *filename);
91 | bool QN902x_ramdump_DumpFlash(TRANSPORT device, uint32_t addr, uint32_t length, char* filename);
92 |
93 | bool Transport_OpenDevice(TRANSPORT *device, char *id);
94 | bool Transport_CloseDevice(TRANSPORT device);
95 | bool Transport_Recv(TRANSPORT device, uint8_t *buffer, uint32_t buffer_len);
96 | bool Transport_Send(TRANSPORT device, uint8_t *buffer, uint32_t buffer_len);
97 | bool Transport_Reset(TRANSPORT device);
98 | bool Transport_Unreset(TRANSPORT device);
99 | bool Transport_ReadLine(TRANSPORT device, char *buffer, uint32_t buffer_max);
100 | bool Transport_GetStats(TRANSPORT device, uint32_t *recv_quenue);
101 | bool Transport_SetBaudRate(TRANSPORT device, uint32_t baudrate);
102 |
103 | #define BAUD_RATE_115200 0x0000082c
104 | #define BAUD_RATE_9600 0x0000680b
105 |
106 | //#define LOG_EXCHANGE
107 |
108 | int main(int argc, char **argv)
109 | {
110 | TRANSPORT device;
111 |
112 | char binary[] = "loader.bin";
113 | char* device_id;
114 |
115 | FAILFALSE(argc > 1);
116 |
117 | device_id = argv[argc-1];
118 |
119 | FAILFALSE(Transport_OpenDevice(&device, device_id));
120 | printf("IO device initialized\n");
121 | bool loaded_success = false;
122 |
123 | size_t i;
124 | size_t loader_sz;
125 | uint8_t *loader;
126 | FAILFALSE(readout_binary(binary, &loader_sz, &loader));
127 | FAILFALSE(loader_sz < 0x1000);
128 | for (i = 0; i < 5; ++i)
129 | {
130 | if (QN902x_subbl_RamLoadLaunchBinaryProtectFlash(device, loader, loader_sz))
131 | {
132 | loaded_success = true;
133 | break;
134 | }
135 | }
136 | free(loader);
137 |
138 | if (!loaded_success)
139 | {
140 | printf("Error loading FW\n");
141 | }
142 | else
143 | {
144 | printf("Application loaded\n");
145 |
146 | //FAILFALSE(QN902x_ramdump_DumpRam(device, 0x10000000, 0x00010000, "ram_0.bin"));
147 | //FAILFALSE(QN902x_ramdump_DumpRam(device, 0x10000000, 0x00010000, "ram_1.bin"));
148 |
149 | //FAILFALSE(QN902x_ramdump_DumpRam(device, 0x00000000, 0x01000000, "BootLoader_0.bin"));
150 | //FAILFALSE(QN902x_ramdump_DumpRam(device, 0x00000000, 0x01000000, "BootLoader_1.bin"));
151 |
152 | FAILFALSE(QN902x_ramdump_DumpRam(device, 0x01000000, 0x00018000, "ROM_0.bin"));
153 | FAILFALSE(QN902x_ramdump_DumpRam(device, 0x01000000, 0x00018000, "ROM_1.bin"));
154 |
155 | FAILFALSE(QN902x_ramdump_DumpFlash(device, 0x00000000, 0x00020000, "flash_0.bin"));
156 | FAILFALSE(QN902x_ramdump_DumpFlash(device, 0x00000000, 0x00020000, "flash_1.bin"));
157 |
158 | }
159 |
160 | Transport_CloseDevice(device);
161 |
162 | return 0;
163 | }
164 |
165 | /* Subfunctions, using bootloader commands */
166 |
167 | bool QN902x_subbl_RamLoadLaunchBinaryProtectFlash(TRANSPORT device, uint8_t *image, size_t image_sz)
168 | {
169 | uint32_t loader_crc;
170 | uint8_t flash_command_set_no_erase[8] =
171 | {
172 | 0x05, //real: 0x05, Read Status Register
173 | 0x05, //real: 0x06, Write Enable
174 | 0x05, //real: 0x20, Sector Erase
175 | 0x05, //real: 0x52, Block Erase
176 | 0x05, //real: 0x60, Chip Erase
177 | 0xB9, //real: 0xB9, Deep Power Down
178 | 0xAB, //real: 0xAB, Release form Deep Power Down
179 | 0x01, //real: 0x01, reserved, the value is not 0x00 and 0xFF
180 | };
181 |
182 | uint8_t flash_command_set_original[8] =
183 | {
184 | 0x05, //real: 0x05, Read Status Register
185 | 0x06, //real: 0x06, Write Enable
186 | 0xDC, //real: 0x20, Sector Erase
187 | 0x4E, //real: 0x52, Block Erase
188 | 0x5C, //real: 0x60, Chip Erase
189 | 0xB9, //real: 0xB9, Deep Power Down
190 | 0xAB, //real: 0xAB, Release form Deep Power Down
191 | 0x01, //real: 0x01, reserved, the value is not 0x00 and 0xFF
192 | };
193 |
194 | loader_crc = QN902x_bl_crc(image_sz, image);
195 |
196 | FAILFALSE(QN902x_bl_InvokeBootloader(device)); //Build Connection
197 | printf("Bootloader mode entered\n");
198 |
199 | uint32_t bl_ver;
200 | FAILFALSE(QN902x_bl_ReadBlVersion(device, &bl_ver)); //Read BL Version
201 | printf("Bootloader version: %.8X\n", bl_ver);
202 |
203 | uint32_t chip_id;
204 | FAILFALSE(QN902x_bl_ReadChipId(device, &chip_id)); //Read Chip ID
205 | printf("Chip ID %.8X\n", chip_id);
206 |
207 | uint32_t flash_id;
208 | FAILFALSE(QN902x_bl_ReadFlashId(device, &flash_id)); //Read Flash ID
209 | printf("Flash ID %.8X\n", flash_id);
210 |
211 |
212 | FAILFALSE(QN902x_bl_SetupFlashCmd(device, flash_command_set_no_erase));
213 |
214 | FAILFALSE(QN902x_bl_SetBaudRate(device, BAUD_RATE_115200)); //Set UART Baudrate
215 | FAILFALSE(Transport_SetBaudRate(device, 115200));//for 16M crystal
216 |
217 |
218 | FAILFALSE(QN902x_bl_SetAppLocation(device, false)); //Set APP LOC(SRAM)
219 |
220 | FAILFALSE(QN902x_bl_SetStartAddress(device, RAM_OFFSET));//set start addr
221 |
222 | FAILFALSE(QN902x_bl_SetAppResetAddress(device, APP_RESET_ADDRESS));//set app reset addr
223 |
224 | FAILFALSE(QN902x_bl_SetAppInRamAddress(device, APP_RESET_ADDRESS));
225 |
226 | FAILFALSE(QN902x_bl_SetAppSize(device, image_sz));//set app size
227 |
228 | FAILFALSE(QN902x_bl_SetAppCrc(device, loader_crc));//set app crc
229 |
230 |
231 | uint16_t loaded = 0;
232 | uint16_t to_load;
233 | while (loaded < (uint16_t)image_sz)
234 | {
235 | if ((uint16_t)image_sz - loaded > 0x100)
236 | {
237 | to_load = 0x100;
238 | }
239 | else
240 | {
241 | to_load = (uint16_t)image_sz - loaded;
242 | }
243 |
244 | FAILFALSE(QN902x_bl_Program(device, image + loaded, to_load));//program
245 | loaded += to_load;
246 | }
247 |
248 | FAILFALSE(QN902x_bl_SetupFlashCmd(device, flash_command_set_original));
249 |
250 | FAILFALSE(QN902x_bl_Verify(device));//verify
251 |
252 | FAILFALSE(QN902x_bl_RunApp(device));//run
253 |
254 | return true;
255 | }
256 |
257 | bool QN902x_subbl_NvdsDump(TRANSPORT device)
258 | {
259 | //untested
260 | uint32_t addr = 0x00000000;
261 | FAILFALSE(QN902x_bl_SetStartAddress(device, addr));
262 | uint8_t readbuf[0x10];
263 | uint32_t readed_total = 0;
264 | while (QN902x_bl_ReadNvds(device, readbuf, sizeof(readbuf)) && readed_total < 0x1000)
265 | {
266 | printf("%.8X: ", addr);
267 | size_t i;
268 | for (i = 0; i < sizeof(readbuf); ++i)
269 | {
270 | printf("%.2hhX ", readbuf[i]);
271 | }
272 | printf("\n");
273 |
274 | addr += sizeof(readbuf);
275 | readed_total += sizeof(readbuf);
276 | }
277 | return true;
278 | }
279 |
280 | /* Direct bootloader commands */
281 |
282 | bool QN902x_bl_EnableProtection(TRANSPORT device)
283 | {
284 | FAILFALSE(QN902x_bl_command(device, PROTECT_CMD, 0, NULL, NULL, NULL, true));
285 |
286 | return true;
287 | }
288 |
289 | bool QN902x_bl_ReadBlVersion(TRANSPORT device, uint32_t *ver)
290 | {
291 | uint32_t recved = 4;
292 | FAILFALSE(QN902x_bl_command(device, RD_BL_VER_CMD, 0, NULL, &recved, (uint8_t*)ver, false));
293 | FAILFALSE(recved == 4);
294 |
295 | return true;
296 | }
297 |
298 | bool QN902x_bl_ReadChipId(TRANSPORT device, uint32_t*id)
299 | {
300 | uint32_t recved = 4;
301 | FAILFALSE(QN902x_bl_command(device, RD_CHIP_ID_CMD, 0, NULL, &recved, (uint8_t*)id, false));
302 | FAILFALSE(recved == 4);
303 |
304 | return true;
305 | }
306 |
307 | bool QN902x_bl_ReadFlashId(TRANSPORT device, uint32_t*id)
308 | {
309 | uint32_t recved = 4;
310 | FAILFALSE(QN902x_bl_command(device, RD_FLASH_ID_CMD, 0, NULL, &recved, (uint8_t*)id, false));
311 | FAILFALSE(recved == 4);
312 |
313 | return true;
314 | }
315 |
316 | bool QN902x_bl_ReadNvds(TRANSPORT device, uint8_t *buffer, uint32_t size)
317 | {
318 | uint32_t recved = size;
319 |
320 | FAILFALSE(QN902x_bl_command(device, RD_CMD, sizeof(size), (uint8_t*)&size, &recved, buffer, false));
321 | FAILFALSE(recved == size);
322 |
323 | return true;
324 | }
325 |
326 | bool QN902x_bl_SetAppInRamAddress(TRANSPORT device, uint32_t addr)
327 | {
328 | FAILFALSE(QN902x_bl_command(device, SET_APP_IN_RAM_ADDR_CMD, sizeof(addr), (uint8_t*)&addr, NULL, NULL, true));
329 |
330 | return true;
331 | }
332 |
333 | bool QN902x_bl_SetStartAddress(TRANSPORT device, uint32_t addr)
334 | {
335 | FAILFALSE(QN902x_bl_command(device, SET_ST_ADDR_CMD, sizeof(addr), (uint8_t*)&addr, NULL, NULL, false));
336 |
337 | return true;
338 | }
339 |
340 | bool QN902x_bl_SetAppResetAddress(TRANSPORT device, uint32_t addr)
341 | {
342 | FAILFALSE(QN902x_bl_command(device, SET_APP_RESET_ADDR_CMD, sizeof(addr), (uint8_t*)&addr, NULL, NULL, true));
343 |
344 | return true;
345 | }
346 |
347 | bool QN902x_bl_SetAppLocation(TRANSPORT device, bool shoudUseFlash)
348 | {
349 | uint32_t param = !!shoudUseFlash;
350 | FAILFALSE(QN902x_bl_command(device, SET_APP_LOC_CMD, sizeof(param), (uint8_t*)¶m, NULL, NULL, false));
351 |
352 | return true;
353 | }
354 |
355 | bool QN902x_bl_SetAppSize(TRANSPORT device, uint32_t size)
356 | {
357 | FAILFALSE(QN902x_bl_command(device, SET_APP_SIZE_CMD, sizeof(size), (uint8_t*)&size, NULL, NULL, true));
358 |
359 | return true;
360 | }
361 |
362 | bool QN902x_bl_SetAppCrc(TRANSPORT device, uint32_t crc)
363 | {
364 | FAILFALSE(QN902x_bl_command(device, SET_APP_CRC_CMD, sizeof(crc), (uint8_t*)&crc, NULL, NULL, true));
365 |
366 | return true;
367 | }
368 |
369 | bool QN902x_bl_SetBaudRate(TRANSPORT device, uint32_t baud)
370 | {
371 | FAILFALSE(QN902x_bl_command(device, SET_BR_CMD, sizeof(baud), (uint8_t*)&baud, NULL, NULL, false));
372 |
373 | return true;
374 | }
375 |
376 | bool QN902x_bl_Program(TRANSPORT device, uint8_t *data, uint16_t size)
377 | {
378 | FAILFALSE(QN902x_bl_command(device, PROGRAM_CMD, size, data, NULL, NULL, true));
379 |
380 | return true;
381 | }
382 |
383 | bool QN902x_bl_Verify(TRANSPORT device)
384 | {
385 | FAILFALSE(QN902x_bl_command(device, VERIFY_CMD, 0, NULL, NULL, NULL, true));
386 |
387 | return true;
388 | }
389 |
390 | bool QN902x_bl_RunApp(TRANSPORT device)
391 | {
392 | FAILFALSE(QN902x_bl_command(device, RUN_APP_CMD, 0, NULL, NULL, NULL, false));
393 |
394 | return true;
395 | }
396 |
397 | bool QN902x_bl_Reboot(TRANSPORT device)
398 | {
399 | FAILFALSE(QN902x_bl_command(device, REBOOT_CMD, 0, NULL, NULL, NULL, false));
400 |
401 | return true;
402 | }
403 |
404 | bool QN902x_bl_ChipErase(TRANSPORT device)
405 | {
406 | FAILFALSE(QN902x_bl_command(device, CE_FLASH_CMD, 0, NULL, NULL, NULL, true));
407 |
408 | return true;
409 | }
410 |
411 | bool QN902x_bl_SetupFlashCmd(TRANSPORT device, uint8_t commands[8])
412 | {
413 | FAILFALSE(QN902x_bl_command(device, SETUP_FLASH_CMD, 8, commands, NULL, NULL, true));
414 |
415 | return true;
416 | }
417 |
418 | bool QN902x_bl_WriteRandomData(TRANSPORT device, uint8_t commands[12])
419 | {
420 | FAILFALSE(QN902x_bl_command(device, WR_RANDOM_DATA_CMD, 12, commands, NULL, NULL, true));
421 |
422 | return true;
423 | }
424 |
425 | /* Utility functions for bootloader functions */
426 |
427 | bool QN902x_bl_InvokeBootloader(TRANSPORT device)
428 | {
429 | uint8_t invokebl[1];
430 |
431 | memset(invokebl, B_C_CMD, sizeof(invokebl));
432 |
433 | uint8_t invoke_attempt = 0;
434 | uint8_t read_attempt = 0;
435 | uint8_t recv = 0;
436 | uint32_t rx;
437 |
438 | for(invoke_attempt=0; invoke_attempt < 100 && recv != BOOTLOADER_CONFIRM_OK; invoke_attempt++)
439 | {
440 | FAILFALSE(Transport_Unreset(device));//unreset
441 | Sleep(10);
442 | FAILFALSE(Transport_Reset(device));//reset
443 | Sleep(10);
444 | FAILFALSE(Transport_Unreset(device));//unreset
445 |
446 | for (read_attempt = 0; read_attempt < 5; ++read_attempt)
447 | {
448 | FAILFALSE(Transport_Send(device, invokebl, sizeof(invokebl)));
449 |
450 | FAILFALSE(Transport_GetStats(device, &rx));
451 |
452 | if (rx)
453 | {
454 | if (!Transport_Recv(device, &recv, 1))
455 | {
456 | continue;
457 | }
458 |
459 | if (recv == BOOTLOADER_CONFIRM_OK)
460 | {
461 | break;
462 | }
463 | }
464 |
465 | Sleep(5);
466 | }
467 | }
468 |
469 | FAILFALSE(recv == BOOTLOADER_CONFIRM_OK);
470 |
471 | return true;
472 | }
473 |
474 | bool QN902x_bl_command(TRANSPORT device, uint8_t command, uint32_t send_length, uint8_t *send, uint32_t *recv_length, uint8_t *recv, bool check_exe_result)
475 | {
476 | uint8_t packet_send[0x1FF] = {
477 | BOORLOADER_HEADCODE,
478 | command,
479 | (send_length >> 0) & 0xFF,
480 | (send_length >> 8) & 0xFF,
481 | (send_length >> 16) & 0xFF,
482 | };
483 | size_t packet_send_pos = 5;
484 |
485 | FAILFALSE(send_length <= (sizeof(packet_send) - 7));
486 |
487 | memcpy(packet_send + packet_send_pos, send, send_length);
488 | packet_send_pos += send_length;
489 |
490 | uint16_t crc16;
491 | crc16 = QN902x_bl_crc(packet_send_pos - 1, packet_send + 1);
492 |
493 | packet_send[packet_send_pos++] = (crc16 >> 0) & 0xFF;
494 | packet_send[packet_send_pos++] = (crc16 >> 8) & 0xFF;
495 |
496 | FAILFALSE(Transport_Send(device, packet_send, packet_send_pos));
497 |
498 | uint8_t packet_recv[0xFFF];
499 | size_t packet_recv_pos = 0;
500 |
501 | size_t retry = 0;
502 |
503 | //CONFIRM + RESULT + HEAD + COMMAND + LEN1 + LEN2 + LEN3 + DATA[0..0xFFFFFF] + CRC1 + CRC2
504 |
505 | uint32_t rx;
506 | uint32_t recv_packet_size;
507 | bool got_confirm = false;
508 | bool got_exe_status = false;
509 | bool crc16_valid = false;
510 | while (retry++<1000)
511 | {
512 | FAILFALSE(Transport_GetStats(device, &rx));
513 |
514 | if (rx)
515 | {
516 | //read
517 | uint32_t toread;
518 | toread = rx;
519 | if (sizeof(packet_recv) - packet_recv_pos < rx)
520 | {
521 | toread = sizeof(packet_recv) - packet_recv_pos < rx;
522 | }
523 |
524 | if (toread)
525 | {
526 | if (!got_confirm || (check_exe_result && !got_exe_status))
527 | {
528 | toread = 1;
529 | }
530 | }
531 |
532 | FAILFALSE(Transport_Recv(device, packet_recv + packet_recv_pos, toread));
533 |
534 | packet_recv_pos += toread;
535 |
536 | if (packet_recv_pos > 0 && got_confirm == false)
537 | {
538 | FAILFALSE(packet_recv[0] == BOOTLOADER_CONFIRM_OK);
539 | memmove(packet_recv, packet_recv + 1, packet_recv_pos - 1);
540 | packet_recv_pos--;
541 | got_confirm = true;
542 | }
543 |
544 | if (packet_recv_pos > 0 && check_exe_result == true && got_exe_status == false)
545 | {
546 | FAILFALSE(packet_recv[0] == BOOTLOADER_RESULT_SUCCESS);
547 | memmove(packet_recv, packet_recv + 1, packet_recv_pos - 1);
548 | packet_recv_pos--;
549 | got_exe_status = true;
550 | }
551 |
552 | if (packet_recv_pos)
553 | {
554 | FAILFALSE(packet_recv[0] == BOORLOADER_HEADCODE);
555 | }
556 |
557 | if (got_confirm)
558 | {
559 | if (!check_exe_result || got_exe_status)
560 | {
561 | if (!recv)
562 | {
563 | return true;
564 | }
565 | }
566 | }
567 |
568 | if (packet_recv_pos > 3)
569 | {
570 | recv_packet_size = ((uint32_t)packet_recv[2] << 0) | ((uint32_t)packet_recv[3] << 8) | ((uint32_t)packet_recv[4] << 16);
571 |
572 | if (packet_recv_pos >= (1 + 1 + 3 + recv_packet_size + 2))
573 | {
574 | crc16 = QN902x_bl_crc(1 + 3 + recv_packet_size, packet_recv + 1);
575 |
576 | uint16_t crc16_recv;
577 | crc16_recv = ((uint16_t)packet_recv[1 + 1 + 3 + recv_packet_size + 0] << 0) | ((uint16_t)packet_recv[1 + 1 + 3 + recv_packet_size + 1] << 8);
578 |
579 | if (crc16 == crc16_recv)
580 | {
581 | crc16_valid = true;
582 | }
583 | else
584 | {
585 | crc16_valid = false;
586 | }
587 | break;
588 | }
589 | }
590 | }
591 | Sleep(1);
592 | }
593 |
594 | if (!crc16_valid)
595 | {
596 | crc16_valid = 0;
597 | }
598 |
599 | FAILFALSE(crc16_valid);
600 | FAILFALSE(recv_packet_size <= *recv_length);
601 |
602 | *recv_length = recv_packet_size;
603 | memcpy(recv, packet_recv + 5, *recv_length);
604 |
605 | return true;
606 | }
607 |
608 | uint16_t QN902x_bl_crc(size_t data_len, uint8_t *data)
609 | {
610 | uint16_t crc16;
611 | size_t i;
612 |
613 | crc16 = 0;// crc16_ccitt_init();
614 | for (i = 0; i < data_len; i++)
615 | {
616 | crc16 = crc16_ccitt_update(data[i], crc16);
617 | }
618 | crc16 = crc16_ccitt_finalize(crc16);
619 |
620 | return crc16;
621 | }
622 |
623 | /* System functions */
624 |
625 | bool readout_binary(char *name, size_t *outsize, uint8_t **data)
626 | {
627 | FILE *f;
628 |
629 | f = fopen(name, "rb");
630 | if (!f)
631 | {
632 | return false;
633 | }
634 |
635 | fseek(f, 0, SEEK_END);
636 | *outsize = ftell(f);
637 | fseek(f, 0, SEEK_SET);
638 |
639 | *data = malloc(*outsize);
640 | if (!*data)
641 | {
642 | fclose(f);
643 | return false;
644 | }
645 |
646 | fread(*data, 1, *outsize, f);
647 |
648 | fclose(f);
649 |
650 | return true;
651 | }
652 |
653 | /* High-level functions, using RAMDUMP interface */
654 |
655 | bool QN902x_ramdump_DumpRam(TRANSPORT device, uint32_t addr, uint32_t length, char* filename)
656 | {
657 | FILE* out;
658 | uint8_t packet[0x20];
659 | uint32_t dumped = 0;
660 | time_t start;
661 | out = fopen(filename, "wb");
662 | FAILFALSE(out);
663 |
664 | start = time(NULL);
665 | while (dumped < length)
666 | {
667 | FAILFALSE(QN902x_ramdump_Read(device, addr + dumped, sizeof(packet), packet));
668 | #if 0
669 | printf("%.8X | ", addr + dumped);
670 | uint32_t i;
671 | for (i=0; i< sizeof(packet); ++i)
672 | {
673 | printf("%.2X ", packet[i]);
674 | }
675 | printf(" | ");
676 | for (i = 0; i < sizeof(packet); ++i)
677 | {
678 | printf("%c", isgraph(packet[i]) ? packet[i] : '.');
679 | }
680 | printf("\n");
681 | #else
682 | if (dumped % 0x400 == 0)
683 | {
684 | double percent;
685 | percent = ((double)dumped) / (((double)length) / 100.0);
686 | time_t time_elapsed;
687 | time_elapsed = time(NULL) - start;
688 |
689 | printf("%ds, address %.8X (%.1f%%). eta %ds\n", (int)time_elapsed, dumped + addr, percent, (int)((100. / percent)* time_elapsed) - (int)time_elapsed);
690 | }
691 | #endif
692 | dumped += sizeof(packet);
693 | fwrite(packet, 1, sizeof(packet), out);
694 | }
695 |
696 | fclose(out);
697 |
698 | return true;
699 | }
700 |
701 | bool QN902x_ramdump_DumpFlash(TRANSPORT device, uint32_t addr, uint32_t length, char* filename)
702 | {
703 | FILE* out;
704 | uint8_t packet[0x100];
705 | uint32_t dumped = 0;
706 | time_t start;
707 | out = fopen(filename, "wb");
708 | FAILFALSE(out);
709 |
710 | FAILFALSE(addr + 0x30000000UL < 0x3FFFFFE8);
711 | FAILFALSE((addr + length + 0x30000000UL) < 0x3FFFFFE8);
712 |
713 | start = time(NULL);
714 | while (dumped < length)
715 | {
716 | FAILFALSE(QN902x_ramdump_ReadFlash(device, addr + dumped, sizeof(packet), packet));
717 | #if 0
718 | printf("%.8X | ", addr + dumped);
719 | uint32_t i;
720 | for (i = 0; i < sizeof(packet); ++i)
721 | {
722 | printf("%.2X ", packet[i]);
723 | }
724 | printf(" | ");
725 | for (i = 0; i < sizeof(packet); ++i)
726 | {
727 | printf("%c", isgraph(packet[i]) ? packet[i] : '.');
728 | }
729 | printf("\n");
730 | #else
731 | if (dumped % 0x400 == 0)
732 | {
733 | double percent;
734 | percent = ((double)dumped) / (((double)length) / 100.0);
735 | time_t time_elapsed;
736 | time_elapsed = time(NULL) - start;
737 |
738 | printf("%ds, address %.8X (%.1f%%). eta %ds\n", (int)time_elapsed, dumped + addr, percent, (int)((100. / percent) * time_elapsed) - (int)time_elapsed);
739 | }
740 | #endif
741 | dumped += sizeof(packet);
742 | fwrite(packet, 1, sizeof(packet), out);
743 | }
744 |
745 | fclose(out);
746 |
747 | return true;
748 | }
749 |
750 | bool QN902x_ramdump_Write(TRANSPORT device, uint32_t addr, uint32_t data)
751 | {
752 | char request[32];
753 |
754 | snprintf(request, sizeof(request), "w%X.%X\n", addr, data);
755 | FAILFALSE(Transport_Send(device, (uint8_t*)request, strlen(request)));
756 |
757 | char readout_text[32];
758 | FAILFALSE(Transport_ReadLine(device, readout_text, sizeof(readout_text)));
759 |
760 | FAILFALSE(strcmp(readout_text, "OK") == 0);
761 |
762 | return true;
763 | }
764 |
765 | bool QN902x_ramdump_Read(TRANSPORT device, uint32_t addr, uint32_t read_bytes, uint8_t* buffer)
766 | {
767 | char request[32];
768 |
769 | FAILFALSE((read_bytes % 4) == 0);
770 |
771 | snprintf(request, sizeof(request), "r%X.%X\n", addr, read_bytes);
772 | FAILFALSE(Transport_Send(device, (uint8_t*)request, strlen(request)));
773 |
774 | char *readout_text;
775 | size_t alloc_size = read_bytes * 3 + 16;
776 | readout_text = malloc(alloc_size);
777 | FAILFALSE(readout_text);
778 | if (!Transport_ReadLine(device, readout_text, alloc_size))
779 | {
780 | free(readout_text);
781 | return false;
782 | }
783 |
784 | uint32_t buffer_pos = 0;
785 |
786 | char* text_p = readout_text;
787 | while (*text_p)
788 | {
789 | uint8_t byte;
790 |
791 | if (strchr("abcdef", *text_p))
792 | {
793 | *text_p -= 'a' - 'A';
794 | }
795 | if (*text_p >= 'A' && *text_p <= 'F')
796 | {
797 | byte = *text_p - 'A' + 0x0a;
798 | }
799 | else if (*text_p >= '0' && *text_p <= '9')
800 | {
801 | byte = *text_p - '0';
802 | }
803 | else
804 | {
805 | free(readout_text);
806 | return false;
807 | }
808 | byte <<= 4;
809 | text_p++;
810 |
811 | if (strchr("abcdef", *text_p))
812 | {
813 | *text_p -= 'a' - 'A';
814 | }
815 | if (*text_p >= 'A' && *text_p <= 'F')
816 | {
817 | byte |= *text_p - 'A' + 0x0a;
818 | }
819 | else if (*text_p >= '0' && *text_p <= '9')
820 | {
821 | byte |= *text_p - '0';
822 | }
823 | else
824 | {
825 | free(readout_text);
826 | return false;
827 | }
828 | text_p++;
829 |
830 | if (*text_p == ' ')
831 | {
832 | text_p++;
833 | }
834 | else
835 | {
836 | free(readout_text);
837 | return false;
838 | }
839 |
840 | buffer[buffer_pos++] = byte;
841 | }
842 |
843 | free(readout_text);
844 | return true;
845 | }
846 |
847 | bool QN902x_ramdump_ReadFlash(TRANSPORT device, uint32_t addr, uint32_t read_bytes, uint8_t* buffer)
848 | {
849 | char request[32];
850 |
851 | FAILFALSE((read_bytes % 4) == 0);
852 |
853 | snprintf(request, sizeof(request), "f%X.%X\n", addr, read_bytes);
854 | FAILFALSE(Transport_Send(device, (uint8_t*)request, strlen(request)));
855 |
856 | char* readout_text;
857 | size_t alloc_size = read_bytes * 3 + 16;
858 | readout_text = malloc(alloc_size);
859 | FAILFALSE(readout_text);
860 | if (!Transport_ReadLine(device, readout_text, alloc_size))
861 | {
862 | free(readout_text);
863 | return false;
864 | }
865 |
866 | uint32_t buffer_pos = 0;
867 |
868 | char* text_p = readout_text;
869 | while (*text_p)
870 | {
871 | uint8_t byte;
872 |
873 | if (strchr("abcdef", *text_p))
874 | {
875 | *text_p -= 'a' - 'A';
876 | }
877 | if (*text_p >= 'A' && *text_p <= 'F')
878 | {
879 | byte = *text_p - 'A' + 0x0a;
880 | }
881 | else if (*text_p >= '0' && *text_p <= '9')
882 | {
883 | byte = *text_p - '0';
884 | }
885 | else
886 | {
887 | free(readout_text);
888 | return false;
889 | }
890 | byte <<= 4;
891 | text_p++;
892 |
893 | if (strchr("abcdef", *text_p))
894 | {
895 | *text_p -= 'a' - 'A';
896 | }
897 | if (*text_p >= 'A' && *text_p <= 'F')
898 | {
899 | byte |= *text_p - 'A' + 0x0a;
900 | }
901 | else if (*text_p >= '0' && *text_p <= '9')
902 | {
903 | byte |= *text_p - '0';
904 | }
905 | else
906 | {
907 | free(readout_text);
908 | return false;
909 | }
910 | text_p++;
911 |
912 | if (*text_p == ' ')
913 | {
914 | text_p++;
915 | }
916 | else
917 | {
918 | free(readout_text);
919 | return false;
920 | }
921 |
922 | buffer[buffer_pos++] = byte;
923 | }
924 |
925 | free(readout_text);
926 | return true;
927 | }
928 |
929 | /* Transport functions */
930 |
931 | bool Transport_ReadLine(TRANSPORT device, char* buffer, uint32_t buffer_max)
932 | {
933 | uint32_t readed_total = 0;
934 | uint32_t index = 0;
935 |
936 | while (readed_total < buffer_max && index++ < 100)
937 | {
938 | uint32_t rx;
939 | FAILFALSE(Transport_GetStats(device, &rx));
940 |
941 | if (rx)
942 | {
943 | uint32_t toread;
944 | if (buffer_max - readed_total >= rx)
945 | {
946 | toread = rx;
947 | }
948 | else
949 | {
950 | toread = buffer_max - readed_total;
951 | }
952 | FAILFALSE(Transport_Recv(device, (uint8_t*)(buffer + readed_total), toread));
953 | readed_total += toread;
954 |
955 | uint32_t i;
956 | for (i = 0; i < readed_total; ++i)
957 | {
958 | if (buffer[i] == '\n')
959 | {
960 | buffer[i] = '\0';
961 | return true;
962 | }
963 | }
964 | }
965 | Sleep(1);
966 | }
967 |
968 | return false;
969 | }
970 |
971 | /* Change functions below for adapting to new system */
972 |
973 | #ifdef USE_FTDI_TRANSPORT
974 |
975 | #include
976 |
977 | bool Transport_Send(TRANSPORT device, uint8_t *buffer, uint32_t buffer_len)
978 | {
979 | DWORD written;
980 |
981 | FAILFALSE(FT_Write(*(FT_HANDLE*)device, (LPVOID)buffer, (DWORD)buffer_len, &written) == FT_OK);
982 |
983 | FAILFALSE(written == buffer_len);
984 |
985 | #ifdef LOG_EXCHANGE
986 | {
987 | printf("> ");
988 | size_t i;
989 | for (i = 0; i < buffer_len; ++i)
990 | {
991 | printf("%.2hhX ", buffer[i]);
992 | }
993 | printf("\n");
994 | }
995 | #endif
996 |
997 | return true;
998 | }
999 |
1000 | bool Transport_Recv(TRANSPORT device, uint8_t *buffer, uint32_t buffer_len)
1001 | {
1002 | DWORD readed;
1003 |
1004 | FAILFALSE(FT_Read(*(FT_HANDLE*)device, (LPVOID)buffer, (DWORD)buffer_len, &readed) == FT_OK);
1005 |
1006 | FAILFALSE(readed == buffer_len);
1007 |
1008 | #ifdef LOG_EXCHANGE
1009 | {
1010 | printf("< ");
1011 | size_t i;
1012 | for (i = 0; i < buffer_len; ++i)
1013 | {
1014 | printf("%.2hhX ", buffer[i]);
1015 | }
1016 | printf("\n");
1017 | }
1018 | #endif
1019 |
1020 | return true;
1021 | }
1022 |
1023 | bool Transport_GetStats(TRANSPORT device, uint32_t *recv_quenue)
1024 | {
1025 | DWORD tx;
1026 | DWORD rx;
1027 | DWORD event;
1028 |
1029 | FAILFALSE(FT_GetStatus(*(FT_HANDLE*)device, &rx, &tx, &event) == FT_OK);
1030 |
1031 | *recv_quenue = rx;
1032 |
1033 | return true;
1034 | }
1035 |
1036 | bool Transport_OpenDevice(TRANSPORT *device, char *id)
1037 | {
1038 | FT_HANDLE dev;
1039 |
1040 | FAILFALSE(FT_OpenEx(id, FT_OPEN_BY_SERIAL_NUMBER, &dev) == FT_OK);
1041 |
1042 | FAILFALSE(FT_SetBaudRate(dev, FT_BAUD_9600) == FT_OK);//for 16M crystal
1043 |
1044 | FAILFALSE(FT_SetDataCharacteristics(dev, FT_BITS_8, FT_STOP_BITS_1, FT_PARITY_NONE) == FT_OK);
1045 |
1046 | FAILFALSE(FT_SetFlowControl(dev, FT_FLOW_NONE, 0, 0) == FT_OK);
1047 |
1048 | FAILFALSE(FT_Purge(dev, FT_PURGE_RX | FT_PURGE_TX) == FT_OK);
1049 |
1050 | Sleep(10);
1051 |
1052 | *device = malloc(sizeof(FT_HANDLE));
1053 | if (!*device)
1054 | {
1055 | FT_Close(dev);
1056 | return false;
1057 | }
1058 |
1059 | **(FT_HANDLE**)device = dev;
1060 |
1061 | return true;
1062 | }
1063 |
1064 | bool Transport_CloseDevice(TRANSPORT device)
1065 | {
1066 | FT_Close(*(FT_HANDLE*)device);
1067 | free(device);
1068 |
1069 | return true;
1070 | }
1071 |
1072 | bool Transport_Reset(TRANSPORT device)
1073 | {
1074 | FAILFALSE(FT_SetRts(*(FT_HANDLE*)device) == FT_OK);//reset
1075 |
1076 | return true;
1077 | }
1078 |
1079 | bool Transport_Unreset(TRANSPORT device)
1080 | {
1081 | FAILFALSE(FT_ClrRts(*(FT_HANDLE*)device) == FT_OK);//unreset
1082 |
1083 | return true;
1084 | }
1085 |
1086 | bool Transport_SetBaudRate(TRANSPORT device, uint32_t baudrate)
1087 | {
1088 | switch (baudrate)
1089 | {
1090 | case 9600:
1091 | FAILFALSE(FT_SetBaudRate(*(FT_HANDLE*)device, FT_BAUD_9600) == FT_OK);//unreset
1092 | break;
1093 |
1094 | case 115200:
1095 | FAILFALSE(FT_SetBaudRate(*(FT_HANDLE*)device, FT_BAUD_115200) == FT_OK);//unreset
1096 | break;
1097 |
1098 | default:
1099 | return false;
1100 | break;
1101 | }
1102 |
1103 | return true;
1104 | }
1105 | #elif USE_WINAPI_COM_PORT
1106 |
1107 | #include
1108 |
1109 | bool Transport_Send(TRANSPORT device, uint8_t* buffer, uint32_t buffer_len)
1110 | {
1111 | DWORD written;
1112 |
1113 | FAILFALSE(WriteFile(*(HANDLE*)device, buffer, buffer_len, &written, NULL) == TRUE);
1114 |
1115 | FAILFALSE(written == buffer_len);
1116 |
1117 | #ifdef LOG_EXCHANGE
1118 | {
1119 | printf("> ");
1120 | size_t i;
1121 | for (i = 0; i < buffer_len; ++i)
1122 | {
1123 | printf("%.2hhX ", buffer[i]);
1124 | }
1125 | printf("\n");
1126 | }
1127 | #endif
1128 |
1129 | return true;
1130 | }
1131 |
1132 | bool Transport_Recv(TRANSPORT device, uint8_t* buffer, uint32_t buffer_len)
1133 | {
1134 | DWORD readed;
1135 |
1136 | FAILFALSE(ReadFile(*(HANDLE*)device, buffer, buffer_len, &readed, NULL) == TRUE);
1137 |
1138 | FAILFALSE(readed == buffer_len);
1139 |
1140 | #ifdef LOG_EXCHANGE
1141 | {
1142 | printf("< ");
1143 | size_t i;
1144 | for (i = 0; i < buffer_len; ++i)
1145 | {
1146 | printf("%.2hhX ", buffer[i]);
1147 | }
1148 | printf("\n");
1149 | }
1150 | #endif
1151 |
1152 | return true;
1153 | }
1154 |
1155 | bool Transport_GetStats(TRANSPORT device, uint32_t* recv_quenue)
1156 | {
1157 | COMSTAT stat;
1158 |
1159 | FAILFALSE(ClearCommError(*(HANDLE*)device, NULL, &stat) );
1160 |
1161 | *recv_quenue = stat.cbInQue;
1162 |
1163 | return true;
1164 | }
1165 |
1166 | bool Transport_OpenDevice(TRANSPORT* device, char* id)
1167 | {
1168 | HANDLE dev;
1169 | DCB dcb_com_params =
1170 | {
1171 | .DCBlength = sizeof(dcb_com_params),
1172 | };
1173 | COMMTIMEOUTS timeouts =
1174 | {
1175 | .ReadIntervalTimeout = 50,
1176 | .ReadTotalTimeoutConstant = 50,
1177 | .ReadTotalTimeoutMultiplier = 10,
1178 | .WriteTotalTimeoutConstant = 50,
1179 | .WriteTotalTimeoutMultiplier = 10,
1180 | };
1181 | char com_port_path[32];
1182 |
1183 | snprintf(com_port_path, sizeof(com_port_path)/sizeof(*com_port_path), "\\\\.\\%s", id);
1184 | dev = CreateFileA(com_port_path, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
1185 | if (dev == INVALID_HANDLE_VALUE)
1186 | {
1187 | return false;
1188 | }
1189 |
1190 | if (GetCommState(dev, &dcb_com_params) == FALSE)
1191 | {
1192 | CloseHandle(dev);
1193 | return false;
1194 | }
1195 |
1196 | dcb_com_params.BaudRate = CBR_9600;
1197 | dcb_com_params.fParity = FALSE;
1198 | dcb_com_params.fOutxCtsFlow = FALSE;
1199 | dcb_com_params.fOutxDsrFlow = FALSE;
1200 | dcb_com_params.fDtrControl = DTR_CONTROL_DISABLE;
1201 | dcb_com_params.fDsrSensitivity = FALSE;
1202 | dcb_com_params.fTXContinueOnXoff = FALSE;
1203 | dcb_com_params.fOutX = FALSE;
1204 | dcb_com_params.fInX = FALSE;
1205 | dcb_com_params.fErrorChar = FALSE;
1206 | dcb_com_params.fNull = FALSE;
1207 | dcb_com_params.fRtsControl = RTS_CONTROL_DISABLE;
1208 | dcb_com_params.fAbortOnError = FALSE;
1209 | dcb_com_params.ByteSize = 8;
1210 | dcb_com_params.Parity = NOPARITY;
1211 | dcb_com_params.StopBits = ONESTOPBIT;
1212 |
1213 | if (SetCommState(dev, &dcb_com_params) == FALSE)
1214 | {
1215 | CloseHandle(dev);
1216 | return false;
1217 | }
1218 |
1219 | if (SetCommTimeouts(dev, &timeouts) == FALSE)
1220 | {
1221 | CloseHandle(dev);
1222 | return false;
1223 | }
1224 |
1225 | Sleep(10);
1226 |
1227 | *device = malloc(sizeof(HANDLE));
1228 | if (!*device)
1229 | {
1230 | CloseHandle(dev);
1231 | return false;
1232 | }
1233 |
1234 | **(HANDLE**)device = dev;
1235 |
1236 | return true;
1237 | }
1238 |
1239 | bool Transport_CloseDevice(TRANSPORT device)
1240 | {
1241 | CloseHandle(*(HANDLE*)device);
1242 |
1243 | free(device);
1244 |
1245 | return true;
1246 | }
1247 |
1248 | bool Transport_Reset(TRANSPORT device)
1249 | {
1250 | DCB dcb_com_params =
1251 | {
1252 | .DCBlength = sizeof(dcb_com_params),
1253 | };
1254 |
1255 | FAILFALSE(GetCommState(*(HANDLE*)device, &dcb_com_params) == TRUE);
1256 |
1257 | FAILFALSE(EscapeCommFunction(*(HANDLE*)device, SETRTS));
1258 |
1259 | dcb_com_params.fRtsControl = RTS_CONTROL_ENABLE; //if not then RTS will fall
1260 | FAILFALSE(SetCommState(*(HANDLE*)device, &dcb_com_params) == TRUE);
1261 |
1262 | return true;
1263 | }
1264 |
1265 | bool Transport_Unreset(TRANSPORT device)
1266 | {
1267 | DCB dcb_com_params =
1268 | {
1269 | .DCBlength = sizeof(dcb_com_params),
1270 | };
1271 |
1272 | FAILFALSE(GetCommState(*(HANDLE*)device, &dcb_com_params) == TRUE);
1273 |
1274 | FAILFALSE(EscapeCommFunction(*(HANDLE*)device, CLRRTS));
1275 |
1276 | dcb_com_params.fRtsControl = RTS_CONTROL_DISABLE; //if not then RTS will fall
1277 | FAILFALSE(SetCommState(*(HANDLE*)device, &dcb_com_params) == TRUE);
1278 |
1279 | return true;
1280 | }
1281 |
1282 | bool Transport_SetBaudRate(TRANSPORT device, uint32_t baudrate)
1283 | {
1284 | DCB dcb_com_params =
1285 | {
1286 | .DCBlength = sizeof(dcb_com_params),
1287 | };
1288 |
1289 | FAILFALSE(GetCommState(*(HANDLE*)device, &dcb_com_params) == TRUE);
1290 |
1291 | dcb_com_params.fRtsControl = RTS_CONTROL_DISABLE; //if not then RTS will fall
1292 |
1293 | switch (baudrate)
1294 | {
1295 | case 9600:
1296 | dcb_com_params.BaudRate = CBR_9600;
1297 | break;
1298 |
1299 | case 115200:
1300 | dcb_com_params.BaudRate = CBR_115200;
1301 | break;
1302 |
1303 | default:
1304 | return false;
1305 | break;
1306 | }
1307 |
1308 | FAILFALSE(SetCommState(*(HANDLE*)device, &dcb_com_params) == TRUE);
1309 |
1310 | return true;
1311 | }
1312 |
1313 | #elif USE_LINUX_TTY
1314 |
1315 | #include
1316 | #include
1317 | #include
1318 | #include
1319 |
1320 | bool Transport_Send(TRANSPORT device, uint8_t* buffer, uint32_t buffer_len)
1321 | {
1322 | FAILFALSE(write(*(int*)device, buffer, buffer_len) == buffer_len);
1323 |
1324 | #ifdef LOG_EXCHANGE
1325 | {
1326 | printf("> ");
1327 | size_t i;
1328 | for (i = 0; i < buffer_len; ++i)
1329 | {
1330 | printf("%.2hhX ", buffer[i]);
1331 | }
1332 | printf("\n");
1333 | }
1334 | #endif
1335 |
1336 | return true;
1337 | }
1338 |
1339 | bool Transport_Recv(TRANSPORT device, uint8_t* buffer, uint32_t buffer_len)
1340 | {
1341 | FAILFALSE(read(*(int*)device, buffer, buffer_len) == buffer_len);
1342 |
1343 | #ifdef LOG_EXCHANGE
1344 | {
1345 | printf("< ");
1346 | size_t i;
1347 | for (i = 0; i < buffer_len; ++i)
1348 | {
1349 | printf("%.2hhX ", buffer[i]);
1350 | }
1351 | printf("\n");
1352 | }
1353 | #endif
1354 |
1355 | return true;
1356 | }
1357 |
1358 | bool Transport_GetStats(TRANSPORT device, uint32_t* recv_quenue)
1359 | {
1360 | int available;
1361 |
1362 | FAILFALSE(ioctl(*(int*)device, FIONREAD, &available) == 0);
1363 |
1364 | *recv_quenue = available;
1365 |
1366 | return true;
1367 | }
1368 |
1369 | bool Transport_OpenDevice(TRANSPORT* device, char* id)
1370 | {
1371 | int fd;
1372 | struct termios serial_port_settings;
1373 |
1374 | fd = open(id, O_RDWR | O_NOCTTY);
1375 |
1376 | FAILFALSE(fd != -1);
1377 |
1378 | FAILFALSE(tcgetattr(fd, &serial_port_settings) == 0);
1379 |
1380 | FAILFALSE(cfsetispeed(&serial_port_settings, B9600) == 0);
1381 | FAILFALSE(cfsetispeed(&serial_port_settings, B9600) == 0);
1382 | /*
1383 | serial_port_settings.c_cflag &= ~CRTSCTS;
1384 | serial_port_settings.c_cflag |= CREAD | CLOCAL;
1385 | serial_port_settings.c_iflag &= ~(ICANON | ECHO | ECHOE | ISIG);
1386 | serial_port_settings.c_iflag &= ~(IXON | IXOFF | IXANY);
1387 | */
1388 |
1389 | serial_port_settings.c_cflag |= (CLOCAL | CREAD); /* ignore modem controls */
1390 | serial_port_settings.c_cflag &= ~CSIZE;
1391 | serial_port_settings.c_cflag |= CS8; /* 8-bit characters */
1392 | serial_port_settings.c_cflag &= ~PARENB; /* no parity bit */
1393 | serial_port_settings.c_cflag &= ~CSTOPB; /* only need 1 stop bit */
1394 | serial_port_settings.c_cflag &= ~CRTSCTS; /* no hardware flowcontrol */
1395 |
1396 | /* setup for non-canonical mode */
1397 | serial_port_settings.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON);
1398 | serial_port_settings.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
1399 | serial_port_settings.c_oflag &= ~OPOST;
1400 |
1401 | /* fetch bytes as they become available */
1402 | serial_port_settings.c_cc[VMIN] = 1;
1403 | serial_port_settings.c_cc[VTIME] = 1;
1404 |
1405 | FAILFALSE(tcsetattr(fd, TCSANOW, &serial_port_settings) == 0);
1406 |
1407 | Sleep(10);
1408 |
1409 | *device = malloc(sizeof(int));
1410 | if (!*device)
1411 | {
1412 | close(fd);
1413 | return false;
1414 | }
1415 |
1416 | **(int**)device = fd;
1417 |
1418 | return true;
1419 | }
1420 |
1421 | bool Transport_CloseDevice(TRANSPORT device)
1422 | {
1423 | close(*(int*)device);
1424 |
1425 | free(device);
1426 |
1427 | return true;
1428 | }
1429 |
1430 | bool Transport_Reset(TRANSPORT device)
1431 | {
1432 | int param = TIOCM_RTS;
1433 |
1434 | FAILFALSE(ioctl(*(int*)device, TIOCMBIS, ¶m) == 0);
1435 |
1436 | return true;
1437 | }
1438 |
1439 | bool Transport_Unreset(TRANSPORT device)
1440 | {
1441 | int param = TIOCM_RTS;
1442 |
1443 | FAILFALSE(ioctl(*(int*)device, TIOCMBIC, ¶m) == 0);
1444 |
1445 | return true;
1446 | }
1447 |
1448 | bool Transport_SetBaudRate(TRANSPORT device, uint32_t baudrate)
1449 | {
1450 | struct termios serial_port_settings;
1451 |
1452 | FAILFALSE(tcgetattr(*(int*)device, &serial_port_settings) == 0);
1453 |
1454 | switch (baudrate)
1455 | {
1456 | case 9600:
1457 | FAILFALSE(cfsetispeed(&serial_port_settings, B9600) == 0);
1458 | FAILFALSE(cfsetospeed(&serial_port_settings, B9600) == 0);
1459 | break;
1460 |
1461 | case 115200:
1462 | FAILFALSE(cfsetispeed(&serial_port_settings, B115200) == 0);
1463 | FAILFALSE(cfsetospeed(&serial_port_settings, B115200) == 0);
1464 | break;
1465 |
1466 | default:
1467 | return false;
1468 | break;
1469 | }
1470 |
1471 | FAILFALSE(tcsetattr(*(int*)device, TCSANOW, &serial_port_settings) == 0);
1472 |
1473 | return true;
1474 | }
1475 |
1476 |
1477 | #else
1478 | #error No transport api
1479 | #endif
1480 |
--------------------------------------------------------------------------------