├── 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 | --------------------------------------------------------------------------------