├── .gitignore ├── .gitmodules ├── LICENSE.txt ├── README.md ├── key_bruteforcer ├── .gitignore ├── Makefile ├── README.md ├── bruteforcer.c ├── link.ld ├── main.c ├── old │ ├── .gitignore │ ├── Makefile │ ├── README.md │ ├── link.ld │ ├── main.c │ └── start.S └── start.S └── usb_payload ├── .gitignore ├── Makefile ├── MarkFile ├── README.md ├── ciphtool.py ├── data └── cat.png ├── imgconv.py ├── key.py ├── link.ld └── source ├── libalarmo ├── input.c ├── input.h ├── lcd.c └── lcd.h ├── main.c ├── main.h ├── qrcodegen.c ├── qrcodegen.h ├── startup_stm32h730xx.s ├── stm32h7xx_hal_conf.h ├── stm32h7xx_hal_msp.c ├── stm32h7xx_it.c ├── stm32h7xx_it.h ├── string.c ├── syscalls.c └── system_stm32h7xx.c /.gitignore: -------------------------------------------------------------------------------- 1 | /.vscode 2 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "usb_payload/STM32CubeH7"] 2 | path = usb_payload/STM32CubeH7 3 | url = https://github.com/STMicroelectronics/STM32CubeH7.git 4 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 GaryOderNichts 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Alarmo 2 | This repository contains tools and code for the Nintendo Sound Clock: Alarmo. 3 | 4 | [Check out the blogpost!](https://garyodernichts.blogspot.com/2024/10/looking-into-nintendo-alarmo.html) 5 | 6 | ## key_bruteforcer 7 | This is a payload intended to be loaded with openocd, which bruteforces the Alarmo content key. 8 | More info [here](./key_bruteforcer/README.md). 9 | 10 | ## usb_payload 11 | This is a simple payload, which can be booted over USB, displaying an image of a cat. 12 | More info [here](./usb_payload/README.md). 13 | -------------------------------------------------------------------------------- /key_bruteforcer/.gitignore: -------------------------------------------------------------------------------- 1 | payload.elf 2 | bruteforcer 3 | aes_data.bin 4 | -------------------------------------------------------------------------------- /key_bruteforcer/Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: all clean bruteforcer 2 | 3 | all: bruteforcer 4 | arm-none-eabi-gcc -o payload.elf main.c start.S -mthumb -march=armv7e-m -mtune=cortex-m7 -mfpu=fpv5-d16 -mfloat-abi=hard -nostartfiles -nodefaultlibs -T link.ld 5 | 6 | bruteforcer: 7 | gcc bruteforcer.c -maes -O3 -o bruteforcer 8 | 9 | clean: 10 | rm -f bruteforcer payload.elf 11 | -------------------------------------------------------------------------------- /key_bruteforcer/README.md: -------------------------------------------------------------------------------- 1 | # Key Bruteforcer 2 | This project contains a payload intended to be loaded with openocd, which dumps necessary data to bruteforce the AES key. 3 | It also contains a x86 PC tool to bruteforce the key. 4 | 5 | The old payload which bruteforces the key on the Alarmo itself can be found [here](./old/README.md). 6 | 7 | ## Usage 8 | 9 | ### Using the USB payload 10 | - Build or download the latest USB payload. 11 | - Run `make bruteforcer` to compile the PC tool. 12 | - Hold down the confirm, back and notification button on the Alarmo at the same time. 13 | - While holding down all three buttons, plug in the USB cable to your PC. 14 | The dial button on top of the Alarmo should light up red and a drive should appear on the PC. 15 | - Copy the `a.bin` from the USB payload to the newly appeared drive. 16 | - Copy the `MarkFile` from the USB payload to the drive. 17 | The alarmo should disconnect from the PC and a picture of a cat is displayed on the screen. 18 | - Press the back button on the Alarmo to display the QR code. 19 | - Scan the QR code and copy the containing text to your PC. 20 | - Run `./bruteforcer ` to start bruteforcing the key. This will take a few minutes. 21 | 22 | ### Using SWD 23 | - Update the `FIRMWARE_VERSION` define in the `main.c` to match the software version the Alarmo is on. 24 | - Run `make` to compile the payload and the PC tool. 25 | - Boot the Alarmo normally and wait until you can see the clock screen. 26 | - Connect to the debug interface using openocd and run the `halt` command. 27 | - Run `load_image payload.elf` to load the payload into memory. 28 | - Run `resume 0x20000000` to execute the payload. The necessary data will now be stored to memory. 29 | Once the payload is done a breakpoint will be triggered. 30 | - Run `dump_image aes_data.bin 0x24000000 0x50` to dump the data to a file. 31 | - Run `./bruteforcer aes_data.bin` to start bruteforcing the key. This will take a few minutes. 32 | -------------------------------------------------------------------------------- /key_bruteforcer/bruteforcer.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Nintendo Alarmo content key bruteforcer. 3 | * Created in 2024 by GaryOderNichts. 4 | * 5 | * Compiled with `gcc bruteforcer.c -maes -O3 -o bruteforcer` 6 | */ 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | typedef struct { 14 | uint8_t iv[16]; 15 | uint8_t encrypted_parts[4][16]; 16 | } aes_data_t; 17 | 18 | static void aes128_encrypt(const uint8_t *key, const uint8_t *plaintext, uint8_t *ciphertext); 19 | static int hex2bin(const char *str, void *bytes, size_t maxsize); 20 | 21 | int main(int argc, char const *argv[]) 22 | { 23 | if (argc != 2) { 24 | printf("Usage: %s \n", argv[0]); 25 | return 1; 26 | } 27 | 28 | // Try to read in AES data from file 29 | aes_data_t data; 30 | FILE *f = fopen(argv[1], "rb"); 31 | if (!f) { 32 | if (hex2bin(argv[1], &data, sizeof(data)) != sizeof(data)) { 33 | printf("Failed to open file or invalid hex string\n"); 34 | return 1; 35 | } 36 | } else { 37 | if (fread(&data, 1, sizeof(data), f) != sizeof(data)) { 38 | fclose(f); 39 | printf("Failed to read file\n"); 40 | return 1; 41 | } 42 | 43 | fclose(f); 44 | } 45 | 46 | // Save start time 47 | time_t start_time = time(NULL); 48 | 49 | const uint8_t *iv = &data.iv[0]; 50 | uint8_t full_key[16] = { 0 }; 51 | 52 | for (int i = 3; i >= 0; i--) { 53 | // Start with the least blanked out key data 54 | const uint8_t *expected = &data.encrypted_parts[i][0]; 55 | 56 | // Start guessing 57 | uint32_t key = 0; 58 | while (1) { 59 | // Fill in the key 60 | full_key[(i * 4) + 0] = (uint8_t) (key >> 24); 61 | full_key[(i * 4) + 1] = (uint8_t) (key >> 16); 62 | full_key[(i * 4) + 2] = (uint8_t) (key >> 8); 63 | full_key[(i * 4) + 3] = (uint8_t) (key); 64 | 65 | // Encrypting the IV should result in the expected data 66 | uint8_t result[16]; 67 | aes128_encrypt(full_key, iv, result); 68 | 69 | if (memcmp(result, expected, 16) == 0) { 70 | // Found key 71 | printf("\nFound key part %d / 4: %08x\n", (4 - i), key); 72 | break; 73 | } 74 | 75 | // Make sure we don't overflow 76 | if (key == ~0) { 77 | printf("\nCouldn't find match\n"); 78 | return 1; 79 | } 80 | 81 | // Update progress 82 | if ((key & 0xFFFF) == 0) { 83 | printf("\rBruteforcing key part %d / 4... %.1f%% (0x%08x / 0xffffffff)", (4 - i), (key / 4294967296.0) * 100.0f, key); 84 | fflush(stdout); 85 | } 86 | 87 | // Increment test key 88 | key++; 89 | } 90 | } 91 | 92 | // Print output 93 | printf("Found key! Took %d seconds.\n", time(NULL) - start_time); 94 | printf("Key:\t"); 95 | for (int i = 0; i < 16; i++) { 96 | printf("%02x", full_key[i]); 97 | } 98 | printf("\n"); 99 | printf("IV:\t"); 100 | for (int i = 0; i < 16; i++) { 101 | printf("%02x", iv[i]); 102 | } 103 | printf("\n"); 104 | 105 | return 0; 106 | } 107 | 108 | static inline int char2bin(char c) 109 | { 110 | if((c >= 'a') && (c <= 'f')) 111 | return c - 'a' + 10; 112 | if((c >= '0') && (c <= '9')) 113 | return c - '0'; 114 | if((c >= 'A') && (c <= 'F')) 115 | return c - 'A' + 10; 116 | 117 | return -1; 118 | } 119 | 120 | static int hex2bin(const char *str, void *bytes, size_t maxsize) 121 | { 122 | uint8_t *bytes_ptr = (uint8_t *)bytes; 123 | size_t bytes_in = 0; 124 | 125 | // Only accept hex pairs 126 | size_t len = strlen(str); 127 | if ((len & 1) != 0 || (len / 2) > maxsize) { 128 | return -1; 129 | } 130 | 131 | for (; str[0] != '\0'; str += 2) { 132 | int char0 = char2bin(str[0]); 133 | int char1 = char2bin(str[1]); 134 | 135 | // Check for invalid characters 136 | if (char0 == -1 || char1 == -1) { 137 | return -1; 138 | } 139 | 140 | bytes_ptr[bytes_in++] = (char0 << 4) | char1; 141 | } 142 | 143 | return bytes_in; 144 | } 145 | 146 | // From https://stackoverflow.com/a/32313659/11511475 147 | #define AES_128_key_exp(k, rcon) aes128_key_expansion(k, _mm_aeskeygenassist_si128(k, rcon)) 148 | static __m128i aes128_key_expansion(__m128i key, __m128i keygened) 149 | { 150 | keygened = _mm_shuffle_epi32(keygened, _MM_SHUFFLE(3,3,3,3)); 151 | key = _mm_xor_si128(key, _mm_slli_si128(key, 4)); 152 | key = _mm_xor_si128(key, _mm_slli_si128(key, 4)); 153 | key = _mm_xor_si128(key, _mm_slli_si128(key, 4)); 154 | return _mm_xor_si128(key, keygened); 155 | } 156 | 157 | static void aes128_encrypt(const uint8_t *key, const uint8_t *plaintext, uint8_t *ciphertext) 158 | { 159 | // Start by loading the key 160 | __m128i aes_key_schedule[10]; 161 | aes_key_schedule[0] = _mm_loadu_si128((const __m128i*) key); 162 | aes_key_schedule[1] = AES_128_key_exp(aes_key_schedule[0], 0x01); 163 | aes_key_schedule[2] = AES_128_key_exp(aes_key_schedule[1], 0x02); 164 | aes_key_schedule[3] = AES_128_key_exp(aes_key_schedule[2], 0x04); 165 | aes_key_schedule[4] = AES_128_key_exp(aes_key_schedule[3], 0x08); 166 | aes_key_schedule[5] = AES_128_key_exp(aes_key_schedule[4], 0x10); 167 | aes_key_schedule[6] = AES_128_key_exp(aes_key_schedule[5], 0x20); 168 | aes_key_schedule[7] = AES_128_key_exp(aes_key_schedule[6], 0x40); 169 | aes_key_schedule[8] = AES_128_key_exp(aes_key_schedule[7], 0x80); 170 | aes_key_schedule[9] = AES_128_key_exp(aes_key_schedule[8], 0x1B); 171 | aes_key_schedule[10] = AES_128_key_exp(aes_key_schedule[9], 0x36); 172 | 173 | // Load plaintext 174 | __m128i m = _mm_loadu_si128((const __m128i *) plaintext); 175 | 176 | // Encrypt block 177 | m = _mm_xor_si128(m, aes_key_schedule[0]); 178 | m = _mm_aesenc_si128(m, aes_key_schedule[1]); 179 | m = _mm_aesenc_si128(m, aes_key_schedule[2]); 180 | m = _mm_aesenc_si128(m, aes_key_schedule[3]); 181 | m = _mm_aesenc_si128(m, aes_key_schedule[4]); 182 | m = _mm_aesenc_si128(m, aes_key_schedule[5]); 183 | m = _mm_aesenc_si128(m, aes_key_schedule[6]); 184 | m = _mm_aesenc_si128(m, aes_key_schedule[7]); 185 | m = _mm_aesenc_si128(m, aes_key_schedule[8]); 186 | m = _mm_aesenc_si128(m, aes_key_schedule[9]); 187 | m = _mm_aesenclast_si128(m, aes_key_schedule[10]); 188 | 189 | // Store cyphertext 190 | _mm_storeu_si128((__m128i *) ciphertext, m); 191 | } 192 | -------------------------------------------------------------------------------- /key_bruteforcer/link.ld: -------------------------------------------------------------------------------- 1 | OUTPUT_ARCH(arm) 2 | 3 | SECTIONS { 4 | /* Place code in DTCM */ 5 | . = (0x20000000); 6 | 7 | /* Place init section first, so it's possible to just jump to the base address */ 8 | .init : { 9 | *(.init*); 10 | } 11 | .text : { 12 | *(.text*); 13 | } 14 | .rodata : { 15 | *(.rodata*) 16 | } 17 | .data : { 18 | *(.data*) 19 | } 20 | 21 | /DISCARD/ : { 22 | *(*); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /key_bruteforcer/main.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Nintendo Alarmo content key bruteforce data dumper. 3 | * Created in 2024 by GaryOderNichts. 4 | */ 5 | #include 6 | 7 | // Make sure to set this according to the firmware version the alarmo is on 8 | // 1.0.0 -> 100 9 | // 2.0.0 -> 200 10 | #define FIRMWARE_VERSION 100 11 | 12 | // Function pointers to the 1.0.0 firmware loaded in external RAM 13 | #if FIRMWARE_VERSION == 100 14 | #define CRYP_AES_CTR_Decrypt ((void (*)(uint32_t *counter, void *outData, uint32_t outSize, const void *inData, uint32_t inSize))(0x700724c8 | 1)) 15 | #define CRYP_AES_CTR_Encrypt ((void (*)(uint32_t *counter, void *outData, uint32_t outSize, const void *inData, uint32_t inSize))(0x7007245c | 1)) 16 | #elif FIRMWARE_VERSION == 200 17 | #define CRYP_AES_CTR_Decrypt ((void (*)(uint32_t *counter, void *outData, uint32_t outSize, const void *inData, uint32_t inSize))(0x7007798c | 1)) 18 | #define CRYP_AES_CTR_Encrypt ((void (*)(uint32_t *counter, void *outData, uint32_t outSize, const void *inData, uint32_t inSize))(0x70077920 | 1)) 19 | #else 20 | #error Unsupported firmware version 21 | #endif 22 | 23 | #define CRYP_BASE (0x48021000UL) 24 | #define CRYP_KEY_BASE ((volatile uint32_t *)(CRYP_BASE + 0x20UL)) 25 | #define CRYP_IV_BASE ((volatile uint32_t *)(CRYP_BASE + 0x40UL)) 26 | 27 | int main(void) 28 | { 29 | // Disable interrupts 30 | __asm__ __volatile__ ("cpsid i" : : : "memory"); 31 | 32 | // Pointer to AXI SRAM where results are stored 33 | uint32_t *result_ptr = (uint32_t*) 0x24000000; 34 | 35 | // Buffer to hold encrypted data 36 | uint32_t encrypted[4]; 37 | 38 | // Clear zero buffer 39 | uint32_t zeroes[4]; 40 | for (int i = 0; i < 4; i++) { 41 | zeroes[i] = 0; 42 | } 43 | 44 | // store IV 45 | *result_ptr++ = __builtin_bswap32(CRYP_IV_BASE[0]); 46 | *result_ptr++ = __builtin_bswap32(CRYP_IV_BASE[1]); 47 | *result_ptr++ = __builtin_bswap32(CRYP_IV_BASE[2]); 48 | *result_ptr++ = 0; // for the counter just store 0 49 | 50 | for (int i = 0; i < 4; i++) { 51 | // Start blanking out parts of the key after the first round 52 | if (i > 0) { 53 | CRYP_KEY_BASE[4 + (i - 1)] = 0; 54 | } 55 | 56 | // Encrypt zeroes 57 | uint32_t counter = 0; 58 | CRYP_AES_CTR_Encrypt(&counter, encrypted, sizeof(encrypted), zeroes, sizeof(zeroes)); 59 | 60 | // Store encrypted data 61 | *result_ptr++ = (encrypted[0]); 62 | *result_ptr++ = (encrypted[1]); 63 | *result_ptr++ = (encrypted[2]); 64 | *result_ptr++ = (encrypted[3]); 65 | } 66 | 67 | // All done 68 | __asm__ __volatile__("bkpt"); 69 | while (1) 70 | ; 71 | } 72 | -------------------------------------------------------------------------------- /key_bruteforcer/old/.gitignore: -------------------------------------------------------------------------------- 1 | payload.elf 2 | -------------------------------------------------------------------------------- /key_bruteforcer/old/Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: all clean 2 | 3 | all: 4 | arm-none-eabi-gcc -o payload.elf main.c start.S -mthumb -march=armv7e-m -mtune=cortex-m7 -mfpu=fpv5-d16 -mfloat-abi=hard -nostartfiles -nodefaultlibs -T link.ld 5 | 6 | clean: 7 | rm payload.elf 8 | -------------------------------------------------------------------------------- /key_bruteforcer/old/README.md: -------------------------------------------------------------------------------- 1 | # Key Bruteforcer 2 | This is a payload intended to be loaded with openocd, which bruteforces the Alarmo content key. 3 | 4 | ## Usage 5 | - Update the `FIRMWARE_VERSION` define in the `main.c` to match the software version the Alarmo is on. 6 | - Run `make` to compile the payload. 7 | - Boot the Alarmo normally and wait until you can see the clock screen. 8 | - Connect to the debug interface using openocd and run the `halt` command. 9 | - Run `load_image payload.elf` to load the payload into memory. 10 | - Run `resume 0x20000000` to execute the payload. The key is now being bruteforced. 11 | 12 | Once it is done a breakpoint will be triggered. 13 | You can check the progress and results using `mdw 0x24000000 9`: 14 | ``` 15 | v- Key 1 v- Key 2 v- Key 3 v- Key 4 v- IV 1 v- IV 2 v- IV 3 v- Counter 16 | 0x24000000: 12345678 ffffffff ffffffff ffffffff d12b3839 6bd19b52 ce803a8f 00000004 17 | 0x24000020: 00321000 18 | ^- Progress counter 19 | ``` 20 | In the output example above the first part of the key would be `12345678` while the other 3 parts haven't been found yet. -------------------------------------------------------------------------------- /key_bruteforcer/old/link.ld: -------------------------------------------------------------------------------- 1 | OUTPUT_ARCH(arm) 2 | 3 | SECTIONS { 4 | /* Place code in DTCM */ 5 | . = (0x20000000); 6 | 7 | /* Place init section first, so it's possible to just jump to the base address */ 8 | .init : { 9 | *(.init*); 10 | } 11 | .text : { 12 | *(.text*); 13 | } 14 | .rodata : { 15 | *(.rodata*) 16 | } 17 | .data : { 18 | *(.data*) 19 | } 20 | 21 | /DISCARD/ : { 22 | *(*); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /key_bruteforcer/old/main.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Nintendo Alarmo content key bruteforcer. 3 | * Created in 2024 by GaryOderNichts. 4 | */ 5 | #include 6 | 7 | // Make sure to set this according to the firmware version the alarmo is on 8 | // 1.0.0 -> 100 9 | // 2.0.0 -> 200 10 | #define FIRMWARE_VERSION 100 11 | 12 | // Function pointers to the 1.0.0 firmware loaded in external RAM 13 | #if FIRMWARE_VERSION == 100 14 | #define CRYP_AES_CTR_Decrypt ((void (*)(uint32_t *counter, void *outData, uint32_t outSize, const void *inData, uint32_t inSize))(0x700724c8 | 1)) 15 | #define CRYP_AES_CTR_Encrypt ((void (*)(uint32_t *counter, void *outData, uint32_t outSize, const void *inData, uint32_t inSize))(0x7007245c | 1)) 16 | #elif FIRMWARE_VERSION == 200 17 | #define CRYP_AES_CTR_Decrypt ((void (*)(uint32_t *counter, void *outData, uint32_t outSize, const void *inData, uint32_t inSize))(0x7007798c | 1)) 18 | #define CRYP_AES_CTR_Encrypt ((void (*)(uint32_t *counter, void *outData, uint32_t outSize, const void *inData, uint32_t inSize))(0x70077920 | 1)) 19 | #else 20 | #error Unsupported firmware version 21 | #endif 22 | 23 | #define CRYP_BASE (0x48021000UL) 24 | #define CRYP_KEY_BASE ((volatile uint32_t *)(CRYP_BASE + 0x20UL)) 25 | #define CRYP_IV_BASE ((volatile uint32_t *)(CRYP_BASE + 0x40UL)) 26 | 27 | static int memcmp32(const uint32_t *a, const uint32_t *b, uint32_t count) 28 | { 29 | while (count-- > 0) { 30 | if (*a++ != *b++) { 31 | return a[-1] < b[-1] ? -1 : 1; 32 | } 33 | } 34 | 35 | return 0; 36 | } 37 | 38 | int main(void) 39 | { 40 | // Disable interrupts 41 | __asm__ __volatile__ ("cpsid i" : : : "memory"); 42 | 43 | // Pointer to AXI SRAM where results are stored 44 | uint32_t *result_ptr = (uint32_t*) 0x24000000; 45 | 46 | // Buffer to store expected and actual data in 47 | uint32_t expected[4]; 48 | uint32_t actual[4]; 49 | 50 | // Clear zero buffer and results 51 | uint32_t zeroes[4]; 52 | for (int i = 0; i < 4; i++) { 53 | zeroes[i] = 0; 54 | 55 | // Initialize results with Fs 56 | result_ptr[i] = ~0; 57 | result_ptr[4 + i] = ~0; 58 | } 59 | 60 | // store IV 61 | result_ptr[4] = CRYP_IV_BASE[0]; 62 | result_ptr[5] = CRYP_IV_BASE[1]; 63 | result_ptr[6] = CRYP_IV_BASE[2]; 64 | result_ptr[7] = CRYP_IV_BASE[3]; 65 | 66 | // To keep track of progress create a progress counter 67 | result_ptr[8] = ~0; 68 | 69 | // Encrypt zeroes with the unmodified key, to create the expected value 70 | uint32_t counter = 0; 71 | CRYP_AES_CTR_Encrypt(&counter, expected, 16, zeroes, 16); 72 | 73 | // Start offsets for the key 74 | // Can be filled out if the process was cancelled and should be resumed while already having made progress 75 | uint32_t start_offsets[4] = { 0, 0, 0, 0 }; 76 | 77 | for (int i = 0; i < 4; i++) { 78 | uint32_t key = start_offsets[i]; 79 | while (1) { 80 | // Update partial key 81 | CRYP_KEY_BASE[4 + i] = key; 82 | 83 | // Encrypt with partially updated key 84 | counter = 0; 85 | CRYP_AES_CTR_Encrypt(&counter, actual, 16, zeroes, 16); 86 | 87 | // Check if output matches 88 | if (memcmp32(actual, expected, 4) == 0) { 89 | // Found a match, store key fragment 90 | result_ptr[i] = key; 91 | break; 92 | } 93 | 94 | if (key == ~0) { 95 | // Could not find a match, this shouldn't happen 96 | __asm__ __volatile__("bkpt"); 97 | break; 98 | } 99 | 100 | // Store progress 101 | if ((key & 0xfff) == 0) { 102 | result_ptr[8] = key; 103 | } 104 | 105 | // Increment key 106 | key++; 107 | } 108 | } 109 | 110 | // All done 111 | __asm__ __volatile__("bkpt"); 112 | while (1) 113 | ; 114 | } 115 | -------------------------------------------------------------------------------- /key_bruteforcer/old/start.S: -------------------------------------------------------------------------------- 1 | .section .init 2 | .global _start 3 | 4 | _start: 5 | b main 6 | -------------------------------------------------------------------------------- /key_bruteforcer/start.S: -------------------------------------------------------------------------------- 1 | .section .init 2 | .global _start 3 | 4 | _start: 5 | b main 6 | -------------------------------------------------------------------------------- /usb_payload/.gitignore: -------------------------------------------------------------------------------- 1 | __pycache__ 2 | *.elf 3 | *.bin 4 | build 5 | -------------------------------------------------------------------------------- /usb_payload/Makefile: -------------------------------------------------------------------------------- 1 | #------------------------------------------------------------------------------- 2 | .SUFFIXES: 3 | #------------------------------------------------------------------------------- 4 | 5 | TOPDIR ?= $(CURDIR) 6 | 7 | #--------------------------------------------------------------------------------- 8 | # the prefix on the compiler executables 9 | #--------------------------------------------------------------------------------- 10 | PREFIX := arm-none-eabi- 11 | export CC := $(PREFIX)gcc 12 | export CXX := $(PREFIX)g++ 13 | export AS := $(PREFIX)as 14 | export AR := $(PREFIX)gcc-ar 15 | export OBJCOPY := $(PREFIX)objcopy 16 | export STRIP := $(PREFIX)strip 17 | export RANLIB := $(PREFIX)gcc-ranlib 18 | 19 | #--------------------------------------------------------------------------------- 20 | # allow seeing compiler command lines with make V=1 (similar to autotools' silent) 21 | #--------------------------------------------------------------------------------- 22 | ifeq ($(V),1) 23 | SILENTMSG := @true 24 | SILENTCMD := 25 | else 26 | SILENTMSG := @echo 27 | SILENTCMD := @ 28 | endif 29 | 30 | #------------------------------------------------------------------------------- 31 | # TARGET is the name of the output 32 | # BUILD is the directory where object files & intermediate files will be placed 33 | # SOURCES is a list of directories containing source code 34 | # INCLUDES is a list of directories containing header files 35 | #------------------------------------------------------------------------------- 36 | TARGET := $(notdir $(CURDIR)) 37 | BUILD := build 38 | SOURCES := source source/libalarmo 39 | INCLUDES := source 40 | DATA := data 41 | 42 | # Add required driver source files 43 | SOURCE_FILES := STM32CubeH7/Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_adc_ex.c \ 44 | STM32CubeH7/Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_adc.c \ 45 | STM32CubeH7/Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_ll_adc.c \ 46 | STM32CubeH7/Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_cortex.c \ 47 | STM32CubeH7/Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_dma_ex.c \ 48 | STM32CubeH7/Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_dma.c \ 49 | STM32CubeH7/Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_ll_dma.c \ 50 | STM32CubeH7/Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_gpio.c \ 51 | STM32CubeH7/Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_ll_gpio.c \ 52 | STM32CubeH7/Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_mdma.c \ 53 | STM32CubeH7/Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_ll_mdma.c \ 54 | STM32CubeH7/Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_pwr_ex.c \ 55 | STM32CubeH7/Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_pwr.c \ 56 | STM32CubeH7/Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_ll_pwr.c \ 57 | STM32CubeH7/Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_rcc_ex.c \ 58 | STM32CubeH7/Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_rcc.c \ 59 | STM32CubeH7/Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_ll_rcc.c \ 60 | STM32CubeH7/Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_sram.c \ 61 | STM32CubeH7/Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_ll_fmc.c \ 62 | STM32CubeH7/Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_tim_ex.c \ 63 | STM32CubeH7/Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_tim.c \ 64 | STM32CubeH7/Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_ll_tim.c \ 65 | STM32CubeH7/Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal.c 66 | 67 | # Add required driver includes 68 | INCLUDES += STM32CubeH7/Drivers/CMSIS/Include \ 69 | STM32CubeH7/Drivers/CMSIS/Device/ST/STM32H7xx/Include \ 70 | STM32CubeH7/Drivers/STM32H7xx_HAL_Driver/Inc 71 | 72 | #------------------------------------------------------------------------------- 73 | # options for code generation 74 | #------------------------------------------------------------------------------- 75 | MACHDEP = -mthumb -march=armv7e-m -mtune=cortex-m7 -mfpu=fpv5-d16 -mfloat-abi=hard -DSTM32H730xx 76 | 77 | CFLAGS := $(MACHDEP) $(INCLUDE) -O0 78 | 79 | CXXFLAGS := $(CFLAGS) 80 | 81 | CFLAGS += 82 | 83 | ASFLAGS := $(MACHDEP) 84 | 85 | LDFLAGS = $(MACHDEP) -specs=nano.specs \ 86 | -Wl,-Map,$(notdir $*.map) \ 87 | -Wl,-T $(TOPDIR)/link.ld \ 88 | -Wl,--no-warn-rwx-segments 89 | 90 | LIBS := -lc -lm -lnosys 91 | 92 | ifeq ($(DEBUG), 1) 93 | CFLAGS += -g 94 | ASFLAGS += -g 95 | LDFLAGS += -g 96 | endif 97 | 98 | #------------------------------------------------------------------------------- 99 | # list of directories containing libraries, this must be the top level 100 | # containing include and lib 101 | #------------------------------------------------------------------------------- 102 | LIBDIRS := 103 | 104 | 105 | #------------------------------------------------------------------------------- 106 | # no real need to edit anything past this point unless you need to add additional 107 | # rules for different file extensions 108 | #------------------------------------------------------------------------------- 109 | ifneq ($(BUILD),$(notdir $(CURDIR))) 110 | #------------------------------------------------------------------------------- 111 | 112 | export OUTPUT := $(CURDIR)/$(TARGET) 113 | export TOPDIR := $(CURDIR) 114 | 115 | export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \ 116 | $(foreach dir,$(DATA),$(CURDIR)/$(dir)) \ 117 | $(CURDIR)/STM32CubeH7/Drivers/STM32H7xx_HAL_Driver/Src 118 | 119 | export DEPSDIR := $(CURDIR)/$(BUILD) 120 | 121 | CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c))) 122 | CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp))) 123 | SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s))) 124 | BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*))) 125 | 126 | CFILES += $(foreach f,$(HAL_SOURCE),$(notdir $(f))) 127 | CFILES += $(foreach f,$(SOURCE_FILES),$(notdir $(f))) 128 | 129 | #------------------------------------------------------------------------------- 130 | # use CXX for linking C++ projects, CC for standard C 131 | #------------------------------------------------------------------------------- 132 | ifeq ($(strip $(CPPFILES)),) 133 | #------------------------------------------------------------------------------- 134 | export LD := $(CC) 135 | #------------------------------------------------------------------------------- 136 | else 137 | #------------------------------------------------------------------------------- 138 | export LD := $(CXX) 139 | #------------------------------------------------------------------------------- 140 | endif 141 | #------------------------------------------------------------------------------- 142 | 143 | export OFILES_SRC := $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o) 144 | export OFILES := $(OFILES_SRC) 145 | export HFILES_BIN := $(addsuffix .h,$(subst .,_,$(BINFILES))) 146 | 147 | export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \ 148 | $(foreach dir,$(LIBDIRS),-I$(dir)/include) \ 149 | -I$(CURDIR)/$(BUILD) 150 | 151 | export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) 152 | 153 | .PHONY: $(BUILD) clean all 154 | 155 | #------------------------------------------------------------------------------- 156 | all: $(BUILD) 157 | 158 | $(BUILD): 159 | @[ -d $@ ] || mkdir -p $@ 160 | @$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile 161 | 162 | #------------------------------------------------------------------------------- 163 | clean: 164 | @echo clean ... 165 | @rm -fr $(BUILD) $(TARGET).elf $(TARGET).bin a.bin 166 | 167 | #------------------------------------------------------------------------------- 168 | else 169 | .PHONY: all 170 | 171 | DEPENDS := $(OFILES:.o=.d) 172 | 173 | #------------------------------------------------------------------------------- 174 | # main targets 175 | #------------------------------------------------------------------------------- 176 | all : $(TOPDIR)/a.bin 177 | 178 | $(TOPDIR)/a.bin: $(OUTPUT).bin 179 | @echo encrypting ... $(notdir $@) 180 | $(SILENTCMD)python3 $(TOPDIR)/ciphtool.py encrypt $< $@ 181 | 182 | $(OUTPUT).bin: $(OUTPUT).elf 183 | @echo creating ... $(notdir $@) 184 | $(SILENTCMD)$(OBJCOPY) -O binary $< $@ 185 | 186 | $(OUTPUT).elf: $(OFILES) 187 | @echo linking ... $(notdir $@) 188 | $(SILENTCMD)$(LD) $(LDFLAGS) $(OFILES) $(LIBPATHS) $(LIBS) -o $@ $(ERROR_FILTER) 189 | 190 | $(OFILES_SRC) : $(HFILES_BIN) 191 | 192 | #--------------------------------------------------------------------------------- 193 | %.o: %.cpp 194 | $(SILENTMSG) $(notdir $<) 195 | $(SILENTCMD)$(CXX) -MMD -MP -MF $(DEPSDIR)/$*.d $(CPPFLAGS) $(CXXFLAGS) -c $< -o $@ $(ERROR_FILTER) 196 | 197 | #--------------------------------------------------------------------------------- 198 | %.o: %.c 199 | $(SILENTMSG) $(notdir $<) 200 | $(SILENTCMD)$(CC) -MMD -MP -MF $(DEPSDIR)/$*.d $(CPPFLAGS) $(CFLAGS) -c $< -o $@ $(ERROR_FILTER) 201 | 202 | #--------------------------------------------------------------------------------- 203 | %.o: %.s 204 | $(SILENTMSG) $(notdir $<) 205 | $(SILENTCMD)$(CC) -MMD -MP -MF $(DEPSDIR)/$*.d -x assembler-with-cpp $(CPPFLAGS) $(ASFLAGS) -c $< -o $@ $(ERROR_FILTER) 206 | 207 | #--------------------------------------------------------------------------------- 208 | 209 | #------------------------------------------------------------------------------- 210 | %_png.h : %.png 211 | #------------------------------------------------------------------------------- 212 | @echo $(notdir $<) 213 | $(SILENTCMD)python3 $(TOPDIR)/imgconv.py $< > $@ 214 | 215 | -include $(DEPENDS) 216 | 217 | #------------------------------------------------------------------------------- 218 | endif 219 | #------------------------------------------------------------------------------- 220 | -------------------------------------------------------------------------------- /usb_payload/MarkFile: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GaryOderNichts/alarmo/846d26beae14a053775d8c1539d7a9c74bd68a12/usb_payload/MarkFile -------------------------------------------------------------------------------- /usb_payload/README.md: -------------------------------------------------------------------------------- 1 | # Alarmo USB Payload 2 | This is a simple payload, which can be booted over USB, displaying an image of a cat. 3 | 4 | ## Usage 5 | - Download the latest release or build from source. 6 | - Hold down the confirm, back and notification button on the Alarmo at the same time. 7 | - While holding all three buttons down, plug in the USB cable to your PC. 8 | The dial button on top of the Alarmo should light up red and a drive should appear on the PC. 9 | - Copy the `a.bin` to the newly appeared drive. 10 | - Copy the `MarkFile` to the drive. 11 | 12 | The Alarmo should disconnect from the PC and a picture of a cat is displayed on the screen. 13 | You can turn the dial to fade through different colors, press the back button to display a QR code with [AES key data](../key_bruteforcer/README.md), or press down on the dial to make the cat return. 14 | 15 | ## Building 16 | - Make sure to clone the repo with all submodules. 17 | - Enter the AES key and IV in the `key.py` file (as a hex string between the quotes). 18 | - Run `make`. 19 | 20 | ## Credits 21 | - https://github.com/nayuki/QR-Code-generator for QR Code generation. 22 | -------------------------------------------------------------------------------- /usb_payload/ciphtool.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # Tool to work with Alarmo CIPH files 3 | # Created by GaryOderNichts in 2024 4 | import sys 5 | import os 6 | from Crypto.Cipher import AES 7 | import hashlib 8 | from key import AES_KEY, AES_IV 9 | 10 | RSA_MOD = int.from_bytes([ 11 | 0xc1, 0xb5, 0x6f, 0xdf, 0x5f, 0xc9, 0xf8, 0x18, 0xf1, 0xd5, 0x08, 0x8f, 0x32, 0x5e, 0x47, 0xa1, 12 | 0x3c, 0xcf, 0x60, 0xa7, 0x99, 0xf5, 0xae, 0x0a, 0xf0, 0xcd, 0xc9, 0x04, 0xd9, 0xca, 0xf0, 0x15, 13 | 0x1c, 0xc6, 0x8e, 0x44, 0x96, 0x45, 0xd1, 0xe7, 0x41, 0x61, 0x13, 0x4a, 0x0c, 0xfe, 0xf7, 0x8c, 14 | 0x28, 0xce, 0x90, 0x0b, 0x61, 0x2d, 0x83, 0x02, 0xa3, 0xe9, 0x70, 0x3b, 0x6a, 0x8c, 0x6b, 0xa0, 15 | 0x42, 0x2d, 0x5b, 0xcf, 0xd1, 0x1b, 0xc2, 0x7a, 0x39, 0x99, 0x8f, 0x08, 0xeb, 0x06, 0x37, 0x81, 16 | 0x23, 0xe3, 0xbe, 0xe4, 0xe3, 0x37, 0x7d, 0x82, 0xb4, 0x4b, 0x35, 0xc6, 0x43, 0xa7, 0x69, 0x23, 17 | 0xbe, 0x3a, 0x5e, 0x3b, 0xa8, 0x6f, 0x8a, 0x92, 0xca, 0x43, 0x4f, 0x78, 0xb9, 0xfd, 0x62, 0xed, 18 | 0x71, 0x6a, 0xf3, 0x89, 0x57, 0xfc, 0x0e, 0x72, 0x6d, 0x29, 0x9c, 0x50, 0x1c, 0x27, 0x60, 0xd5, 19 | 0x0a, 0x58, 0x2e, 0x2f, 0xc4, 0x4a, 0x26, 0xff, 0x88, 0xf2, 0xac, 0x52, 0xcf, 0xcf, 0x56, 0x86, 20 | 0x92, 0x75, 0x93, 0xea, 0xbe, 0x6b, 0x7c, 0x41, 0xab, 0x76, 0x3b, 0x17, 0x4e, 0x49, 0x5e, 0xc5, 21 | 0xaa, 0xd3, 0x12, 0xed, 0x7d, 0x8b, 0x0b, 0x84, 0x7c, 0x32, 0x15, 0x94, 0x4a, 0x82, 0x17, 0xc9, 22 | 0x80, 0x5c, 0x73, 0x1b, 0xcd, 0xf8, 0x4c, 0x5c, 0x4f, 0x8c, 0xfd, 0x3b, 0x71, 0x60, 0xe2, 0x5c, 23 | 0x8a, 0x32, 0x3e, 0x0e, 0xab, 0xe1, 0x1a, 0xbd, 0x9b, 0xd2, 0x2f, 0x1a, 0x89, 0x8c, 0xdb, 0xe6, 24 | 0xcf, 0xce, 0xb6, 0x24, 0x5e, 0x2e, 0x99, 0x94, 0xc1, 0xc0, 0xa5, 0xfa, 0x13, 0xff, 0x27, 0x14, 25 | 0x28, 0xad, 0x63, 0xdf, 0x2e, 0x68, 0xa2, 0xf4, 0x7b, 0xfc, 0x4f, 0xe7, 0x22, 0x85, 0xcb, 0xd0, 26 | 0x9c, 0x40, 0xfb, 0x3f, 0xa8, 0x25, 0x77, 0x10, 0x8b, 0x11, 0x43, 0x8a, 0x1b, 0xe2, 0xb3, 0x83, 27 | ], byteorder='big') 28 | 29 | RSA_EXP = int.from_bytes([ 30 | 0x01, 0x00, 0x01, 31 | ], byteorder='big') 32 | 33 | # https://lapo.it/asn1js/#MDEwDQYJYIZIAWUDBAIBBQAEIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 34 | ASN1_PREFIX = b'\x30\x31\x30\x0d\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x01\x05\x00\x04\x20' 35 | 36 | def get_remaining_size(f): 37 | # Get file size 38 | offset = f.tell() 39 | f.seek(0, os.SEEK_END) 40 | size = f.tell() - offset 41 | f.seek(offset) 42 | return size 43 | 44 | def verify_signature(signature, hash): 45 | result = pow(signature, RSA_EXP, RSA_MOD).to_bytes(0x100, byteorder='big') 46 | 47 | if result[0] != 0x00 or result[1] != 0x01: 48 | print('Invalid signature') 49 | return False 50 | 51 | # Check padding 52 | padding_length = len(result) - 0x36 53 | if result[0x02:0x02+padding_length] != b'\xff' * padding_length: 54 | print('Invalid signature padding') 55 | return False 56 | 57 | if result[len(result) - 0x34] != 0x00: 58 | print('Invalid signature') 59 | return False 60 | 61 | # Check ASN.1 62 | if result[len(result) - 0x33:len(result) - 0x20] != ASN1_PREFIX: 63 | print('Invalid ASN.1 prefix') 64 | return False 65 | 66 | if result[len(result) - 0x20:] != hash: 67 | print('Invalid SHA256 hash') 68 | print(f'Expected SHA256: {result[len(result) - 0x20:].hex()}\nActual SHA256: {hash.hex()}') 69 | return False 70 | 71 | return True 72 | 73 | def verify(f): 74 | # Check header 75 | if f.read(8) != b'CIPH\x00\x00\x00\x00': 76 | print('Invalid file signature') 77 | sys.exit(1) 78 | 79 | # Get body size 80 | size = get_remaining_size(f) 81 | 82 | # Don't count signature 83 | size -= 0x100 84 | 85 | # Calculate body hash 86 | cipher = AES.new(AES_KEY, AES.MODE_CTR, nonce=AES_IV[:12]) 87 | sha256 = hashlib.sha256() 88 | while size > 0: 89 | to_read = min(size, 0x10000) 90 | 91 | # Decrypt and update hash 92 | sha256.update(cipher.decrypt(f.read(to_read))) 93 | size -= to_read 94 | 95 | # Read and decrypt the signature 96 | signature = int.from_bytes(cipher.decrypt(f.read(0x100)), byteorder='big') 97 | 98 | if verify_signature(signature, sha256.digest()) != True: 99 | print('Error: Invalid signature') 100 | sys.exit(1) 101 | 102 | print('Verified successfully!') 103 | 104 | 105 | def encrypt(f, outf): 106 | # Get size to encrypt 107 | size = get_remaining_size(f) 108 | 109 | # Add file signature 110 | outf.write(b'CIPH\x00\x00\x00\x00') 111 | 112 | cipher = AES.new(AES_KEY, AES.MODE_CTR, nonce=AES_IV[:12]) 113 | while size > 0: 114 | to_read = min(size, 0x10000) 115 | 116 | # Encrypt and write to file 117 | outf.write(cipher.encrypt(f.read(to_read))) 118 | size -= to_read 119 | 120 | # Add dummy signature 121 | outf.write(b'\x00' * 0x100) 122 | 123 | outf.close() 124 | 125 | def decrypt(f, outf): 126 | # Check header 127 | if f.read(8) != b'CIPH\x00\x00\x00\x00': 128 | print('Invalid file signature') 129 | sys.exit(1) 130 | 131 | # Get body size 132 | size = get_remaining_size(f) 133 | 134 | # Don't count signature 135 | size -= 0x100 136 | 137 | cipher = AES.new(AES_KEY, AES.MODE_CTR, nonce=AES_IV[:12]) 138 | sha256 = hashlib.sha256() 139 | while size > 0: 140 | to_read = min(size, 0x10000) 141 | 142 | # Decrypt, update hash and write file 143 | decrypted = cipher.decrypt(f.read(to_read)) 144 | sha256.update(decrypted) 145 | outf.write(decrypted) 146 | size -= to_read 147 | 148 | # Read and decrypt the signature 149 | signature_data = cipher.decrypt(f.read(0x100)) 150 | signature = int.from_bytes(signature_data) 151 | 152 | # TODO should the signature be added to the output file? 153 | # outf.write(signature_data) 154 | 155 | if verify_signature(signature, sha256.digest()) != True: 156 | print('Warning: Invalid signature') 157 | 158 | outf.close() 159 | 160 | 161 | def print_usage(file): 162 | print(f'Usage: {file} verify/encrypt/decrypt infile outfile') 163 | sys.exit(1) 164 | 165 | def main(argc, argv): 166 | if argc < 3: 167 | print_usage(argv[0]) 168 | 169 | if len(AES_KEY) != 16 or len(AES_IV) < 12: 170 | print('Error: Update AES_KEY and AES_IV in key.py') 171 | sys.exit(1) 172 | 173 | f = open(argv[2], 'rb') 174 | 175 | if argv[1] == 'verify': 176 | verify(f) 177 | elif argv[1] == 'encrypt': 178 | if argc < 4: 179 | print_usage(argv[0]) 180 | 181 | encrypt(f, open(sys.argv[3], 'wb')) 182 | elif argv[1] == 'decrypt': 183 | if argc < 4: 184 | print_usage(argv[0]) 185 | 186 | decrypt(f, open(sys.argv[3], 'wb')) 187 | 188 | f.close() 189 | 190 | if __name__ == '__main__': 191 | main(len(sys.argv), sys.argv) 192 | -------------------------------------------------------------------------------- /usb_payload/data/cat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GaryOderNichts/alarmo/846d26beae14a053775d8c1539d7a9c74bd68a12/usb_payload/data/cat.png -------------------------------------------------------------------------------- /usb_payload/imgconv.py: -------------------------------------------------------------------------------- 1 | from PIL import Image 2 | import sys, os 3 | 4 | def print_usage(file): 5 | print(f'Usage: {file} file') 6 | sys.exit(1) 7 | 8 | def main(argc, argv): 9 | if argc != 2: 10 | print_usage(argv[0]) 11 | 12 | image = Image.open(sys.argv[1]).resize((320, 240)).convert('RGB') 13 | 14 | print(f'static uint8_t {os.path.basename(argv[1].replace(".", "_"))}_data[] = {{') 15 | 16 | count = 0 17 | width, height = image.size 18 | for x in reversed(range(width)): 19 | for y in range(height): 20 | pixel = image.getpixel((x, y)) 21 | r, g, b = pixel 22 | print(f"0x{b:02x}, 0x{g:02x}, 0x{r:02x}, ", end='') 23 | 24 | count += 1 25 | 26 | if (count % 16) == 0: 27 | print() 28 | 29 | print('};') 30 | 31 | if __name__ == '__main__': 32 | main(len(sys.argv), sys.argv) 33 | -------------------------------------------------------------------------------- /usb_payload/key.py: -------------------------------------------------------------------------------- 1 | AES_KEY = bytearray.fromhex("1234") 2 | AES_IV = bytearray.fromhex("1234") 3 | -------------------------------------------------------------------------------- /usb_payload/link.ld: -------------------------------------------------------------------------------- 1 | OUTPUT_ARCH(arm) 2 | 3 | /* Entry Point */ 4 | ENTRY(Reset_Handler) 5 | 6 | /* Place stack in SRAM1 */ 7 | _estack = 0x24050000; 8 | 9 | SECTIONS 10 | { 11 | /* OCTOSPI base */ 12 | . = (0x70000000); 13 | 14 | __image_start = .; 15 | 16 | .binf_header : 17 | { 18 | /* 'BINF' magic */ 19 | LONG(0x464e4942); 20 | /* Unknown, has to be 1 */ 21 | LONG(0x00000001); 22 | /* Address where the image gets loaded to */ 23 | LONG(__image_start); 24 | /* Address to vector table */ 25 | LONG(__vector_table_start); 26 | /* Total image size */ 27 | LONG(__image_end - __image_start); 28 | /* Unknown */ 29 | BYTE(0); 30 | /* If this is loaded from a .shpac file, the .shpac path is copied here */ 31 | __shpac_path = .; 32 | 33 | . = ALIGN(0x100); 34 | } 35 | 36 | .isr_vector : 37 | { 38 | /* Vector table offset must be a multiple of 0x400 */ 39 | . = ALIGN(0x400); 40 | 41 | __vector_table_start = .; 42 | KEEP(*(.isr_vector)) /* Startup code */ 43 | 44 | . = ALIGN(0x100); 45 | } 46 | 47 | .text : 48 | { 49 | . = ALIGN(4); 50 | *(.text) /* .text sections (code) */ 51 | *(.text*) /* .text* sections (code) */ 52 | *(.glue_7) /* glue arm to thumb code */ 53 | *(.glue_7t) /* glue thumb to arm code */ 54 | *(.eh_frame) 55 | 56 | KEEP (*(.init)) 57 | KEEP (*(.fini)) 58 | 59 | . = ALIGN(4); 60 | _etext = .; /* define a global symbols at end of code */ 61 | } 62 | 63 | .rodata : 64 | { 65 | . = ALIGN(4); 66 | *(.rodata) /* .rodata sections (constants, strings, etc.) */ 67 | *(.rodata*) /* .rodata* sections (constants, strings, etc.) */ 68 | . = ALIGN(4); 69 | } 70 | 71 | .preinit_array : 72 | { 73 | PROVIDE_HIDDEN (__preinit_array_start = .); 74 | KEEP (*(.preinit_array*)) 75 | PROVIDE_HIDDEN (__preinit_array_end = .); 76 | } 77 | .init_array : 78 | { 79 | PROVIDE_HIDDEN (__init_array_start = .); 80 | KEEP (*(SORT(.init_array.*))) 81 | KEEP (*(.init_array*)) 82 | PROVIDE_HIDDEN (__init_array_end = .); 83 | } 84 | .fini_array : 85 | { 86 | PROVIDE_HIDDEN (__fini_array_start = .); 87 | KEEP (*(SORT(.fini_array.*))) 88 | KEEP (*(.fini_array*)) 89 | PROVIDE_HIDDEN (__fini_array_end = .); 90 | } 91 | 92 | /* used by the startup to initialize data */ 93 | _sidata = LOADADDR(.data); 94 | /* do not copy any data, since we're already loaded in RAM */ 95 | _sdata = .; 96 | _edata = .; 97 | 98 | .data : 99 | { 100 | . = ALIGN(4); 101 | *(.data) /* .data sections */ 102 | *(.data*) /* .data* sections */ 103 | 104 | . = ALIGN(4); 105 | } 106 | 107 | . = ALIGN(4); 108 | .bss : 109 | { 110 | /* This is used by the startup in order to initialize the .bss secion */ 111 | _sbss = .; /* define a global symbol at bss start */ 112 | __bss_start__ = _sbss; 113 | *(.bss) 114 | *(.bss*) 115 | *(COMMON) 116 | 117 | . = ALIGN(4); 118 | _ebss = .; /* define a global symbol at bss end */ 119 | __bss_end__ = _ebss; 120 | } 121 | 122 | __image_end = .; 123 | 124 | . = ALIGN(8); 125 | PROVIDE ( end = . ); 126 | PROVIDE ( _end = . ); 127 | } 128 | -------------------------------------------------------------------------------- /usb_payload/source/libalarmo/input.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Input code for the Nintendo Alarmo. 3 | * Created in 2024 by GaryOderNichts. 4 | */ 5 | #include "input.h" 6 | #include 7 | #include 8 | 9 | ALIGN_32BYTES (__IO uint16_t adcConvertedValues[3]); 10 | ALIGN_32BYTES (__IO uint16_t adcConvertedValues2[2]); 11 | 12 | void INPUT_Init(void) 13 | { 14 | // Start reading adc data into buffers 15 | HAL_ADC_Start_DMA(&adcHandle, (uint32_t *)adcConvertedValues, 3); 16 | HAL_ADC_Start_DMA(&adc2Handle, (uint32_t *)adcConvertedValues2, 2); 17 | } 18 | 19 | uint32_t INPUT_GetButtons(void) 20 | { 21 | uint32_t buttons = 0; 22 | 23 | if (HAL_GPIO_ReadPin(GPIOG, GPIO_PIN_5) == GPIO_PIN_RESET) { 24 | buttons |= BUTTON_NOTIFICATION; 25 | } 26 | 27 | if (HAL_GPIO_ReadPin(GPIOG, GPIO_PIN_6) == GPIO_PIN_RESET) { 28 | buttons |= BUTTON_BACK; 29 | } 30 | 31 | if (HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_5) == GPIO_PIN_RESET) { 32 | buttons |= BUTTON_DIAL; 33 | } 34 | 35 | return buttons; 36 | } 37 | 38 | float INPUT_GetDial(void) 39 | { 40 | // Invalidate adc buffers 41 | SCB_InvalidateDCache_by_Addr((void *)adcConvertedValues, sizeof(adcConvertedValues)); 42 | SCB_InvalidateDCache_by_Addr((void *)adcConvertedValues2, sizeof(adcConvertedValues2)); 43 | 44 | float val1 = (float) adcConvertedValues[0] / 65535.0f; 45 | float val2 = (float) adcConvertedValues2[0] / 65535.0f; 46 | 47 | float radians = atan2f(val1 - 0.5f, val2 - 0.5f); 48 | float degrees = (radians * 180.0f) / 3.141593f + 180.0f; 49 | 50 | return degrees; 51 | } 52 | -------------------------------------------------------------------------------- /usb_payload/source/libalarmo/input.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Input code for the Nintendo Alarmo. 3 | * Created in 2024 by GaryOderNichts. 4 | */ 5 | #pragma once 6 | 7 | #include 8 | 9 | enum { 10 | BUTTON_NOTIFICATION = (1u << 0), 11 | BUTTON_BACK = (1u << 1), 12 | BUTTON_DIAL = (1u << 2), 13 | }; 14 | 15 | void INPUT_Init(void); 16 | 17 | uint32_t INPUT_GetButtons(void); 18 | 19 | float INPUT_GetDial(void); 20 | -------------------------------------------------------------------------------- /usb_payload/source/libalarmo/lcd.c: -------------------------------------------------------------------------------- 1 | /** 2 | * ST7789 LCD code for the Nintendo Alarmo. 3 | * Created in 2024 by GaryOderNichts. 4 | */ 5 | #include "lcd.h" 6 | #include "main.h" 7 | #include 8 | 9 | #define USE_DMA 1 10 | 11 | #define LCD_COMMAND (*(volatile uint8_t *) 0xc0000000) 12 | 13 | #define LCD_RS_PIN (6) 14 | #define LCD_DATA_ADDRESS (0xc0000000lu + (1lu << (LCD_RS_PIN + 1))) 15 | #define LCD_DATA8 (*(volatile uint8_t *)LCD_DATA_ADDRESS) 16 | #define LCD_DATA16 (*(volatile uint16_t *)LCD_DATA_ADDRESS) 17 | 18 | static void LCD_Select(void) 19 | { 20 | HAL_GPIO_WritePin(GPIOC, GPIO_PIN_7, GPIO_PIN_RESET); 21 | } 22 | 23 | static void LCD_Deselect(void) 24 | { 25 | HAL_GPIO_WritePin(GPIOC, GPIO_PIN_7, GPIO_PIN_SET); 26 | } 27 | 28 | static void LCD_WriteCommand(uint8_t cmd) 29 | { 30 | LCD_COMMAND = cmd; 31 | } 32 | 33 | static void LCD_WriteData(uint8_t data) 34 | { 35 | LCD_DATA8 = data; 36 | } 37 | 38 | static void LCD_InitSequence(void) 39 | { 40 | LCD_Select(); 41 | LCD_WriteCommand(0x11); 42 | LCD_Deselect(); 43 | 44 | HAL_Delay(120); 45 | 46 | LCD_Select(); 47 | LCD_WriteCommand(0x36); 48 | LCD_WriteData(0x0); 49 | LCD_Deselect(); 50 | 51 | LCD_Select(); 52 | LCD_WriteCommand(0x21); 53 | LCD_Deselect(); 54 | 55 | LCD_Select(); 56 | LCD_WriteCommand(0x3a); 57 | LCD_WriteData(0x6); 58 | LCD_Deselect(); 59 | 60 | LCD_Select(); 61 | LCD_WriteCommand(0xb7); 62 | LCD_WriteData(0x37); 63 | LCD_Deselect(); 64 | 65 | LCD_Select(); 66 | LCD_WriteCommand(0xbb); 67 | LCD_WriteData(0x14); 68 | LCD_Deselect(); 69 | 70 | LCD_Select(); 71 | LCD_WriteCommand(0xc0); 72 | LCD_WriteData(0x2c); 73 | LCD_Deselect(); 74 | 75 | LCD_Select(); 76 | LCD_WriteCommand(0xc2); 77 | LCD_WriteData(0x1); 78 | LCD_WriteData(0xff); 79 | LCD_Deselect(); 80 | 81 | LCD_Select(); 82 | LCD_WriteCommand(0xc3); 83 | LCD_WriteData(0x19); 84 | LCD_Deselect(); 85 | 86 | LCD_Select(); 87 | LCD_WriteCommand(0xc6); 88 | LCD_WriteData(0x17); 89 | LCD_Deselect(); 90 | 91 | LCD_Select(); 92 | LCD_WriteCommand(0xd0); 93 | LCD_WriteData(0xa4); 94 | LCD_WriteData(0xb3); 95 | LCD_Deselect(); 96 | 97 | LCD_Select(); 98 | LCD_WriteCommand(0xe0); 99 | LCD_WriteData(0xa0); 100 | LCD_WriteData(0x3); 101 | LCD_WriteData(0x6); 102 | LCD_WriteData(0x7); 103 | LCD_WriteData(0x6); 104 | LCD_WriteData(0x24); 105 | LCD_WriteData(0x25); 106 | LCD_WriteData(0x33); 107 | LCD_WriteData(0x3d); 108 | LCD_WriteData(0x27); 109 | LCD_WriteData(0x14); 110 | LCD_WriteData(0x14); 111 | LCD_WriteData(0x28); 112 | LCD_WriteData(0x2f); 113 | LCD_Deselect(); 114 | 115 | LCD_Select(); 116 | LCD_WriteCommand(0xe1); 117 | LCD_WriteData(0xa0); 118 | LCD_WriteData(0x3); 119 | LCD_WriteData(0x6); 120 | LCD_WriteData(0x7); 121 | LCD_WriteData(0x6); 122 | LCD_WriteData(0x24); 123 | LCD_WriteData(0x25); 124 | LCD_WriteData(0x33); 125 | LCD_WriteData(0x3d); 126 | LCD_WriteData(0x27); 127 | LCD_WriteData(0x14); 128 | LCD_WriteData(0x14); 129 | LCD_WriteData(0x28); 130 | LCD_WriteData(0x2f); 131 | LCD_Deselect(); 132 | } 133 | 134 | static void LCD_FRCTR2(uint8_t p1, uint8_t p2) 135 | { 136 | LCD_Select(); 137 | 138 | LCD_WriteCommand(0xc6); 139 | LCD_WriteData((p1 << 5) | (p2 & 0x1f)); 140 | 141 | LCD_Deselect(); 142 | } 143 | 144 | static void LCD_INVON(void) 145 | { 146 | LCD_Select(); 147 | 148 | LCD_WriteCommand(0x21); 149 | 150 | LCD_Deselect(); 151 | } 152 | 153 | static void LCD_MADCTL(uint8_t p1, uint8_t p2, uint8_t p3, uint8_t p4) 154 | { 155 | LCD_Select(); 156 | 157 | LCD_WriteCommand(0x36); 158 | LCD_WriteData((p2 << 6) | (p1 << 7) | (p3 << 5) | (p4 << 3)); 159 | 160 | LCD_Deselect(); 161 | } 162 | 163 | static void LCD_DISPOFF(void) 164 | { 165 | LCD_Select(); 166 | 167 | LCD_WriteCommand(0x28); 168 | 169 | LCD_Deselect(); 170 | } 171 | 172 | void LCD_DISPON(void) 173 | { 174 | LCD_Select(); 175 | 176 | LCD_WriteCommand(0x29); 177 | 178 | LCD_Deselect(); 179 | } 180 | 181 | static void LCD_SLPOUT(void) 182 | { 183 | LCD_Select(); 184 | 185 | LCD_WriteCommand(0x11); 186 | 187 | LCD_Deselect(); 188 | } 189 | 190 | static void LCD_COLMOD(uint8_t p1, uint8_t p2) 191 | { 192 | LCD_Select(); 193 | 194 | LCD_WriteCommand(0x3a); 195 | LCD_WriteData(p2 | (p1 << 4)); 196 | 197 | LCD_Deselect(); 198 | } 199 | 200 | static void LCD_RAMCTRL(uint8_t p2, uint8_t p3, uint8_t p4, uint8_t p5, uint8_t p6) 201 | { 202 | LCD_Select(); 203 | 204 | LCD_WriteCommand(0xb0); 205 | LCD_WriteData(p3 | (p2 << 4)); 206 | LCD_WriteData(p5 | (p4 << 3) | (p6 << 2) | 0xc0); 207 | 208 | LCD_Deselect(); 209 | } 210 | 211 | static void LCD_CASET(uint16_t p1, uint16_t p2) 212 | { 213 | LCD_Select(); 214 | 215 | LCD_WriteCommand(0x2a); 216 | LCD_WriteData((uint8_t)(p1 >> 8)); 217 | LCD_WriteData((uint8_t)(p1)); 218 | LCD_WriteData((uint8_t)(p2 >> 8)); 219 | LCD_WriteData((uint8_t)(p2)); 220 | 221 | LCD_Deselect(); 222 | } 223 | 224 | static void LCD_RASET(uint16_t p1, uint16_t p2) 225 | { 226 | LCD_Select(); 227 | 228 | LCD_WriteCommand(0x2b); 229 | LCD_WriteData((uint8_t)(p1 >> 8)); 230 | LCD_WriteData((uint8_t)(p1)); 231 | LCD_WriteData((uint8_t)(p2 >> 8)); 232 | LCD_WriteData((uint8_t)(p2)); 233 | 234 | LCD_Deselect(); 235 | } 236 | 237 | void LCD_RDID(uint32_t* outId) 238 | { 239 | LCD_Select(); 240 | LCD_WriteCommand(0x04); // RDID 241 | *outId |= LCD_DATA8 << 24; 242 | *outId |= LCD_DATA8 << 16; 243 | *outId |= LCD_DATA8 << 8; 244 | *outId |= LCD_DATA8; 245 | LCD_Deselect(); 246 | } 247 | 248 | void LCD_Init(void) 249 | { 250 | HAL_MDMA_Abort(&mdmaHandle); 251 | 252 | LCD_Deselect(); 253 | 254 | HAL_GPIO_WritePin(GPIOG, GPIO_PIN_4, GPIO_PIN_RESET); 255 | HAL_GPIO_WritePin(GPIOG, GPIO_PIN_4, GPIO_PIN_SET); 256 | HAL_Delay(120); 257 | 258 | LCD_InitSequence(); 259 | LCD_FRCTR2(0, 0x17); 260 | LCD_INVON(); 261 | LCD_MADCTL(0, 0, 0, 1); 262 | LCD_DISPOFF(); 263 | LCD_SLPOUT(); 264 | LCD_COLMOD(5, 6); 265 | LCD_RAMCTRL(0, 0, 0, 0, 0); 266 | LCD_CASET(0, SCREEN_HEIGHT - 1); 267 | LCD_RASET(0, SCREEN_WIDTH - 1); 268 | } 269 | 270 | static void LCD_DrawData(const uint8_t *source, uint32_t size) 271 | { 272 | #if USE_DMA == 1 273 | // flush cache for dma 274 | SCB_CleanDCache_by_Addr((uint32_t *)source, size); 275 | 276 | uint32_t offset = 0; 277 | while (size > 0) { 278 | uint32_t to_copy = size; 279 | if (to_copy > 65536U) { 280 | to_copy = 65536U; 281 | } 282 | 283 | if (HAL_MDMA_Start(&mdmaHandle, (uint32_t)source + offset, (uint32_t) &LCD_DATA16, to_copy, 1) != HAL_OK) { 284 | while (1) 285 | ; 286 | } 287 | 288 | // TODO instead of polling, perform irq driven transfers 289 | if (HAL_MDMA_PollForTransfer(&mdmaHandle, HAL_MDMA_FULL_TRANSFER, 1000) != HAL_OK) { 290 | while (1) 291 | ; 292 | } 293 | 294 | size -= to_copy; 295 | offset += to_copy; 296 | } 297 | #else // Software 298 | for (uint32_t i = 0; i < size; i += 2) { 299 | LCD_DATA16 = (source[i] << 8) | source[i + 1]; 300 | } 301 | #endif 302 | } 303 | 304 | void LCD_DrawRect(uint32_t x0, uint32_t y0, uint32_t x1, uint32_t y1, uint8_t r, uint8_t g, uint8_t b) 305 | { 306 | uint32_t size = y1 * x1 + ((y1 * x1) % 2); 307 | 308 | uint32_t rowsize = size; 309 | if (rowsize > SCREEN_HEIGHT) { 310 | rowsize = SCREEN_HEIGHT; 311 | } 312 | 313 | static uint8_t color_buffer[SCREEN_HEIGHT * 3]; 314 | for (uint32_t i = 0; i < rowsize; i++) { 315 | color_buffer[(i*3)+2] = r; 316 | color_buffer[(i*3)+1] = g; 317 | color_buffer[(i*3) ] = b; 318 | } 319 | 320 | // flush cache for dma 321 | SCB_CleanDCache_by_Addr((uint32_t *)&color_buffer[0], rowsize); 322 | 323 | LCD_RASET(SCREEN_WIDTH - (x0 + x1), SCREEN_WIDTH - x0 - 1); 324 | LCD_CASET(y0, (y1 + y0) - 1); 325 | 326 | LCD_Select(); 327 | LCD_WriteCommand(0x2c); 328 | 329 | while (size > 0) { 330 | uint32_t to_copy = size; 331 | if (to_copy > SCREEN_HEIGHT) { 332 | to_copy = SCREEN_HEIGHT; 333 | } 334 | 335 | LCD_DrawData(&color_buffer[0], to_copy * 3); 336 | 337 | size -= to_copy; 338 | } 339 | 340 | LCD_Deselect(); 341 | } 342 | 343 | void LCD_DrawScreenBuffer(const uint8_t *buffer, uint32_t size) 344 | { 345 | // flush cache for dma 346 | SCB_CleanDCache_by_Addr((uint32_t *)buffer, size); 347 | 348 | LCD_RASET(0, SCREEN_WIDTH - 1); 349 | LCD_CASET(0, SCREEN_HEIGHT - 1); 350 | 351 | LCD_Select(); 352 | LCD_WriteCommand(0x2c); 353 | LCD_DrawData(buffer, size); 354 | LCD_Deselect(); 355 | } 356 | 357 | void LCD_SetBrightness(float brightness) 358 | { 359 | __HAL_TIM_SET_COMPARE(&tim3Handle, TIM_CHANNEL_4, brightness * tim3Handle.Init.Period); 360 | HAL_TIM_PWM_Start(&tim3Handle, TIM_CHANNEL_4); 361 | } 362 | -------------------------------------------------------------------------------- /usb_payload/source/libalarmo/lcd.h: -------------------------------------------------------------------------------- 1 | /** 2 | * ST7789 LCD code for the Nintendo Alarmo. 3 | * Created in 2024 by GaryOderNichts. 4 | */ 5 | #pragma once 6 | 7 | #include 8 | 9 | #define SCREEN_HEIGHT 240 10 | #define SCREEN_WIDTH 320 11 | 12 | void LCD_Init(void); 13 | 14 | void LCD_RDID(uint32_t* outId); 15 | 16 | void LCD_DISPON(void); 17 | 18 | void LCD_SetBrightness(float brightness); 19 | 20 | void LCD_DrawRect(uint32_t x0, uint32_t y0, uint32_t x1, uint32_t y1, uint8_t r, uint8_t g, uint8_t b); 21 | 22 | void LCD_DrawScreenBuffer(const uint8_t *buffer, uint32_t size); 23 | -------------------------------------------------------------------------------- /usb_payload/source/main.c: -------------------------------------------------------------------------------- 1 | #include "main.h" 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include "system_stm32h7xx.h" 8 | #include "libalarmo/lcd.h" 9 | #include "libalarmo/input.h" 10 | #include "qrcodegen.h" 11 | 12 | #include "cat_png.h" 13 | 14 | typedef struct { 15 | uint32_t iv[4]; 16 | uint32_t encrypted_parts[4][4]; 17 | } aes_data_t; 18 | 19 | static void DMA_Init(void); 20 | static void FMC_Init(void); 21 | static void TIM3_Init(void); 22 | static void MDMA_Init(void); 23 | static void ADC_Init(void); 24 | 25 | static void hsv2rgb(float h, float s, float v, float *r, float *g, float *b); 26 | 27 | static void CRYP_AES_CTR_Encrypt(uint32_t *counter, void *outData, uint32_t outSize, const void *inData, uint32_t inSize); 28 | static void get_aes_data(aes_data_t *aesData); 29 | static void generate_qr(const void *data, size_t size, uint8_t *screenBuffer); 30 | 31 | SRAM_HandleTypeDef fmcHandle; 32 | TIM_HandleTypeDef tim3Handle; 33 | MDMA_HandleTypeDef mdmaHandle; 34 | ADC_HandleTypeDef adcHandle; 35 | DMA_HandleTypeDef dmaHandle; 36 | ADC_HandleTypeDef adc2Handle; 37 | DMA_HandleTypeDef dma2Handle; 38 | 39 | static uint8_t qrBuffer[SCREEN_WIDTH * SCREEN_HEIGHT * 3]; 40 | 41 | int main(void) 42 | { 43 | SCB_EnableICache(); 44 | SCB_EnableDCache(); 45 | __enable_irq(); 46 | 47 | HAL_Init(); 48 | 49 | // TODO we just run with whatever the 2ndloader configured for now 50 | // SystemClock_Config(); 51 | // PeriphClock_Config(); 52 | 53 | // Enable DMA streams 54 | DMA_Init(); 55 | 56 | // Initialize FMC for interfacing with the LCD 57 | FMC_Init(); 58 | 59 | // Initialize MDMA for DMA LCD transfers 60 | MDMA_Init(); 61 | 62 | // Initialize timer 3 for the LCD backlight 63 | TIM3_Init(); 64 | 65 | // Enable the ADCs for the dial wheel 66 | ADC_Init(); 67 | 68 | // Initialize inputs 69 | INPUT_Init(); 70 | 71 | // Initialize the LCD 72 | LCD_Init(); 73 | 74 | uint32_t lcdId = 0; 75 | LCD_RDID(&lcdId); 76 | 77 | // Setup backlight 78 | LCD_SetBrightness(1.0f); 79 | 80 | // Clear screen 81 | LCD_DrawRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 255, 0, 0); 82 | 83 | // Draw cat 84 | LCD_DrawScreenBuffer(cat_png_data, sizeof(cat_png_data)); 85 | 86 | // Turn on the display 87 | LCD_DISPON(); 88 | 89 | // Generate QR code 90 | aes_data_t aesData; 91 | get_aes_data(&aesData); 92 | generate_qr(&aesData, sizeof(aesData), qrBuffer); 93 | 94 | // Main loop 95 | float lastDial = INPUT_GetDial(); 96 | while (1) { 97 | uint32_t buttons = INPUT_GetButtons(); 98 | float dial = INPUT_GetDial(); 99 | 100 | // Draw cat for dial button presses 101 | if (buttons & BUTTON_DIAL) { 102 | LCD_DrawScreenBuffer(cat_png_data, sizeof(cat_png_data)); 103 | } 104 | 105 | // Draw qr code for back button presses 106 | if (buttons & BUTTON_BACK) { 107 | LCD_DrawScreenBuffer(qrBuffer, sizeof(qrBuffer)); 108 | } 109 | 110 | // Draw red screen for notif button presses 111 | if (buttons & BUTTON_NOTIFICATION) { 112 | LCD_DrawRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 255, 0, 0); 113 | } 114 | 115 | // Fade through colors for dial turns 116 | if (fabs(lastDial - dial) >= 1.5f) { 117 | float r, g, b; 118 | hsv2rgb(dial / 360.0f, 1.0f, 1.0f, &r, &g, &b); 119 | LCD_DrawRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, r * 255, g * 255, b * 255); 120 | lastDial = dial; 121 | } 122 | 123 | HAL_Delay(10); 124 | } 125 | } 126 | 127 | static void DMA_Init(void) 128 | { 129 | __HAL_RCC_DMA1_CLK_ENABLE(); 130 | __HAL_RCC_DMA2_CLK_ENABLE(); 131 | 132 | HAL_NVIC_SetPriority(DMA1_Stream0_IRQn, 5, 0); 133 | HAL_NVIC_EnableIRQ(DMA1_Stream0_IRQn); 134 | HAL_NVIC_SetPriority(DMA1_Stream1_IRQn, 5, 0); 135 | HAL_NVIC_EnableIRQ(DMA1_Stream1_IRQn); 136 | HAL_NVIC_SetPriority(DMA1_Stream2_IRQn, 5, 0); 137 | HAL_NVIC_EnableIRQ(DMA1_Stream2_IRQn); 138 | HAL_NVIC_SetPriority(DMA1_Stream3_IRQn, 5, 0); 139 | HAL_NVIC_EnableIRQ(DMA1_Stream3_IRQn); 140 | HAL_NVIC_SetPriority(DMA2_Stream1_IRQn, 0, 0); 141 | HAL_NVIC_EnableIRQ(DMA2_Stream1_IRQn); 142 | HAL_NVIC_SetPriority(DMA2_Stream2_IRQn, 0, 0); 143 | HAL_NVIC_EnableIRQ(DMA2_Stream2_IRQn); 144 | } 145 | 146 | static void FMC_Init(void) 147 | { 148 | FMC_NORSRAM_TimingTypeDef timing; 149 | 150 | fmcHandle.Instance = FMC_Bank1_R; 151 | fmcHandle.Extended = FMC_Bank1E_R; 152 | 153 | fmcHandle.Init.WaitSignalActive = 0; 154 | fmcHandle.Init.WriteOperation = FMC_WRITE_OPERATION_ENABLE; 155 | fmcHandle.Init.NSBank = FMC_NORSRAM_BANK1; 156 | fmcHandle.Init.MemoryDataWidth = FMC_NORSRAM_MEM_BUS_WIDTH_16; 157 | fmcHandle.Init.BurstAccessMode = FMC_BURST_ACCESS_MODE_DISABLE; 158 | fmcHandle.Init.DataAddressMux = FMC_DATA_ADDRESS_MUX_DISABLE; 159 | fmcHandle.Init.MemoryType = FMC_MEMORY_TYPE_SRAM; 160 | fmcHandle.Init.WaitSignalPolarity = FMC_WAIT_SIGNAL_POLARITY_LOW; 161 | 162 | timing.BusTurnAroundDuration = 0; 163 | timing.CLKDivision = 1; 164 | timing.DataLatency = 0; 165 | timing.AccessMode = 0; 166 | timing.DataSetupTime = 2; 167 | timing.AddressSetupTime = 2; 168 | timing.AddressHoldTime = 0; 169 | if (HAL_SRAM_Init(&fmcHandle, &timing, NULL) != HAL_OK) { 170 | while (1) 171 | ; 172 | } 173 | 174 | HAL_SetFMCMemorySwappingConfig(FMC_SWAPBMAP_SDRAM_SRAM); 175 | } 176 | 177 | static void TIMx_PWM_MspInit(TIM_HandleTypeDef *handle) 178 | { 179 | GPIO_InitTypeDef gpioConfig = { 0 }; 180 | 181 | if (handle->Instance == TIM3) { 182 | __HAL_RCC_GPIOB_CLK_ENABLE(); 183 | __HAL_RCC_GPIOC_CLK_ENABLE(); 184 | 185 | gpioConfig.Alternate = GPIO_AF2_TIM3; 186 | gpioConfig.Pull = GPIO_NOPULL; 187 | gpioConfig.Speed = GPIO_SPEED_FREQ_LOW; 188 | gpioConfig.Pin = GPIO_PIN_1; 189 | gpioConfig.Mode = GPIO_MODE_AF_PP; 190 | HAL_GPIO_Init(GPIOB, &gpioConfig); 191 | 192 | gpioConfig.Pin = GPIO_PIN_8; 193 | gpioConfig.Alternate = GPIO_AF2_TIM3; 194 | gpioConfig.Speed = GPIO_SPEED_FREQ_LOW; 195 | gpioConfig.Pull = GPIO_NOPULL; 196 | gpioConfig.Mode = GPIO_MODE_AF_PP; 197 | HAL_GPIO_Init(GPIOC, &gpioConfig); 198 | } 199 | } 200 | 201 | static void TIM3_Init(void) 202 | { 203 | TIM_MasterConfigTypeDef masterConfig = { 0 }; 204 | TIM_OC_InitTypeDef channelConfig = { 0 }; 205 | 206 | tim3Handle.Instance = TIM3; 207 | tim3Handle.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE; 208 | tim3Handle.Init.Prescaler = 0; 209 | tim3Handle.Init.CounterMode = TIM_COUNTERMODE_UP; 210 | tim3Handle.Init.Period = 0xffff; 211 | tim3Handle.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; 212 | if (HAL_TIM_PWM_Init(&tim3Handle) != HAL_OK) { 213 | while (1) 214 | ; 215 | } 216 | 217 | masterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE; 218 | masterConfig.MasterOutputTrigger = TIM_TRGO_RESET; 219 | if (HAL_TIMEx_MasterConfigSynchronization(&tim3Handle, &masterConfig) != HAL_OK) { 220 | while (1) 221 | ; 222 | } 223 | 224 | channelConfig.OCFastMode = TIM_OCFAST_DISABLE; 225 | channelConfig.Pulse = 0; 226 | channelConfig.OCPolarity = TIM_OCPOLARITY_HIGH; 227 | channelConfig.OCMode = TIM_OCMODE_PWM1; 228 | if (HAL_TIM_PWM_ConfigChannel(&tim3Handle, &channelConfig, TIM_CHANNEL_3) != HAL_OK) { 229 | while (1) 230 | ; 231 | } 232 | 233 | if (HAL_TIM_PWM_ConfigChannel(&tim3Handle, &channelConfig, TIM_CHANNEL_4) != HAL_OK) { 234 | while (1) 235 | ; 236 | } 237 | 238 | TIMx_PWM_MspInit(&tim3Handle); 239 | } 240 | 241 | static void MDMA_Init(void) 242 | { 243 | __HAL_RCC_MDMA_CLK_ENABLE(); 244 | 245 | mdmaHandle.Instance = MDMA_Channel0; 246 | 247 | mdmaHandle.Init.BufferTransferLength = 0x80; 248 | mdmaHandle.Init.DataAlignment = MDMA_DATAALIGN_PACKENABLE; 249 | mdmaHandle.Init.Request = MDMA_REQUEST_SW; 250 | mdmaHandle.Init.DestinationInc = MDMA_DEST_INC_DISABLE; 251 | mdmaHandle.Init.SourceDataSize = MDMA_SRC_DATASIZE_HALFWORD; 252 | mdmaHandle.Init.DestDataSize = MDMA_DEST_DATASIZE_HALFWORD; 253 | mdmaHandle.Init.TransferTriggerMode = MDMA_BLOCK_TRANSFER; 254 | mdmaHandle.Init.Priority = MDMA_PRIORITY_VERY_HIGH; 255 | mdmaHandle.Init.Endianness = MDMA_LITTLE_BYTE_ENDIANNESS_EXCHANGE; 256 | mdmaHandle.Init.SourceInc = MDMA_SRC_INC_HALFWORD; 257 | mdmaHandle.Init.SourceBurst = MDMA_SOURCE_BURST_SINGLE; 258 | mdmaHandle.Init.DestBurst = MDMA_DEST_BURST_SINGLE; 259 | mdmaHandle.Init.SourceBlockAddressOffset = 0x0; 260 | mdmaHandle.Init.DestBlockAddressOffset = 0x0; 261 | 262 | if (HAL_MDMA_Init(&mdmaHandle) != HAL_OK) { 263 | while (1) 264 | ; 265 | } 266 | 267 | // TODO 268 | // HAL_NVIC_SetPriority(MDMA_IRQn, 5, 0); 269 | // HAL_NVIC_EnableIRQ(MDMA_IRQn); 270 | } 271 | 272 | static void ADC_Init(void) 273 | { 274 | RCC_PeriphCLKInitTypeDef RCC_PeriphCLKInitStruct = { 0 }; 275 | RCC_PeriphCLKInitStruct.PeriphClockSelection = RCC_PERIPHCLK_ADC; 276 | RCC_PeriphCLKInitStruct.AdcClockSelection = RCC_ADCCLKSOURCE_PLL2; 277 | HAL_RCCEx_PeriphCLKConfig(&RCC_PeriphCLKInitStruct); 278 | 279 | adcHandle.Instance = ADC1; 280 | 281 | adcHandle.Init.Overrun = ADC_OVR_DATA_OVERWRITTEN; 282 | adcHandle.Init.LeftBitShift = ADC_LEFTBITSHIFT_NONE; 283 | adcHandle.Init.OversamplingMode = ENABLE; 284 | adcHandle.Init.Oversampling.Ratio = 0x10; 285 | adcHandle.Init.Oversampling.RightBitShift = ADC_RIGHTBITSHIFT_4; 286 | adcHandle.Init.Oversampling.TriggeredMode = ADC_TRIGGEREDMODE_SINGLE_TRIGGER; 287 | adcHandle.Init.Oversampling.OversamplingStopReset = ADC_REGOVERSAMPLING_CONTINUED_MODE; 288 | adcHandle.Init.ExternalTrigConv = ADC_SOFTWARE_START; 289 | adcHandle.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE; 290 | adcHandle.Init.ConversionDataManagement = ADC_CONVERSIONDATA_DMA_CIRCULAR; 291 | adcHandle.Init.Resolution = ADC_RESOLUTION_16B; 292 | adcHandle.Init.ScanConvMode = ADC_SCAN_ENABLE; 293 | adcHandle.Init.EOCSelection = ADC_EOC_SINGLE_CONV; 294 | adcHandle.Init.LowPowerAutoWait = DISABLE; 295 | adcHandle.Init.ContinuousConvMode = ENABLE; 296 | adcHandle.Init.NbrOfConversion = 0x3; 297 | adcHandle.Init.DiscontinuousConvMode = DISABLE; 298 | adcHandle.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV8; 299 | if (HAL_ADC_Init(&adcHandle) != HAL_OK) { 300 | while (1) 301 | ; 302 | } 303 | 304 | ADC_MultiModeTypeDef multiMode = { 0 }; 305 | multiMode.Mode = ADC_MODE_INDEPENDENT; 306 | if (HAL_ADCEx_MultiModeConfigChannel(&adcHandle, &multiMode) != HAL_OK) { 307 | while (1) 308 | ; 309 | } 310 | 311 | ADC_ChannelConfTypeDef channelConf = { 0 }; 312 | channelConf.OffsetSignedSaturation = DISABLE; 313 | channelConf.Offset = 0x0; 314 | channelConf.OffsetNumber = ADC_OFFSET_NONE; 315 | channelConf.SingleDiff = ADC_SINGLE_ENDED; 316 | channelConf.SamplingTime = ADC_SAMPLETIME_64CYCLES_5; 317 | channelConf.Rank = ADC_REGULAR_RANK_1; 318 | channelConf.Channel = ADC_CHANNEL_4; 319 | if (HAL_ADC_ConfigChannel(&adcHandle, &channelConf) != HAL_OK) { 320 | while (1) 321 | ; 322 | } 323 | 324 | channelConf.Rank = ADC_REGULAR_RANK_2; 325 | if (HAL_ADC_ConfigChannel(&adcHandle, &channelConf) != HAL_OK) { 326 | while (1) 327 | ; 328 | } 329 | 330 | channelConf.Rank = ADC_REGULAR_RANK_3; 331 | channelConf.Channel = ADC_CHANNEL_10; 332 | if (HAL_ADC_ConfigChannel(&adcHandle, &channelConf) != HAL_OK) { 333 | while (1) 334 | ; 335 | } 336 | 337 | HAL_ADCEx_Calibration_Start(&adcHandle, ADC_CALIB_OFFSET, ADC_SINGLE_ENDED); 338 | 339 | adc2Handle.Instance = ADC2; 340 | 341 | adc2Handle.Init.Oversampling.RightBitShift = ADC_RIGHTBITSHIFT_4; 342 | adc2Handle.Init.Oversampling.TriggeredMode = ADC_TRIGGEREDMODE_SINGLE_TRIGGER; 343 | adc2Handle.Init.ConversionDataManagement = ADC_CONVERSIONDATA_DMA_CIRCULAR; 344 | adc2Handle.Init.Overrun = ADC_OVR_DATA_OVERWRITTEN; 345 | adc2Handle.Init.LeftBitShift = ADC_LEFTBITSHIFT_NONE; 346 | adc2Handle.Init.OversamplingMode = ENABLE; 347 | adc2Handle.Init.Oversampling.Ratio = 0x10; 348 | adc2Handle.Init.Oversampling.OversamplingStopReset = ADC_REGOVERSAMPLING_CONTINUED_MODE; 349 | adc2Handle.Init.ExternalTrigConv = ADC_SOFTWARE_START; 350 | adc2Handle.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE; 351 | adc2Handle.Init.ScanConvMode = ADC_SCAN_ENABLE; 352 | adc2Handle.Init.EOCSelection = ADC_EOC_SINGLE_CONV; 353 | adc2Handle.Init.LowPowerAutoWait = DISABLE; 354 | adc2Handle.Init.ContinuousConvMode = ENABLE; 355 | adc2Handle.Init.Resolution = ADC_RESOLUTION_16B; 356 | adc2Handle.Init.NbrOfConversion = 0x2; 357 | adc2Handle.Init.DiscontinuousConvMode = DISABLE; 358 | adc2Handle.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV8; 359 | if (HAL_ADC_Init(&adc2Handle) != HAL_OK) { 360 | while (1) 361 | ; 362 | } 363 | 364 | channelConf.SingleDiff = ADC_SINGLE_ENDED; 365 | channelConf.OffsetSignedSaturation = DISABLE; 366 | channelConf.OffsetNumber = ADC_OFFSET_NONE; 367 | channelConf.Offset = 0x0; 368 | channelConf.SamplingTime = ADC_SAMPLETIME_64CYCLES_5; 369 | channelConf.Rank = ADC_REGULAR_RANK_1; 370 | channelConf.Channel = ADC_CHANNEL_9; 371 | if (HAL_ADC_ConfigChannel(&adc2Handle, &channelConf) != HAL_OK) { 372 | while (1) 373 | ; 374 | } 375 | 376 | channelConf.Rank = ADC_REGULAR_RANK_2; 377 | if (HAL_ADC_ConfigChannel(&adc2Handle, &channelConf) != HAL_OK) { 378 | while (1) 379 | ; 380 | } 381 | 382 | HAL_ADCEx_Calibration_Start(&adc2Handle, ADC_CALIB_OFFSET, ADC_SINGLE_ENDED); 383 | } 384 | 385 | static void hsv2rgb(float h, float s, float v, float *r, float *g, float *b) 386 | { 387 | float p, q, t, fract; 388 | int i; 389 | 390 | i = (int) floor(h * 6); 391 | fract = h * 6.0f - i; 392 | p = v * (1.0f - s); 393 | q = v * (1.0f - fract * s); 394 | t = v * (1.0f - (1 - fract) * s); 395 | 396 | switch (i % 6) { 397 | case 0: 398 | *r = v; *g = t; *b = p; 399 | break; 400 | case 1: 401 | *r = q; *g = v; *b = p; 402 | break; 403 | case 2: 404 | *r = p; *g = v; *b = t; 405 | break; 406 | case 3: 407 | *r = p; *g = q; *b = v; 408 | break; 409 | case 4: 410 | *r = t; *g = p; *b = v; 411 | break; 412 | case 5: 413 | *r = v; *g = p; *b = q; 414 | break; 415 | } 416 | } 417 | 418 | static void CRYP_ProcessData(uint32_t* outData, uint32_t outCount, const uint32_t* inData, uint32_t inCount) 419 | { 420 | // Enable CRYP 421 | CRYP->CR |= CRYP_CR_CRYPEN; 422 | 423 | uint32_t inOffset = 0; 424 | uint32_t outOffset = 0; 425 | while (outOffset < outCount) { 426 | // Push data if input FIFO isn't full 427 | while (inOffset < inCount && (CRYP->SR & CRYP_SR_IFNF)) { 428 | CRYP->DIN = inData[inOffset++]; 429 | } 430 | 431 | // Read data if output FIFO isn't empty 432 | while (CRYP->SR & CRYP_SR_OFNE) { 433 | outData[outOffset++] = CRYP->DOUT; 434 | } 435 | } 436 | 437 | // Disable CRYP 438 | CRYP->CR &= ~CRYP_CR_CRYPEN; 439 | 440 | // Flush CRYP 441 | CRYP->CR |= CRYP_CR_FFLUSH; 442 | } 443 | 444 | static void CRYP_AES_CTR_Encrypt(uint32_t *counter, void *outData, uint32_t outSize, const void *inData, uint32_t inSize) 445 | { 446 | // Setup datatype and algomode (AES-CTR) 447 | CRYP->CR &= ~(CRYP_CR_DATATYPE_0 | CRYP_CR_ALGOMODE_0 | CRYP_CR_ALGOMODE_1 | CRYP_CR_ALGOMODE_2); 448 | CRYP->CR |= CRYP_CR_ALGOMODE_AES_CTR; 449 | 450 | // Setup direction (Encrypt) 451 | CRYP->CR &= ~CRYP_CR_ALGODIR; 452 | 453 | // Setup key size (128) 454 | CRYP->CR &= ~CRYP_CR_KEYSIZE; 455 | 456 | // Clear lowest IV word 457 | CRYP->IV1RR = 0; 458 | 459 | CRYP_ProcessData((uint32_t*)outData, outSize / 4, (const uint32_t*)inData, inSize / 4); 460 | } 461 | 462 | static void get_aes_data(aes_data_t *aesData) 463 | { 464 | // store IV 465 | aesData->iv[0] = __builtin_bswap32(CRYP->IV0LR); 466 | aesData->iv[1] = __builtin_bswap32(CRYP->IV0RR); 467 | aesData->iv[2] = __builtin_bswap32(CRYP->IV1LR); 468 | aesData->iv[3] = 0; // for the counter just store 0 469 | 470 | // Clear zero buffer 471 | uint32_t zeroes[4] = { 0 }; 472 | 473 | for (int i = 0; i < 4; i++) { 474 | // Start blanking out parts of the key after the first round 475 | if (i > 0) { 476 | (&CRYP->K0LR)[4 + (i - 1)] = 0; 477 | } 478 | 479 | // Encrypt zeroes 480 | uint32_t counter = 0; 481 | CRYP_AES_CTR_Encrypt(&counter, aesData->encrypted_parts[i], sizeof(aesData->encrypted_parts[i]), zeroes, sizeof(zeroes)); 482 | } 483 | } 484 | 485 | static void generate_qr(const void *data, size_t size, uint8_t *screenBuffer) 486 | { 487 | char* hexBuffer = malloc(size*2 + 1); 488 | if (!hexBuffer) { 489 | memset(screenBuffer, 0xFF, SCREEN_WIDTH * SCREEN_HEIGHT * 3); 490 | return; 491 | } 492 | 493 | char* hexPtr = hexBuffer; 494 | for (size_t i = 0; i < size; i++) { 495 | hexPtr += sprintf(hexPtr, "%02x", *((uint8_t *)data + i)); 496 | } 497 | 498 | uint8_t qr0[qrcodegen_BUFFER_LEN_MAX]; 499 | uint8_t tempBuffer[qrcodegen_BUFFER_LEN_MAX]; 500 | if (!qrcodegen_encodeText(hexBuffer, tempBuffer, qr0, qrcodegen_Ecc_MEDIUM, qrcodegen_VERSION_MIN, qrcodegen_VERSION_MAX, qrcodegen_Mask_AUTO, true)) { 501 | free(hexBuffer); 502 | memset(screenBuffer, 0xFF, SCREEN_WIDTH * SCREEN_HEIGHT * 3); 503 | return; 504 | } 505 | 506 | free(hexBuffer); 507 | 508 | uint32_t offset = 0; 509 | for (int x = SCREEN_WIDTH - 1; x >= 0; x--) { 510 | for (int y = 0; y < SCREEN_HEIGHT; y++) { 511 | uint8_t color = 255; 512 | 513 | // Get color and scale up qr code 514 | if (qrcodegen_getModule(qr0, x/4 - 5, y/4 - 4)) { 515 | color = 0; 516 | } 517 | 518 | screenBuffer[offset++] = color; 519 | screenBuffer[offset++] = color; 520 | screenBuffer[offset++] = color; 521 | } 522 | } 523 | } 524 | -------------------------------------------------------------------------------- /usb_payload/source/main.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | extern SRAM_HandleTypeDef fmcHandle; 6 | extern TIM_HandleTypeDef tim3Handle; 7 | extern MDMA_HandleTypeDef mdmaHandle; 8 | extern ADC_HandleTypeDef adcHandle; 9 | extern DMA_HandleTypeDef dmaHandle; 10 | extern ADC_HandleTypeDef adc2Handle; 11 | extern DMA_HandleTypeDef dma2Handle; 12 | -------------------------------------------------------------------------------- /usb_payload/source/qrcodegen.c: -------------------------------------------------------------------------------- 1 | /* 2 | * QR Code generator library (C) 3 | * 4 | * Copyright (c) Project Nayuki. (MIT License) 5 | * https://www.nayuki.io/page/qr-code-generator-library 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy of 8 | * this software and associated documentation files (the "Software"), to deal in 9 | * the Software without restriction, including without limitation the rights to 10 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 11 | * the Software, and to permit persons to whom the Software is furnished to do so, 12 | * subject to the following conditions: 13 | * - The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * - The Software is provided "as is", without warranty of any kind, express or 16 | * implied, including but not limited to the warranties of merchantability, 17 | * fitness for a particular purpose and noninfringement. In no event shall the 18 | * authors or copyright holders be liable for any claim, damages or other 19 | * liability, whether in an action of contract, tort or otherwise, arising from, 20 | * out of or in connection with the Software or the use or other dealings in the 21 | * Software. 22 | */ 23 | 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include "qrcodegen.h" 29 | 30 | #undef assert 31 | #define assert(...) 32 | 33 | #ifndef QRCODEGEN_TEST 34 | #define testable static // Keep functions private 35 | #else 36 | #define testable // Expose private functions 37 | #endif 38 | 39 | 40 | /*---- Forward declarations for private functions ----*/ 41 | 42 | // Regarding all public and private functions defined in this source file: 43 | // - They require all pointer/array arguments to be not null unless the array length is zero. 44 | // - They only read input scalar/array arguments, write to output pointer/array 45 | // arguments, and return scalar values; they are "pure" functions. 46 | // - They don't read mutable global variables or write to any global variables. 47 | // - They don't perform I/O, read the clock, print to console, etc. 48 | // - They allocate a small and constant amount of stack memory. 49 | // - They don't allocate or free any memory on the heap. 50 | // - They don't recurse or mutually recurse. All the code 51 | // could be inlined into the top-level public functions. 52 | // - They run in at most quadratic time with respect to input arguments. 53 | // Most functions run in linear time, and some in constant time. 54 | // There are no unbounded loops or non-obvious termination conditions. 55 | // - They are completely thread-safe if the caller does not give the 56 | // same writable buffer to concurrent calls to these functions. 57 | 58 | testable void appendBitsToBuffer(unsigned int val, int numBits, uint8_t buffer[], int *bitLen); 59 | 60 | testable void addEccAndInterleave(uint8_t data[], int version, enum qrcodegen_Ecc ecl, uint8_t result[]); 61 | testable int getNumDataCodewords(int version, enum qrcodegen_Ecc ecl); 62 | testable int getNumRawDataModules(int ver); 63 | 64 | testable void reedSolomonComputeDivisor(int degree, uint8_t result[]); 65 | testable void reedSolomonComputeRemainder(const uint8_t data[], int dataLen, 66 | const uint8_t generator[], int degree, uint8_t result[]); 67 | testable uint8_t reedSolomonMultiply(uint8_t x, uint8_t y); 68 | 69 | testable void initializeFunctionModules(int version, uint8_t qrcode[]); 70 | static void drawLightFunctionModules(uint8_t qrcode[], int version); 71 | static void drawFormatBits(enum qrcodegen_Ecc ecl, enum qrcodegen_Mask mask, uint8_t qrcode[]); 72 | testable int getAlignmentPatternPositions(int version, uint8_t result[7]); 73 | static void fillRectangle(int left, int top, int width, int height, uint8_t qrcode[]); 74 | 75 | static void drawCodewords(const uint8_t data[], int dataLen, uint8_t qrcode[]); 76 | static void applyMask(const uint8_t functionModules[], uint8_t qrcode[], enum qrcodegen_Mask mask); 77 | static long getPenaltyScore(const uint8_t qrcode[]); 78 | static int finderPenaltyCountPatterns(const int runHistory[7], int qrsize); 79 | static int finderPenaltyTerminateAndCount(bool currentRunColor, int currentRunLength, int runHistory[7], int qrsize); 80 | static void finderPenaltyAddHistory(int currentRunLength, int runHistory[7], int qrsize); 81 | 82 | testable bool getModuleBounded(const uint8_t qrcode[], int x, int y); 83 | testable void setModuleBounded(uint8_t qrcode[], int x, int y, bool isDark); 84 | testable void setModuleUnbounded(uint8_t qrcode[], int x, int y, bool isDark); 85 | static bool getBit(int x, int i); 86 | 87 | testable int calcSegmentBitLength(enum qrcodegen_Mode mode, size_t numChars); 88 | testable int getTotalBits(const struct qrcodegen_Segment segs[], size_t len, int version); 89 | static int numCharCountBits(enum qrcodegen_Mode mode, int version); 90 | 91 | 92 | 93 | /*---- Private tables of constants ----*/ 94 | 95 | // The set of all legal characters in alphanumeric mode, where each character 96 | // value maps to the index in the string. For checking text and encoding segments. 97 | static const char *ALPHANUMERIC_CHARSET = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:"; 98 | 99 | // Sentinel value for use in only some functions. 100 | #define LENGTH_OVERFLOW -1 101 | 102 | // For generating error correction codes. 103 | testable const int8_t ECC_CODEWORDS_PER_BLOCK[4][41] = { 104 | // Version: (note that index 0 is for padding, and is set to an illegal value) 105 | //0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40 Error correction level 106 | {-1, 7, 10, 15, 20, 26, 18, 20, 24, 30, 18, 20, 24, 26, 30, 22, 24, 28, 30, 28, 28, 28, 28, 30, 30, 26, 28, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30}, // Low 107 | {-1, 10, 16, 26, 18, 24, 16, 18, 22, 22, 26, 30, 22, 22, 24, 24, 28, 28, 26, 26, 26, 26, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28}, // Medium 108 | {-1, 13, 22, 18, 26, 18, 24, 18, 22, 20, 24, 28, 26, 24, 20, 30, 24, 28, 28, 26, 30, 28, 30, 30, 30, 30, 28, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30}, // Quartile 109 | {-1, 17, 28, 22, 16, 22, 28, 26, 26, 24, 28, 24, 28, 22, 24, 24, 30, 28, 28, 26, 28, 30, 24, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30}, // High 110 | }; 111 | 112 | #define qrcodegen_REED_SOLOMON_DEGREE_MAX 30 // Based on the table above 113 | 114 | // For generating error correction codes. 115 | testable const int8_t NUM_ERROR_CORRECTION_BLOCKS[4][41] = { 116 | // Version: (note that index 0 is for padding, and is set to an illegal value) 117 | //0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40 Error correction level 118 | {-1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 4, 4, 4, 4, 4, 6, 6, 6, 6, 7, 8, 8, 9, 9, 10, 12, 12, 12, 13, 14, 15, 16, 17, 18, 19, 19, 20, 21, 22, 24, 25}, // Low 119 | {-1, 1, 1, 1, 2, 2, 4, 4, 4, 5, 5, 5, 8, 9, 9, 10, 10, 11, 13, 14, 16, 17, 17, 18, 20, 21, 23, 25, 26, 28, 29, 31, 33, 35, 37, 38, 40, 43, 45, 47, 49}, // Medium 120 | {-1, 1, 1, 2, 2, 4, 4, 6, 6, 8, 8, 8, 10, 12, 16, 12, 17, 16, 18, 21, 20, 23, 23, 25, 27, 29, 34, 34, 35, 38, 40, 43, 45, 48, 51, 53, 56, 59, 62, 65, 68}, // Quartile 121 | {-1, 1, 1, 2, 4, 4, 4, 5, 6, 8, 8, 11, 11, 16, 16, 18, 16, 19, 21, 25, 25, 25, 34, 30, 32, 35, 37, 40, 42, 45, 48, 51, 54, 57, 60, 63, 66, 70, 74, 77, 81}, // High 122 | }; 123 | 124 | // For automatic mask pattern selection. 125 | static const int PENALTY_N1 = 3; 126 | static const int PENALTY_N2 = 3; 127 | static const int PENALTY_N3 = 40; 128 | static const int PENALTY_N4 = 10; 129 | 130 | 131 | 132 | /*---- High-level QR Code encoding functions ----*/ 133 | 134 | // Public function - see documentation comment in header file. 135 | bool qrcodegen_encodeText(const char *text, uint8_t tempBuffer[], uint8_t qrcode[], 136 | enum qrcodegen_Ecc ecl, int minVersion, int maxVersion, enum qrcodegen_Mask mask, bool boostEcl) { 137 | 138 | size_t textLen = strlen(text); 139 | if (textLen == 0) 140 | return qrcodegen_encodeSegmentsAdvanced(NULL, 0, ecl, minVersion, maxVersion, mask, boostEcl, tempBuffer, qrcode); 141 | size_t bufLen = (size_t)qrcodegen_BUFFER_LEN_FOR_VERSION(maxVersion); 142 | 143 | struct qrcodegen_Segment seg; 144 | if (qrcodegen_isNumeric(text)) { 145 | if (qrcodegen_calcSegmentBufferSize(qrcodegen_Mode_NUMERIC, textLen) > bufLen) 146 | goto fail; 147 | seg = qrcodegen_makeNumeric(text, tempBuffer); 148 | } else if (qrcodegen_isAlphanumeric(text)) { 149 | if (qrcodegen_calcSegmentBufferSize(qrcodegen_Mode_ALPHANUMERIC, textLen) > bufLen) 150 | goto fail; 151 | seg = qrcodegen_makeAlphanumeric(text, tempBuffer); 152 | } else { 153 | if (textLen > bufLen) 154 | goto fail; 155 | for (size_t i = 0; i < textLen; i++) 156 | tempBuffer[i] = (uint8_t)text[i]; 157 | seg.mode = qrcodegen_Mode_BYTE; 158 | seg.bitLength = calcSegmentBitLength(seg.mode, textLen); 159 | if (seg.bitLength == LENGTH_OVERFLOW) 160 | goto fail; 161 | seg.numChars = (int)textLen; 162 | seg.data = tempBuffer; 163 | } 164 | return qrcodegen_encodeSegmentsAdvanced(&seg, 1, ecl, minVersion, maxVersion, mask, boostEcl, tempBuffer, qrcode); 165 | 166 | fail: 167 | qrcode[0] = 0; // Set size to invalid value for safety 168 | return false; 169 | } 170 | 171 | 172 | // Public function - see documentation comment in header file. 173 | bool qrcodegen_encodeBinary(uint8_t dataAndTemp[], size_t dataLen, uint8_t qrcode[], 174 | enum qrcodegen_Ecc ecl, int minVersion, int maxVersion, enum qrcodegen_Mask mask, bool boostEcl) { 175 | 176 | struct qrcodegen_Segment seg; 177 | seg.mode = qrcodegen_Mode_BYTE; 178 | seg.bitLength = calcSegmentBitLength(seg.mode, dataLen); 179 | if (seg.bitLength == LENGTH_OVERFLOW) { 180 | qrcode[0] = 0; // Set size to invalid value for safety 181 | return false; 182 | } 183 | seg.numChars = (int)dataLen; 184 | seg.data = dataAndTemp; 185 | return qrcodegen_encodeSegmentsAdvanced(&seg, 1, ecl, minVersion, maxVersion, mask, boostEcl, dataAndTemp, qrcode); 186 | } 187 | 188 | 189 | // Appends the given number of low-order bits of the given value to the given byte-based 190 | // bit buffer, increasing the bit length. Requires 0 <= numBits <= 16 and val < 2^numBits. 191 | testable void appendBitsToBuffer(unsigned int val, int numBits, uint8_t buffer[], int *bitLen) { 192 | assert(0 <= numBits && numBits <= 16 && (unsigned long)val >> numBits == 0); 193 | for (int i = numBits - 1; i >= 0; i--, (*bitLen)++) 194 | buffer[*bitLen >> 3] |= ((val >> i) & 1) << (7 - (*bitLen & 7)); 195 | } 196 | 197 | 198 | 199 | /*---- Low-level QR Code encoding functions ----*/ 200 | 201 | // Public function - see documentation comment in header file. 202 | bool qrcodegen_encodeSegments(const struct qrcodegen_Segment segs[], size_t len, 203 | enum qrcodegen_Ecc ecl, uint8_t tempBuffer[], uint8_t qrcode[]) { 204 | return qrcodegen_encodeSegmentsAdvanced(segs, len, ecl, 205 | qrcodegen_VERSION_MIN, qrcodegen_VERSION_MAX, qrcodegen_Mask_AUTO, true, tempBuffer, qrcode); 206 | } 207 | 208 | 209 | // Public function - see documentation comment in header file. 210 | bool qrcodegen_encodeSegmentsAdvanced(const struct qrcodegen_Segment segs[], size_t len, enum qrcodegen_Ecc ecl, 211 | int minVersion, int maxVersion, enum qrcodegen_Mask mask, bool boostEcl, uint8_t tempBuffer[], uint8_t qrcode[]) { 212 | assert(segs != NULL || len == 0); 213 | assert(qrcodegen_VERSION_MIN <= minVersion && minVersion <= maxVersion && maxVersion <= qrcodegen_VERSION_MAX); 214 | assert(0 <= (int)ecl && (int)ecl <= 3 && -1 <= (int)mask && (int)mask <= 7); 215 | 216 | // Find the minimal version number to use 217 | int version, dataUsedBits; 218 | for (version = minVersion; ; version++) { 219 | int dataCapacityBits = getNumDataCodewords(version, ecl) * 8; // Number of data bits available 220 | dataUsedBits = getTotalBits(segs, len, version); 221 | if (dataUsedBits != LENGTH_OVERFLOW && dataUsedBits <= dataCapacityBits) 222 | break; // This version number is found to be suitable 223 | if (version >= maxVersion) { // All versions in the range could not fit the given data 224 | qrcode[0] = 0; // Set size to invalid value for safety 225 | return false; 226 | } 227 | } 228 | assert(dataUsedBits != LENGTH_OVERFLOW); 229 | 230 | // Increase the error correction level while the data still fits in the current version number 231 | for (int i = (int)qrcodegen_Ecc_MEDIUM; i <= (int)qrcodegen_Ecc_HIGH; i++) { // From low to high 232 | if (boostEcl && dataUsedBits <= getNumDataCodewords(version, (enum qrcodegen_Ecc)i) * 8) 233 | ecl = (enum qrcodegen_Ecc)i; 234 | } 235 | 236 | // Concatenate all segments to create the data bit string 237 | memset(qrcode, 0, (size_t)qrcodegen_BUFFER_LEN_FOR_VERSION(version) * sizeof(qrcode[0])); 238 | int bitLen = 0; 239 | for (size_t i = 0; i < len; i++) { 240 | const struct qrcodegen_Segment *seg = &segs[i]; 241 | appendBitsToBuffer((unsigned int)seg->mode, 4, qrcode, &bitLen); 242 | appendBitsToBuffer((unsigned int)seg->numChars, numCharCountBits(seg->mode, version), qrcode, &bitLen); 243 | for (int j = 0; j < seg->bitLength; j++) { 244 | int bit = (seg->data[j >> 3] >> (7 - (j & 7))) & 1; 245 | appendBitsToBuffer((unsigned int)bit, 1, qrcode, &bitLen); 246 | } 247 | } 248 | assert(bitLen == dataUsedBits); 249 | 250 | // Add terminator and pad up to a byte if applicable 251 | int dataCapacityBits = getNumDataCodewords(version, ecl) * 8; 252 | assert(bitLen <= dataCapacityBits); 253 | int terminatorBits = dataCapacityBits - bitLen; 254 | if (terminatorBits > 4) 255 | terminatorBits = 4; 256 | appendBitsToBuffer(0, terminatorBits, qrcode, &bitLen); 257 | appendBitsToBuffer(0, (8 - bitLen % 8) % 8, qrcode, &bitLen); 258 | assert(bitLen % 8 == 0); 259 | 260 | // Pad with alternating bytes until data capacity is reached 261 | for (uint8_t padByte = 0xEC; bitLen < dataCapacityBits; padByte ^= 0xEC ^ 0x11) 262 | appendBitsToBuffer(padByte, 8, qrcode, &bitLen); 263 | 264 | // Compute ECC, draw modules 265 | addEccAndInterleave(qrcode, version, ecl, tempBuffer); 266 | initializeFunctionModules(version, qrcode); 267 | drawCodewords(tempBuffer, getNumRawDataModules(version) / 8, qrcode); 268 | drawLightFunctionModules(qrcode, version); 269 | initializeFunctionModules(version, tempBuffer); 270 | 271 | // Do masking 272 | if (mask == qrcodegen_Mask_AUTO) { // Automatically choose best mask 273 | long minPenalty = LONG_MAX; 274 | for (int i = 0; i < 8; i++) { 275 | enum qrcodegen_Mask msk = (enum qrcodegen_Mask)i; 276 | applyMask(tempBuffer, qrcode, msk); 277 | drawFormatBits(ecl, msk, qrcode); 278 | long penalty = getPenaltyScore(qrcode); 279 | if (penalty < minPenalty) { 280 | mask = msk; 281 | minPenalty = penalty; 282 | } 283 | applyMask(tempBuffer, qrcode, msk); // Undoes the mask due to XOR 284 | } 285 | } 286 | assert(0 <= (int)mask && (int)mask <= 7); 287 | applyMask(tempBuffer, qrcode, mask); // Apply the final choice of mask 288 | drawFormatBits(ecl, mask, qrcode); // Overwrite old format bits 289 | return true; 290 | } 291 | 292 | 293 | 294 | /*---- Error correction code generation functions ----*/ 295 | 296 | // Appends error correction bytes to each block of the given data array, then interleaves 297 | // bytes from the blocks and stores them in the result array. data[0 : dataLen] contains 298 | // the input data. data[dataLen : rawCodewords] is used as a temporary work area and will 299 | // be clobbered by this function. The final answer is stored in result[0 : rawCodewords]. 300 | testable void addEccAndInterleave(uint8_t data[], int version, enum qrcodegen_Ecc ecl, uint8_t result[]) { 301 | // Calculate parameter numbers 302 | assert(0 <= (int)ecl && (int)ecl < 4 && qrcodegen_VERSION_MIN <= version && version <= qrcodegen_VERSION_MAX); 303 | int numBlocks = NUM_ERROR_CORRECTION_BLOCKS[(int)ecl][version]; 304 | int blockEccLen = ECC_CODEWORDS_PER_BLOCK [(int)ecl][version]; 305 | int rawCodewords = getNumRawDataModules(version) / 8; 306 | int dataLen = getNumDataCodewords(version, ecl); 307 | int numShortBlocks = numBlocks - rawCodewords % numBlocks; 308 | int shortBlockDataLen = rawCodewords / numBlocks - blockEccLen; 309 | 310 | // Split data into blocks, calculate ECC, and interleave 311 | // (not concatenate) the bytes into a single sequence 312 | uint8_t rsdiv[qrcodegen_REED_SOLOMON_DEGREE_MAX]; 313 | reedSolomonComputeDivisor(blockEccLen, rsdiv); 314 | const uint8_t *dat = data; 315 | for (int i = 0; i < numBlocks; i++) { 316 | int datLen = shortBlockDataLen + (i < numShortBlocks ? 0 : 1); 317 | uint8_t *ecc = &data[dataLen]; // Temporary storage 318 | reedSolomonComputeRemainder(dat, datLen, rsdiv, blockEccLen, ecc); 319 | for (int j = 0, k = i; j < datLen; j++, k += numBlocks) { // Copy data 320 | if (j == shortBlockDataLen) 321 | k -= numShortBlocks; 322 | result[k] = dat[j]; 323 | } 324 | for (int j = 0, k = dataLen + i; j < blockEccLen; j++, k += numBlocks) // Copy ECC 325 | result[k] = ecc[j]; 326 | dat += datLen; 327 | } 328 | } 329 | 330 | 331 | // Returns the number of 8-bit codewords that can be used for storing data (not ECC), 332 | // for the given version number and error correction level. The result is in the range [9, 2956]. 333 | testable int getNumDataCodewords(int version, enum qrcodegen_Ecc ecl) { 334 | int v = version, e = (int)ecl; 335 | assert(0 <= e && e < 4); 336 | return getNumRawDataModules(v) / 8 337 | - ECC_CODEWORDS_PER_BLOCK [e][v] 338 | * NUM_ERROR_CORRECTION_BLOCKS[e][v]; 339 | } 340 | 341 | 342 | // Returns the number of data bits that can be stored in a QR Code of the given version number, after 343 | // all function modules are excluded. This includes remainder bits, so it might not be a multiple of 8. 344 | // The result is in the range [208, 29648]. This could be implemented as a 40-entry lookup table. 345 | testable int getNumRawDataModules(int ver) { 346 | assert(qrcodegen_VERSION_MIN <= ver && ver <= qrcodegen_VERSION_MAX); 347 | int result = (16 * ver + 128) * ver + 64; 348 | if (ver >= 2) { 349 | int numAlign = ver / 7 + 2; 350 | result -= (25 * numAlign - 10) * numAlign - 55; 351 | if (ver >= 7) 352 | result -= 36; 353 | } 354 | assert(208 <= result && result <= 29648); 355 | return result; 356 | } 357 | 358 | 359 | 360 | /*---- Reed-Solomon ECC generator functions ----*/ 361 | 362 | // Computes a Reed-Solomon ECC generator polynomial for the given degree, storing in result[0 : degree]. 363 | // This could be implemented as a lookup table over all possible parameter values, instead of as an algorithm. 364 | testable void reedSolomonComputeDivisor(int degree, uint8_t result[]) { 365 | assert(1 <= degree && degree <= qrcodegen_REED_SOLOMON_DEGREE_MAX); 366 | // Polynomial coefficients are stored from highest to lowest power, excluding the leading term which is always 1. 367 | // For example the polynomial x^3 + 255x^2 + 8x + 93 is stored as the uint8 array {255, 8, 93}. 368 | memset(result, 0, (size_t)degree * sizeof(result[0])); 369 | result[degree - 1] = 1; // Start off with the monomial x^0 370 | 371 | // Compute the product polynomial (x - r^0) * (x - r^1) * (x - r^2) * ... * (x - r^{degree-1}), 372 | // drop the highest monomial term which is always 1x^degree. 373 | // Note that r = 0x02, which is a generator element of this field GF(2^8/0x11D). 374 | uint8_t root = 1; 375 | for (int i = 0; i < degree; i++) { 376 | // Multiply the current product by (x - r^i) 377 | for (int j = 0; j < degree; j++) { 378 | result[j] = reedSolomonMultiply(result[j], root); 379 | if (j + 1 < degree) 380 | result[j] ^= result[j + 1]; 381 | } 382 | root = reedSolomonMultiply(root, 0x02); 383 | } 384 | } 385 | 386 | 387 | // Computes the Reed-Solomon error correction codeword for the given data and divisor polynomials. 388 | // The remainder when data[0 : dataLen] is divided by divisor[0 : degree] is stored in result[0 : degree]. 389 | // All polynomials are in big endian, and the generator has an implicit leading 1 term. 390 | testable void reedSolomonComputeRemainder(const uint8_t data[], int dataLen, 391 | const uint8_t generator[], int degree, uint8_t result[]) { 392 | assert(1 <= degree && degree <= qrcodegen_REED_SOLOMON_DEGREE_MAX); 393 | memset(result, 0, (size_t)degree * sizeof(result[0])); 394 | for (int i = 0; i < dataLen; i++) { // Polynomial division 395 | uint8_t factor = data[i] ^ result[0]; 396 | memmove(&result[0], &result[1], (size_t)(degree - 1) * sizeof(result[0])); 397 | result[degree - 1] = 0; 398 | for (int j = 0; j < degree; j++) 399 | result[j] ^= reedSolomonMultiply(generator[j], factor); 400 | } 401 | } 402 | 403 | #undef qrcodegen_REED_SOLOMON_DEGREE_MAX 404 | 405 | 406 | // Returns the product of the two given field elements modulo GF(2^8/0x11D). 407 | // All inputs are valid. This could be implemented as a 256*256 lookup table. 408 | testable uint8_t reedSolomonMultiply(uint8_t x, uint8_t y) { 409 | // Russian peasant multiplication 410 | uint8_t z = 0; 411 | for (int i = 7; i >= 0; i--) { 412 | z = (uint8_t)((z << 1) ^ ((z >> 7) * 0x11D)); 413 | z ^= ((y >> i) & 1) * x; 414 | } 415 | return z; 416 | } 417 | 418 | 419 | 420 | /*---- Drawing function modules ----*/ 421 | 422 | // Clears the given QR Code grid with light modules for the given 423 | // version's size, then marks every function module as dark. 424 | testable void initializeFunctionModules(int version, uint8_t qrcode[]) { 425 | // Initialize QR Code 426 | int qrsize = version * 4 + 17; 427 | memset(qrcode, 0, (size_t)((qrsize * qrsize + 7) / 8 + 1) * sizeof(qrcode[0])); 428 | qrcode[0] = (uint8_t)qrsize; 429 | 430 | // Fill horizontal and vertical timing patterns 431 | fillRectangle(6, 0, 1, qrsize, qrcode); 432 | fillRectangle(0, 6, qrsize, 1, qrcode); 433 | 434 | // Fill 3 finder patterns (all corners except bottom right) and format bits 435 | fillRectangle(0, 0, 9, 9, qrcode); 436 | fillRectangle(qrsize - 8, 0, 8, 9, qrcode); 437 | fillRectangle(0, qrsize - 8, 9, 8, qrcode); 438 | 439 | // Fill numerous alignment patterns 440 | uint8_t alignPatPos[7]; 441 | int numAlign = getAlignmentPatternPositions(version, alignPatPos); 442 | for (int i = 0; i < numAlign; i++) { 443 | for (int j = 0; j < numAlign; j++) { 444 | // Don't draw on the three finder corners 445 | if (!((i == 0 && j == 0) || (i == 0 && j == numAlign - 1) || (i == numAlign - 1 && j == 0))) 446 | fillRectangle(alignPatPos[i] - 2, alignPatPos[j] - 2, 5, 5, qrcode); 447 | } 448 | } 449 | 450 | // Fill version blocks 451 | if (version >= 7) { 452 | fillRectangle(qrsize - 11, 0, 3, 6, qrcode); 453 | fillRectangle(0, qrsize - 11, 6, 3, qrcode); 454 | } 455 | } 456 | 457 | 458 | // Draws light function modules and possibly some dark modules onto the given QR Code, without changing 459 | // non-function modules. This does not draw the format bits. This requires all function modules to be previously 460 | // marked dark (namely by initializeFunctionModules()), because this may skip redrawing dark function modules. 461 | static void drawLightFunctionModules(uint8_t qrcode[], int version) { 462 | // Draw horizontal and vertical timing patterns 463 | int qrsize = qrcodegen_getSize(qrcode); 464 | for (int i = 7; i < qrsize - 7; i += 2) { 465 | setModuleBounded(qrcode, 6, i, false); 466 | setModuleBounded(qrcode, i, 6, false); 467 | } 468 | 469 | // Draw 3 finder patterns (all corners except bottom right; overwrites some timing modules) 470 | for (int dy = -4; dy <= 4; dy++) { 471 | for (int dx = -4; dx <= 4; dx++) { 472 | int dist = abs(dx); 473 | if (abs(dy) > dist) 474 | dist = abs(dy); 475 | if (dist == 2 || dist == 4) { 476 | setModuleUnbounded(qrcode, 3 + dx, 3 + dy, false); 477 | setModuleUnbounded(qrcode, qrsize - 4 + dx, 3 + dy, false); 478 | setModuleUnbounded(qrcode, 3 + dx, qrsize - 4 + dy, false); 479 | } 480 | } 481 | } 482 | 483 | // Draw numerous alignment patterns 484 | uint8_t alignPatPos[7]; 485 | int numAlign = getAlignmentPatternPositions(version, alignPatPos); 486 | for (int i = 0; i < numAlign; i++) { 487 | for (int j = 0; j < numAlign; j++) { 488 | if ((i == 0 && j == 0) || (i == 0 && j == numAlign - 1) || (i == numAlign - 1 && j == 0)) 489 | continue; // Don't draw on the three finder corners 490 | for (int dy = -1; dy <= 1; dy++) { 491 | for (int dx = -1; dx <= 1; dx++) 492 | setModuleBounded(qrcode, alignPatPos[i] + dx, alignPatPos[j] + dy, dx == 0 && dy == 0); 493 | } 494 | } 495 | } 496 | 497 | // Draw version blocks 498 | if (version >= 7) { 499 | // Calculate error correction code and pack bits 500 | int rem = version; // version is uint6, in the range [7, 40] 501 | for (int i = 0; i < 12; i++) 502 | rem = (rem << 1) ^ ((rem >> 11) * 0x1F25); 503 | long bits = (long)version << 12 | rem; // uint18 504 | assert(bits >> 18 == 0); 505 | 506 | // Draw two copies 507 | for (int i = 0; i < 6; i++) { 508 | for (int j = 0; j < 3; j++) { 509 | int k = qrsize - 11 + j; 510 | setModuleBounded(qrcode, k, i, (bits & 1) != 0); 511 | setModuleBounded(qrcode, i, k, (bits & 1) != 0); 512 | bits >>= 1; 513 | } 514 | } 515 | } 516 | } 517 | 518 | 519 | // Draws two copies of the format bits (with its own error correction code) based 520 | // on the given mask and error correction level. This always draws all modules of 521 | // the format bits, unlike drawLightFunctionModules() which might skip dark modules. 522 | static void drawFormatBits(enum qrcodegen_Ecc ecl, enum qrcodegen_Mask mask, uint8_t qrcode[]) { 523 | // Calculate error correction code and pack bits 524 | assert(0 <= (int)mask && (int)mask <= 7); 525 | static const int table[] = {1, 0, 3, 2}; 526 | int data = table[(int)ecl] << 3 | (int)mask; // errCorrLvl is uint2, mask is uint3 527 | int rem = data; 528 | for (int i = 0; i < 10; i++) 529 | rem = (rem << 1) ^ ((rem >> 9) * 0x537); 530 | int bits = (data << 10 | rem) ^ 0x5412; // uint15 531 | assert(bits >> 15 == 0); 532 | 533 | // Draw first copy 534 | for (int i = 0; i <= 5; i++) 535 | setModuleBounded(qrcode, 8, i, getBit(bits, i)); 536 | setModuleBounded(qrcode, 8, 7, getBit(bits, 6)); 537 | setModuleBounded(qrcode, 8, 8, getBit(bits, 7)); 538 | setModuleBounded(qrcode, 7, 8, getBit(bits, 8)); 539 | for (int i = 9; i < 15; i++) 540 | setModuleBounded(qrcode, 14 - i, 8, getBit(bits, i)); 541 | 542 | // Draw second copy 543 | int qrsize = qrcodegen_getSize(qrcode); 544 | for (int i = 0; i < 8; i++) 545 | setModuleBounded(qrcode, qrsize - 1 - i, 8, getBit(bits, i)); 546 | for (int i = 8; i < 15; i++) 547 | setModuleBounded(qrcode, 8, qrsize - 15 + i, getBit(bits, i)); 548 | setModuleBounded(qrcode, 8, qrsize - 8, true); // Always dark 549 | } 550 | 551 | 552 | // Calculates and stores an ascending list of positions of alignment patterns 553 | // for this version number, returning the length of the list (in the range [0,7]). 554 | // Each position is in the range [0,177), and are used on both the x and y axes. 555 | // This could be implemented as lookup table of 40 variable-length lists of unsigned bytes. 556 | testable int getAlignmentPatternPositions(int version, uint8_t result[7]) { 557 | if (version == 1) 558 | return 0; 559 | int numAlign = version / 7 + 2; 560 | int step = (version * 8 + numAlign * 3 + 5) / (numAlign * 4 - 4) * 2; 561 | for (int i = numAlign - 1, pos = version * 4 + 10; i >= 1; i--, pos -= step) 562 | result[i] = (uint8_t)pos; 563 | result[0] = 6; 564 | return numAlign; 565 | } 566 | 567 | 568 | // Sets every module in the range [left : left + width] * [top : top + height] to dark. 569 | static void fillRectangle(int left, int top, int width, int height, uint8_t qrcode[]) { 570 | for (int dy = 0; dy < height; dy++) { 571 | for (int dx = 0; dx < width; dx++) 572 | setModuleBounded(qrcode, left + dx, top + dy, true); 573 | } 574 | } 575 | 576 | 577 | 578 | /*---- Drawing data modules and masking ----*/ 579 | 580 | // Draws the raw codewords (including data and ECC) onto the given QR Code. This requires the initial state of 581 | // the QR Code to be dark at function modules and light at codeword modules (including unused remainder bits). 582 | static void drawCodewords(const uint8_t data[], int dataLen, uint8_t qrcode[]) { 583 | int qrsize = qrcodegen_getSize(qrcode); 584 | int i = 0; // Bit index into the data 585 | // Do the funny zigzag scan 586 | for (int right = qrsize - 1; right >= 1; right -= 2) { // Index of right column in each column pair 587 | if (right == 6) 588 | right = 5; 589 | for (int vert = 0; vert < qrsize; vert++) { // Vertical counter 590 | for (int j = 0; j < 2; j++) { 591 | int x = right - j; // Actual x coordinate 592 | bool upward = ((right + 1) & 2) == 0; 593 | int y = upward ? qrsize - 1 - vert : vert; // Actual y coordinate 594 | if (!getModuleBounded(qrcode, x, y) && i < dataLen * 8) { 595 | bool dark = getBit(data[i >> 3], 7 - (i & 7)); 596 | setModuleBounded(qrcode, x, y, dark); 597 | i++; 598 | } 599 | // If this QR Code has any remainder bits (0 to 7), they were assigned as 600 | // 0/false/light by the constructor and are left unchanged by this method 601 | } 602 | } 603 | } 604 | assert(i == dataLen * 8); 605 | } 606 | 607 | 608 | // XORs the codeword modules in this QR Code with the given mask pattern 609 | // and given pattern of function modules. The codeword bits must be drawn 610 | // before masking. Due to the arithmetic of XOR, calling applyMask() with 611 | // the same mask value a second time will undo the mask. A final well-formed 612 | // QR Code needs exactly one (not zero, two, etc.) mask applied. 613 | static void applyMask(const uint8_t functionModules[], uint8_t qrcode[], enum qrcodegen_Mask mask) { 614 | assert(0 <= (int)mask && (int)mask <= 7); // Disallows qrcodegen_Mask_AUTO 615 | int qrsize = qrcodegen_getSize(qrcode); 616 | for (int y = 0; y < qrsize; y++) { 617 | for (int x = 0; x < qrsize; x++) { 618 | if (getModuleBounded(functionModules, x, y)) 619 | continue; 620 | bool invert; 621 | switch ((int)mask) { 622 | case 0: invert = (x + y) % 2 == 0; break; 623 | case 1: invert = y % 2 == 0; break; 624 | case 2: invert = x % 3 == 0; break; 625 | case 3: invert = (x + y) % 3 == 0; break; 626 | case 4: invert = (x / 3 + y / 2) % 2 == 0; break; 627 | case 5: invert = x * y % 2 + x * y % 3 == 0; break; 628 | case 6: invert = (x * y % 2 + x * y % 3) % 2 == 0; break; 629 | case 7: invert = ((x + y) % 2 + x * y % 3) % 2 == 0; break; 630 | default: assert(false); return; 631 | } 632 | bool val = getModuleBounded(qrcode, x, y); 633 | setModuleBounded(qrcode, x, y, val ^ invert); 634 | } 635 | } 636 | } 637 | 638 | 639 | // Calculates and returns the penalty score based on state of the given QR Code's current modules. 640 | // This is used by the automatic mask choice algorithm to find the mask pattern that yields the lowest score. 641 | static long getPenaltyScore(const uint8_t qrcode[]) { 642 | int qrsize = qrcodegen_getSize(qrcode); 643 | long result = 0; 644 | 645 | // Adjacent modules in row having same color, and finder-like patterns 646 | for (int y = 0; y < qrsize; y++) { 647 | bool runColor = false; 648 | int runX = 0; 649 | int runHistory[7] = {0}; 650 | for (int x = 0; x < qrsize; x++) { 651 | if (getModuleBounded(qrcode, x, y) == runColor) { 652 | runX++; 653 | if (runX == 5) 654 | result += PENALTY_N1; 655 | else if (runX > 5) 656 | result++; 657 | } else { 658 | finderPenaltyAddHistory(runX, runHistory, qrsize); 659 | if (!runColor) 660 | result += finderPenaltyCountPatterns(runHistory, qrsize) * PENALTY_N3; 661 | runColor = getModuleBounded(qrcode, x, y); 662 | runX = 1; 663 | } 664 | } 665 | result += finderPenaltyTerminateAndCount(runColor, runX, runHistory, qrsize) * PENALTY_N3; 666 | } 667 | // Adjacent modules in column having same color, and finder-like patterns 668 | for (int x = 0; x < qrsize; x++) { 669 | bool runColor = false; 670 | int runY = 0; 671 | int runHistory[7] = {0}; 672 | for (int y = 0; y < qrsize; y++) { 673 | if (getModuleBounded(qrcode, x, y) == runColor) { 674 | runY++; 675 | if (runY == 5) 676 | result += PENALTY_N1; 677 | else if (runY > 5) 678 | result++; 679 | } else { 680 | finderPenaltyAddHistory(runY, runHistory, qrsize); 681 | if (!runColor) 682 | result += finderPenaltyCountPatterns(runHistory, qrsize) * PENALTY_N3; 683 | runColor = getModuleBounded(qrcode, x, y); 684 | runY = 1; 685 | } 686 | } 687 | result += finderPenaltyTerminateAndCount(runColor, runY, runHistory, qrsize) * PENALTY_N3; 688 | } 689 | 690 | // 2*2 blocks of modules having same color 691 | for (int y = 0; y < qrsize - 1; y++) { 692 | for (int x = 0; x < qrsize - 1; x++) { 693 | bool color = getModuleBounded(qrcode, x, y); 694 | if ( color == getModuleBounded(qrcode, x + 1, y) && 695 | color == getModuleBounded(qrcode, x, y + 1) && 696 | color == getModuleBounded(qrcode, x + 1, y + 1)) 697 | result += PENALTY_N2; 698 | } 699 | } 700 | 701 | // Balance of dark and light modules 702 | int dark = 0; 703 | for (int y = 0; y < qrsize; y++) { 704 | for (int x = 0; x < qrsize; x++) { 705 | if (getModuleBounded(qrcode, x, y)) 706 | dark++; 707 | } 708 | } 709 | int total = qrsize * qrsize; // Note that size is odd, so dark/total != 1/2 710 | // Compute the smallest integer k >= 0 such that (45-5k)% <= dark/total <= (55+5k)% 711 | int k = (int)((labs(dark * 20L - total * 10L) + total - 1) / total) - 1; 712 | assert(0 <= k && k <= 9); 713 | result += k * PENALTY_N4; 714 | assert(0 <= result && result <= 2568888L); // Non-tight upper bound based on default values of PENALTY_N1, ..., N4 715 | return result; 716 | } 717 | 718 | 719 | // Can only be called immediately after a light run is added, and 720 | // returns either 0, 1, or 2. A helper function for getPenaltyScore(). 721 | static int finderPenaltyCountPatterns(const int runHistory[7], int qrsize) { 722 | int n = runHistory[1]; 723 | assert(n <= qrsize * 3); (void)qrsize; 724 | bool core = n > 0 && runHistory[2] == n && runHistory[3] == n * 3 && runHistory[4] == n && runHistory[5] == n; 725 | // The maximum QR Code size is 177, hence the dark run length n <= 177. 726 | // Arithmetic is promoted to int, so n*4 will not overflow. 727 | return (core && runHistory[0] >= n * 4 && runHistory[6] >= n ? 1 : 0) 728 | + (core && runHistory[6] >= n * 4 && runHistory[0] >= n ? 1 : 0); 729 | } 730 | 731 | 732 | // Must be called at the end of a line (row or column) of modules. A helper function for getPenaltyScore(). 733 | static int finderPenaltyTerminateAndCount(bool currentRunColor, int currentRunLength, int runHistory[7], int qrsize) { 734 | if (currentRunColor) { // Terminate dark run 735 | finderPenaltyAddHistory(currentRunLength, runHistory, qrsize); 736 | currentRunLength = 0; 737 | } 738 | currentRunLength += qrsize; // Add light border to final run 739 | finderPenaltyAddHistory(currentRunLength, runHistory, qrsize); 740 | return finderPenaltyCountPatterns(runHistory, qrsize); 741 | } 742 | 743 | 744 | // Pushes the given value to the front and drops the last value. A helper function for getPenaltyScore(). 745 | static void finderPenaltyAddHistory(int currentRunLength, int runHistory[7], int qrsize) { 746 | if (runHistory[0] == 0) 747 | currentRunLength += qrsize; // Add light border to initial run 748 | memmove(&runHistory[1], &runHistory[0], 6 * sizeof(runHistory[0])); 749 | runHistory[0] = currentRunLength; 750 | } 751 | 752 | 753 | 754 | /*---- Basic QR Code information ----*/ 755 | 756 | // Public function - see documentation comment in header file. 757 | int qrcodegen_getSize(const uint8_t qrcode[]) { 758 | assert(qrcode != NULL); 759 | int result = qrcode[0]; 760 | assert((qrcodegen_VERSION_MIN * 4 + 17) <= result 761 | && result <= (qrcodegen_VERSION_MAX * 4 + 17)); 762 | return result; 763 | } 764 | 765 | 766 | // Public function - see documentation comment in header file. 767 | bool qrcodegen_getModule(const uint8_t qrcode[], int x, int y) { 768 | assert(qrcode != NULL); 769 | int qrsize = qrcode[0]; 770 | return (0 <= x && x < qrsize && 0 <= y && y < qrsize) && getModuleBounded(qrcode, x, y); 771 | } 772 | 773 | 774 | // Returns the color of the module at the given coordinates, which must be in bounds. 775 | testable bool getModuleBounded(const uint8_t qrcode[], int x, int y) { 776 | int qrsize = qrcode[0]; 777 | assert(21 <= qrsize && qrsize <= 177 && 0 <= x && x < qrsize && 0 <= y && y < qrsize); 778 | int index = y * qrsize + x; 779 | return getBit(qrcode[(index >> 3) + 1], index & 7); 780 | } 781 | 782 | 783 | // Sets the color of the module at the given coordinates, which must be in bounds. 784 | testable void setModuleBounded(uint8_t qrcode[], int x, int y, bool isDark) { 785 | int qrsize = qrcode[0]; 786 | assert(21 <= qrsize && qrsize <= 177 && 0 <= x && x < qrsize && 0 <= y && y < qrsize); 787 | int index = y * qrsize + x; 788 | int bitIndex = index & 7; 789 | int byteIndex = (index >> 3) + 1; 790 | if (isDark) 791 | qrcode[byteIndex] |= 1 << bitIndex; 792 | else 793 | qrcode[byteIndex] &= (1 << bitIndex) ^ 0xFF; 794 | } 795 | 796 | 797 | // Sets the color of the module at the given coordinates, doing nothing if out of bounds. 798 | testable void setModuleUnbounded(uint8_t qrcode[], int x, int y, bool isDark) { 799 | int qrsize = qrcode[0]; 800 | if (0 <= x && x < qrsize && 0 <= y && y < qrsize) 801 | setModuleBounded(qrcode, x, y, isDark); 802 | } 803 | 804 | 805 | // Returns true iff the i'th bit of x is set to 1. Requires x >= 0 and 0 <= i <= 14. 806 | static bool getBit(int x, int i) { 807 | return ((x >> i) & 1) != 0; 808 | } 809 | 810 | 811 | 812 | /*---- Segment handling ----*/ 813 | 814 | // Public function - see documentation comment in header file. 815 | bool qrcodegen_isNumeric(const char *text) { 816 | assert(text != NULL); 817 | for (; *text != '\0'; text++) { 818 | if (*text < '0' || *text > '9') 819 | return false; 820 | } 821 | return true; 822 | } 823 | 824 | 825 | // Public function - see documentation comment in header file. 826 | bool qrcodegen_isAlphanumeric(const char *text) { 827 | assert(text != NULL); 828 | for (; *text != '\0'; text++) { 829 | if (strchr(ALPHANUMERIC_CHARSET, *text) == NULL) 830 | return false; 831 | } 832 | return true; 833 | } 834 | 835 | 836 | // Public function - see documentation comment in header file. 837 | size_t qrcodegen_calcSegmentBufferSize(enum qrcodegen_Mode mode, size_t numChars) { 838 | int temp = calcSegmentBitLength(mode, numChars); 839 | if (temp == LENGTH_OVERFLOW) 840 | return SIZE_MAX; 841 | assert(0 <= temp && temp <= INT16_MAX); 842 | return ((size_t)temp + 7) / 8; 843 | } 844 | 845 | 846 | // Returns the number of data bits needed to represent a segment 847 | // containing the given number of characters using the given mode. Notes: 848 | // - Returns LENGTH_OVERFLOW on failure, i.e. numChars > INT16_MAX 849 | // or the number of needed bits exceeds INT16_MAX (i.e. 32767). 850 | // - Otherwise, all valid results are in the range [0, INT16_MAX]. 851 | // - For byte mode, numChars measures the number of bytes, not Unicode code points. 852 | // - For ECI mode, numChars must be 0, and the worst-case number of bits is returned. 853 | // An actual ECI segment can have shorter data. For non-ECI modes, the result is exact. 854 | testable int calcSegmentBitLength(enum qrcodegen_Mode mode, size_t numChars) { 855 | // All calculations are designed to avoid overflow on all platforms 856 | if (numChars > (unsigned int)INT16_MAX) 857 | return LENGTH_OVERFLOW; 858 | long result = (long)numChars; 859 | if (mode == qrcodegen_Mode_NUMERIC) 860 | result = (result * 10 + 2) / 3; // ceil(10/3 * n) 861 | else if (mode == qrcodegen_Mode_ALPHANUMERIC) 862 | result = (result * 11 + 1) / 2; // ceil(11/2 * n) 863 | else if (mode == qrcodegen_Mode_BYTE) 864 | result *= 8; 865 | else if (mode == qrcodegen_Mode_KANJI) 866 | result *= 13; 867 | else if (mode == qrcodegen_Mode_ECI && numChars == 0) 868 | result = 3 * 8; 869 | else { // Invalid argument 870 | assert(false); 871 | return LENGTH_OVERFLOW; 872 | } 873 | assert(result >= 0); 874 | if (result > INT16_MAX) 875 | return LENGTH_OVERFLOW; 876 | return (int)result; 877 | } 878 | 879 | 880 | // Public function - see documentation comment in header file. 881 | struct qrcodegen_Segment qrcodegen_makeBytes(const uint8_t data[], size_t len, uint8_t buf[]) { 882 | assert(data != NULL || len == 0); 883 | struct qrcodegen_Segment result; 884 | result.mode = qrcodegen_Mode_BYTE; 885 | result.bitLength = calcSegmentBitLength(result.mode, len); 886 | assert(result.bitLength != LENGTH_OVERFLOW); 887 | result.numChars = (int)len; 888 | if (len > 0) 889 | memcpy(buf, data, len * sizeof(buf[0])); 890 | result.data = buf; 891 | return result; 892 | } 893 | 894 | 895 | // Public function - see documentation comment in header file. 896 | struct qrcodegen_Segment qrcodegen_makeNumeric(const char *digits, uint8_t buf[]) { 897 | assert(digits != NULL); 898 | struct qrcodegen_Segment result; 899 | size_t len = strlen(digits); 900 | result.mode = qrcodegen_Mode_NUMERIC; 901 | int bitLen = calcSegmentBitLength(result.mode, len); 902 | assert(bitLen != LENGTH_OVERFLOW); 903 | result.numChars = (int)len; 904 | if (bitLen > 0) 905 | memset(buf, 0, ((size_t)bitLen + 7) / 8 * sizeof(buf[0])); 906 | result.bitLength = 0; 907 | 908 | unsigned int accumData = 0; 909 | int accumCount = 0; 910 | for (; *digits != '\0'; digits++) { 911 | char c = *digits; 912 | assert('0' <= c && c <= '9'); 913 | accumData = accumData * 10 + (unsigned int)(c - '0'); 914 | accumCount++; 915 | if (accumCount == 3) { 916 | appendBitsToBuffer(accumData, 10, buf, &result.bitLength); 917 | accumData = 0; 918 | accumCount = 0; 919 | } 920 | } 921 | if (accumCount > 0) // 1 or 2 digits remaining 922 | appendBitsToBuffer(accumData, accumCount * 3 + 1, buf, &result.bitLength); 923 | assert(result.bitLength == bitLen); 924 | result.data = buf; 925 | return result; 926 | } 927 | 928 | 929 | // Public function - see documentation comment in header file. 930 | struct qrcodegen_Segment qrcodegen_makeAlphanumeric(const char *text, uint8_t buf[]) { 931 | assert(text != NULL); 932 | struct qrcodegen_Segment result; 933 | size_t len = strlen(text); 934 | result.mode = qrcodegen_Mode_ALPHANUMERIC; 935 | int bitLen = calcSegmentBitLength(result.mode, len); 936 | assert(bitLen != LENGTH_OVERFLOW); 937 | result.numChars = (int)len; 938 | if (bitLen > 0) 939 | memset(buf, 0, ((size_t)bitLen + 7) / 8 * sizeof(buf[0])); 940 | result.bitLength = 0; 941 | 942 | unsigned int accumData = 0; 943 | int accumCount = 0; 944 | for (; *text != '\0'; text++) { 945 | const char *temp = strchr(ALPHANUMERIC_CHARSET, *text); 946 | assert(temp != NULL); 947 | accumData = accumData * 45 + (unsigned int)(temp - ALPHANUMERIC_CHARSET); 948 | accumCount++; 949 | if (accumCount == 2) { 950 | appendBitsToBuffer(accumData, 11, buf, &result.bitLength); 951 | accumData = 0; 952 | accumCount = 0; 953 | } 954 | } 955 | if (accumCount > 0) // 1 character remaining 956 | appendBitsToBuffer(accumData, 6, buf, &result.bitLength); 957 | assert(result.bitLength == bitLen); 958 | result.data = buf; 959 | return result; 960 | } 961 | 962 | 963 | // Public function - see documentation comment in header file. 964 | struct qrcodegen_Segment qrcodegen_makeEci(long assignVal, uint8_t buf[]) { 965 | struct qrcodegen_Segment result; 966 | result.mode = qrcodegen_Mode_ECI; 967 | result.numChars = 0; 968 | result.bitLength = 0; 969 | if (assignVal < 0) 970 | assert(false); 971 | else if (assignVal < (1 << 7)) { 972 | memset(buf, 0, 1 * sizeof(buf[0])); 973 | appendBitsToBuffer((unsigned int)assignVal, 8, buf, &result.bitLength); 974 | } else if (assignVal < (1 << 14)) { 975 | memset(buf, 0, 2 * sizeof(buf[0])); 976 | appendBitsToBuffer(2, 2, buf, &result.bitLength); 977 | appendBitsToBuffer((unsigned int)assignVal, 14, buf, &result.bitLength); 978 | } else if (assignVal < 1000000L) { 979 | memset(buf, 0, 3 * sizeof(buf[0])); 980 | appendBitsToBuffer(6, 3, buf, &result.bitLength); 981 | appendBitsToBuffer((unsigned int)(assignVal >> 10), 11, buf, &result.bitLength); 982 | appendBitsToBuffer((unsigned int)(assignVal & 0x3FF), 10, buf, &result.bitLength); 983 | } else 984 | assert(false); 985 | result.data = buf; 986 | return result; 987 | } 988 | 989 | 990 | // Calculates the number of bits needed to encode the given segments at the given version. 991 | // Returns a non-negative number if successful. Otherwise returns LENGTH_OVERFLOW if a segment 992 | // has too many characters to fit its length field, or the total bits exceeds INT16_MAX. 993 | testable int getTotalBits(const struct qrcodegen_Segment segs[], size_t len, int version) { 994 | assert(segs != NULL || len == 0); 995 | long result = 0; 996 | for (size_t i = 0; i < len; i++) { 997 | int numChars = segs[i].numChars; 998 | int bitLength = segs[i].bitLength; 999 | assert(0 <= numChars && numChars <= INT16_MAX); 1000 | assert(0 <= bitLength && bitLength <= INT16_MAX); 1001 | int ccbits = numCharCountBits(segs[i].mode, version); 1002 | assert(0 <= ccbits && ccbits <= 16); 1003 | if (numChars >= (1L << ccbits)) 1004 | return LENGTH_OVERFLOW; // The segment's length doesn't fit the field's bit width 1005 | result += 4L + ccbits + bitLength; 1006 | if (result > INT16_MAX) 1007 | return LENGTH_OVERFLOW; // The sum might overflow an int type 1008 | } 1009 | assert(0 <= result && result <= INT16_MAX); 1010 | return (int)result; 1011 | } 1012 | 1013 | 1014 | // Returns the bit width of the character count field for a segment in the given mode 1015 | // in a QR Code at the given version number. The result is in the range [0, 16]. 1016 | static int numCharCountBits(enum qrcodegen_Mode mode, int version) { 1017 | assert(qrcodegen_VERSION_MIN <= version && version <= qrcodegen_VERSION_MAX); 1018 | int i = (version + 7) / 17; 1019 | switch (mode) { 1020 | case qrcodegen_Mode_NUMERIC : { static const int temp[] = {10, 12, 14}; return temp[i]; } 1021 | case qrcodegen_Mode_ALPHANUMERIC: { static const int temp[] = { 9, 11, 13}; return temp[i]; } 1022 | case qrcodegen_Mode_BYTE : { static const int temp[] = { 8, 16, 16}; return temp[i]; } 1023 | case qrcodegen_Mode_KANJI : { static const int temp[] = { 8, 10, 12}; return temp[i]; } 1024 | case qrcodegen_Mode_ECI : return 0; 1025 | default: assert(false); return -1; // Dummy value 1026 | } 1027 | } 1028 | 1029 | 1030 | #undef LENGTH_OVERFLOW 1031 | -------------------------------------------------------------------------------- /usb_payload/source/qrcodegen.h: -------------------------------------------------------------------------------- 1 | /* 2 | * QR Code generator library (C) 3 | * 4 | * Copyright (c) Project Nayuki. (MIT License) 5 | * https://www.nayuki.io/page/qr-code-generator-library 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy of 8 | * this software and associated documentation files (the "Software"), to deal in 9 | * the Software without restriction, including without limitation the rights to 10 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 11 | * the Software, and to permit persons to whom the Software is furnished to do so, 12 | * subject to the following conditions: 13 | * - The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * - The Software is provided "as is", without warranty of any kind, express or 16 | * implied, including but not limited to the warranties of merchantability, 17 | * fitness for a particular purpose and noninfringement. In no event shall the 18 | * authors or copyright holders be liable for any claim, damages or other 19 | * liability, whether in an action of contract, tort or otherwise, arising from, 20 | * out of or in connection with the Software or the use or other dealings in the 21 | * Software. 22 | */ 23 | 24 | #pragma once 25 | 26 | #include 27 | #include 28 | #include 29 | 30 | 31 | #ifdef __cplusplus 32 | extern "C" { 33 | #endif 34 | 35 | 36 | /* 37 | * This library creates QR Code symbols, which is a type of two-dimension barcode. 38 | * Invented by Denso Wave and described in the ISO/IEC 18004 standard. 39 | * A QR Code structure is an immutable square grid of dark and light cells. 40 | * The library provides functions to create a QR Code from text or binary data. 41 | * The library covers the QR Code Model 2 specification, supporting all versions (sizes) 42 | * from 1 to 40, all 4 error correction levels, and 4 character encoding modes. 43 | * 44 | * Ways to create a QR Code object: 45 | * - High level: Take the payload data and call qrcodegen_encodeText() or qrcodegen_encodeBinary(). 46 | * - Low level: Custom-make the list of segments and call 47 | * qrcodegen_encodeSegments() or qrcodegen_encodeSegmentsAdvanced(). 48 | * (Note that all ways require supplying the desired error correction level and various byte buffers.) 49 | */ 50 | 51 | 52 | /*---- Enum and struct types----*/ 53 | 54 | /* 55 | * The error correction level in a QR Code symbol. 56 | */ 57 | enum qrcodegen_Ecc { 58 | // Must be declared in ascending order of error protection 59 | // so that an internal qrcodegen function works properly 60 | qrcodegen_Ecc_LOW = 0 , // The QR Code can tolerate about 7% erroneous codewords 61 | qrcodegen_Ecc_MEDIUM , // The QR Code can tolerate about 15% erroneous codewords 62 | qrcodegen_Ecc_QUARTILE, // The QR Code can tolerate about 25% erroneous codewords 63 | qrcodegen_Ecc_HIGH , // The QR Code can tolerate about 30% erroneous codewords 64 | }; 65 | 66 | 67 | /* 68 | * The mask pattern used in a QR Code symbol. 69 | */ 70 | enum qrcodegen_Mask { 71 | // A special value to tell the QR Code encoder to 72 | // automatically select an appropriate mask pattern 73 | qrcodegen_Mask_AUTO = -1, 74 | // The eight actual mask patterns 75 | qrcodegen_Mask_0 = 0, 76 | qrcodegen_Mask_1, 77 | qrcodegen_Mask_2, 78 | qrcodegen_Mask_3, 79 | qrcodegen_Mask_4, 80 | qrcodegen_Mask_5, 81 | qrcodegen_Mask_6, 82 | qrcodegen_Mask_7, 83 | }; 84 | 85 | 86 | /* 87 | * Describes how a segment's data bits are interpreted. 88 | */ 89 | enum qrcodegen_Mode { 90 | qrcodegen_Mode_NUMERIC = 0x1, 91 | qrcodegen_Mode_ALPHANUMERIC = 0x2, 92 | qrcodegen_Mode_BYTE = 0x4, 93 | qrcodegen_Mode_KANJI = 0x8, 94 | qrcodegen_Mode_ECI = 0x7, 95 | }; 96 | 97 | 98 | /* 99 | * A segment of character/binary/control data in a QR Code symbol. 100 | * The mid-level way to create a segment is to take the payload data 101 | * and call a factory function such as qrcodegen_makeNumeric(). 102 | * The low-level way to create a segment is to custom-make the bit buffer 103 | * and initialize a qrcodegen_Segment struct with appropriate values. 104 | * Even in the most favorable conditions, a QR Code can only hold 7089 characters of data. 105 | * Any segment longer than this is meaningless for the purpose of generating QR Codes. 106 | * Moreover, the maximum allowed bit length is 32767 because 107 | * the largest QR Code (version 40) has 31329 modules. 108 | */ 109 | struct qrcodegen_Segment { 110 | // The mode indicator of this segment. 111 | enum qrcodegen_Mode mode; 112 | 113 | // The length of this segment's unencoded data. Measured in characters for 114 | // numeric/alphanumeric/kanji mode, bytes for byte mode, and 0 for ECI mode. 115 | // Always zero or positive. Not the same as the data's bit length. 116 | int numChars; 117 | 118 | // The data bits of this segment, packed in bitwise big endian. 119 | // Can be null if the bit length is zero. 120 | uint8_t *data; 121 | 122 | // The number of valid data bits used in the buffer. Requires 123 | // 0 <= bitLength <= 32767, and bitLength <= (capacity of data array) * 8. 124 | // The character count (numChars) must agree with the mode and the bit buffer length. 125 | int bitLength; 126 | }; 127 | 128 | 129 | 130 | /*---- Macro constants and functions ----*/ 131 | 132 | #define qrcodegen_VERSION_MIN 1 // The minimum version number supported in the QR Code Model 2 standard 133 | #define qrcodegen_VERSION_MAX 40 // The maximum version number supported in the QR Code Model 2 standard 134 | 135 | // Calculates the number of bytes needed to store any QR Code up to and including the given version number, 136 | // as a compile-time constant. For example, 'uint8_t buffer[qrcodegen_BUFFER_LEN_FOR_VERSION(25)];' 137 | // can store any single QR Code from version 1 to 25 (inclusive). The result fits in an int (or int16). 138 | // Requires qrcodegen_VERSION_MIN <= n <= qrcodegen_VERSION_MAX. 139 | #define qrcodegen_BUFFER_LEN_FOR_VERSION(n) ((((n) * 4 + 17) * ((n) * 4 + 17) + 7) / 8 + 1) 140 | 141 | // The worst-case number of bytes needed to store one QR Code, up to and including 142 | // version 40. This value equals 3918, which is just under 4 kilobytes. 143 | // Use this more convenient value to avoid calculating tighter memory bounds for buffers. 144 | #define qrcodegen_BUFFER_LEN_MAX qrcodegen_BUFFER_LEN_FOR_VERSION(qrcodegen_VERSION_MAX) 145 | 146 | 147 | 148 | /*---- Functions (high level) to generate QR Codes ----*/ 149 | 150 | /* 151 | * Encodes the given text string to a QR Code, returning true if successful. 152 | * If the data is too long to fit in any version in the given range 153 | * at the given ECC level, then false is returned. 154 | * 155 | * The input text must be encoded in UTF-8 and contain no NULs. 156 | * Requires 1 <= minVersion <= maxVersion <= 40. 157 | * 158 | * The smallest possible QR Code version within the given range is automatically 159 | * chosen for the output. Iff boostEcl is true, then the ECC level of the result 160 | * may be higher than the ecl argument if it can be done without increasing the 161 | * version. The mask is either between qrcodegen_Mask_0 to 7 to force that mask, or 162 | * qrcodegen_Mask_AUTO to automatically choose an appropriate mask (which may be slow). 163 | * 164 | * About the arrays, letting len = qrcodegen_BUFFER_LEN_FOR_VERSION(maxVersion): 165 | * - Before calling the function: 166 | * - The array ranges tempBuffer[0 : len] and qrcode[0 : len] must allow 167 | * reading and writing; hence each array must have a length of at least len. 168 | * - The two ranges must not overlap (aliasing). 169 | * - The initial state of both ranges can be uninitialized 170 | * because the function always writes before reading. 171 | * - After the function returns: 172 | * - Both ranges have no guarantee on which elements are initialized and what values are stored. 173 | * - tempBuffer contains no useful data and should be treated as entirely uninitialized. 174 | * - If successful, qrcode can be passed into qrcodegen_getSize() and qrcodegen_getModule(). 175 | * 176 | * If successful, the resulting QR Code may use numeric, 177 | * alphanumeric, or byte mode to encode the text. 178 | * 179 | * In the most optimistic case, a QR Code at version 40 with low ECC 180 | * can hold any UTF-8 string up to 2953 bytes, or any alphanumeric string 181 | * up to 4296 characters, or any digit string up to 7089 characters. 182 | * These numbers represent the hard upper limit of the QR Code standard. 183 | * 184 | * Please consult the QR Code specification for information on 185 | * data capacities per version, ECC level, and text encoding mode. 186 | */ 187 | bool qrcodegen_encodeText(const char *text, uint8_t tempBuffer[], uint8_t qrcode[], 188 | enum qrcodegen_Ecc ecl, int minVersion, int maxVersion, enum qrcodegen_Mask mask, bool boostEcl); 189 | 190 | 191 | /* 192 | * Encodes the given binary data to a QR Code, returning true if successful. 193 | * If the data is too long to fit in any version in the given range 194 | * at the given ECC level, then false is returned. 195 | * 196 | * Requires 1 <= minVersion <= maxVersion <= 40. 197 | * 198 | * The smallest possible QR Code version within the given range is automatically 199 | * chosen for the output. Iff boostEcl is true, then the ECC level of the result 200 | * may be higher than the ecl argument if it can be done without increasing the 201 | * version. The mask is either between qrcodegen_Mask_0 to 7 to force that mask, or 202 | * qrcodegen_Mask_AUTO to automatically choose an appropriate mask (which may be slow). 203 | * 204 | * About the arrays, letting len = qrcodegen_BUFFER_LEN_FOR_VERSION(maxVersion): 205 | * - Before calling the function: 206 | * - The array ranges dataAndTemp[0 : len] and qrcode[0 : len] must allow 207 | * reading and writing; hence each array must have a length of at least len. 208 | * - The two ranges must not overlap (aliasing). 209 | * - The input array range dataAndTemp[0 : dataLen] should normally be 210 | * valid UTF-8 text, but is not required by the QR Code standard. 211 | * - The initial state of dataAndTemp[dataLen : len] and qrcode[0 : len] 212 | * can be uninitialized because the function always writes before reading. 213 | * - After the function returns: 214 | * - Both ranges have no guarantee on which elements are initialized and what values are stored. 215 | * - dataAndTemp contains no useful data and should be treated as entirely uninitialized. 216 | * - If successful, qrcode can be passed into qrcodegen_getSize() and qrcodegen_getModule(). 217 | * 218 | * If successful, the resulting QR Code will use byte mode to encode the data. 219 | * 220 | * In the most optimistic case, a QR Code at version 40 with low ECC can hold any byte 221 | * sequence up to length 2953. This is the hard upper limit of the QR Code standard. 222 | * 223 | * Please consult the QR Code specification for information on 224 | * data capacities per version, ECC level, and text encoding mode. 225 | */ 226 | bool qrcodegen_encodeBinary(uint8_t dataAndTemp[], size_t dataLen, uint8_t qrcode[], 227 | enum qrcodegen_Ecc ecl, int minVersion, int maxVersion, enum qrcodegen_Mask mask, bool boostEcl); 228 | 229 | 230 | /*---- Functions (low level) to generate QR Codes ----*/ 231 | 232 | /* 233 | * Encodes the given segments to a QR Code, returning true if successful. 234 | * If the data is too long to fit in any version at the given ECC level, 235 | * then false is returned. 236 | * 237 | * The smallest possible QR Code version is automatically chosen for 238 | * the output. The ECC level of the result may be higher than the 239 | * ecl argument if it can be done without increasing the version. 240 | * 241 | * About the byte arrays, letting len = qrcodegen_BUFFER_LEN_FOR_VERSION(qrcodegen_VERSION_MAX): 242 | * - Before calling the function: 243 | * - The array ranges tempBuffer[0 : len] and qrcode[0 : len] must allow 244 | * reading and writing; hence each array must have a length of at least len. 245 | * - The two ranges must not overlap (aliasing). 246 | * - The initial state of both ranges can be uninitialized 247 | * because the function always writes before reading. 248 | * - The input array segs can contain segments whose data buffers overlap with tempBuffer. 249 | * - After the function returns: 250 | * - Both ranges have no guarantee on which elements are initialized and what values are stored. 251 | * - tempBuffer contains no useful data and should be treated as entirely uninitialized. 252 | * - Any segment whose data buffer overlaps with tempBuffer[0 : len] 253 | * must be treated as having invalid values in that array. 254 | * - If successful, qrcode can be passed into qrcodegen_getSize() and qrcodegen_getModule(). 255 | * 256 | * Please consult the QR Code specification for information on 257 | * data capacities per version, ECC level, and text encoding mode. 258 | * 259 | * This function allows the user to create a custom sequence of segments that switches 260 | * between modes (such as alphanumeric and byte) to encode text in less space. 261 | * This is a low-level API; the high-level API is qrcodegen_encodeText() and qrcodegen_encodeBinary(). 262 | */ 263 | bool qrcodegen_encodeSegments(const struct qrcodegen_Segment segs[], size_t len, 264 | enum qrcodegen_Ecc ecl, uint8_t tempBuffer[], uint8_t qrcode[]); 265 | 266 | 267 | /* 268 | * Encodes the given segments to a QR Code, returning true if successful. 269 | * If the data is too long to fit in any version in the given range 270 | * at the given ECC level, then false is returned. 271 | * 272 | * Requires 1 <= minVersion <= maxVersion <= 40. 273 | * 274 | * The smallest possible QR Code version within the given range is automatically 275 | * chosen for the output. Iff boostEcl is true, then the ECC level of the result 276 | * may be higher than the ecl argument if it can be done without increasing the 277 | * version. The mask is either between qrcodegen_Mask_0 to 7 to force that mask, or 278 | * qrcodegen_Mask_AUTO to automatically choose an appropriate mask (which may be slow). 279 | * 280 | * About the byte arrays, letting len = qrcodegen_BUFFER_LEN_FOR_VERSION(qrcodegen_VERSION_MAX): 281 | * - Before calling the function: 282 | * - The array ranges tempBuffer[0 : len] and qrcode[0 : len] must allow 283 | * reading and writing; hence each array must have a length of at least len. 284 | * - The two ranges must not overlap (aliasing). 285 | * - The initial state of both ranges can be uninitialized 286 | * because the function always writes before reading. 287 | * - The input array segs can contain segments whose data buffers overlap with tempBuffer. 288 | * - After the function returns: 289 | * - Both ranges have no guarantee on which elements are initialized and what values are stored. 290 | * - tempBuffer contains no useful data and should be treated as entirely uninitialized. 291 | * - Any segment whose data buffer overlaps with tempBuffer[0 : len] 292 | * must be treated as having invalid values in that array. 293 | * - If successful, qrcode can be passed into qrcodegen_getSize() and qrcodegen_getModule(). 294 | * 295 | * Please consult the QR Code specification for information on 296 | * data capacities per version, ECC level, and text encoding mode. 297 | * 298 | * This function allows the user to create a custom sequence of segments that switches 299 | * between modes (such as alphanumeric and byte) to encode text in less space. 300 | * This is a low-level API; the high-level API is qrcodegen_encodeText() and qrcodegen_encodeBinary(). 301 | */ 302 | bool qrcodegen_encodeSegmentsAdvanced(const struct qrcodegen_Segment segs[], size_t len, enum qrcodegen_Ecc ecl, 303 | int minVersion, int maxVersion, enum qrcodegen_Mask mask, bool boostEcl, uint8_t tempBuffer[], uint8_t qrcode[]); 304 | 305 | 306 | /* 307 | * Tests whether the given string can be encoded as a segment in numeric mode. 308 | * A string is encodable iff each character is in the range 0 to 9. 309 | */ 310 | bool qrcodegen_isNumeric(const char *text); 311 | 312 | 313 | /* 314 | * Tests whether the given string can be encoded as a segment in alphanumeric mode. 315 | * A string is encodable iff each character is in the following set: 0 to 9, A to Z 316 | * (uppercase only), space, dollar, percent, asterisk, plus, hyphen, period, slash, colon. 317 | */ 318 | bool qrcodegen_isAlphanumeric(const char *text); 319 | 320 | 321 | /* 322 | * Returns the number of bytes (uint8_t) needed for the data buffer of a segment 323 | * containing the given number of characters using the given mode. Notes: 324 | * - Returns SIZE_MAX on failure, i.e. numChars > INT16_MAX or the internal 325 | * calculation of the number of needed bits exceeds INT16_MAX (i.e. 32767). 326 | * - Otherwise, all valid results are in the range [0, ceil(INT16_MAX / 8)], i.e. at most 4096. 327 | * - It is okay for the user to allocate more bytes for the buffer than needed. 328 | * - For byte mode, numChars measures the number of bytes, not Unicode code points. 329 | * - For ECI mode, numChars must be 0, and the worst-case number of bytes is returned. 330 | * An actual ECI segment can have shorter data. For non-ECI modes, the result is exact. 331 | */ 332 | size_t qrcodegen_calcSegmentBufferSize(enum qrcodegen_Mode mode, size_t numChars); 333 | 334 | 335 | /* 336 | * Returns a segment representing the given binary data encoded in 337 | * byte mode. All input byte arrays are acceptable. Any text string 338 | * can be converted to UTF-8 bytes and encoded as a byte mode segment. 339 | */ 340 | struct qrcodegen_Segment qrcodegen_makeBytes(const uint8_t data[], size_t len, uint8_t buf[]); 341 | 342 | 343 | /* 344 | * Returns a segment representing the given string of decimal digits encoded in numeric mode. 345 | */ 346 | struct qrcodegen_Segment qrcodegen_makeNumeric(const char *digits, uint8_t buf[]); 347 | 348 | 349 | /* 350 | * Returns a segment representing the given text string encoded in alphanumeric mode. 351 | * The characters allowed are: 0 to 9, A to Z (uppercase only), space, 352 | * dollar, percent, asterisk, plus, hyphen, period, slash, colon. 353 | */ 354 | struct qrcodegen_Segment qrcodegen_makeAlphanumeric(const char *text, uint8_t buf[]); 355 | 356 | 357 | /* 358 | * Returns a segment representing an Extended Channel Interpretation 359 | * (ECI) designator with the given assignment value. 360 | */ 361 | struct qrcodegen_Segment qrcodegen_makeEci(long assignVal, uint8_t buf[]); 362 | 363 | 364 | /*---- Functions to extract raw data from QR Codes ----*/ 365 | 366 | /* 367 | * Returns the side length of the given QR Code, assuming that encoding succeeded. 368 | * The result is in the range [21, 177]. Note that the length of the array buffer 369 | * is related to the side length - every 'uint8_t qrcode[]' must have length at least 370 | * qrcodegen_BUFFER_LEN_FOR_VERSION(version), which equals ceil(size^2 / 8 + 1). 371 | */ 372 | int qrcodegen_getSize(const uint8_t qrcode[]); 373 | 374 | 375 | /* 376 | * Returns the color of the module (pixel) at the given coordinates, which is false 377 | * for light or true for dark. The top left corner has the coordinates (x=0, y=0). 378 | * If the given coordinates are out of bounds, then false (light) is returned. 379 | */ 380 | bool qrcodegen_getModule(const uint8_t qrcode[], int x, int y); 381 | 382 | 383 | #ifdef __cplusplus 384 | } 385 | #endif 386 | -------------------------------------------------------------------------------- /usb_payload/source/startup_stm32h730xx.s: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * @file startup_stm32h730xx.s 4 | * @author MCD Application Team 5 | * @brief STM32H730xx Devices vector table for GCC based toolchain. 6 | * This module performs: 7 | * - Set the initial SP 8 | * - Set the initial PC == Reset_Handler, 9 | * - Set the vector table entries with the exceptions ISR address 10 | * - Branches to main in the C library (which eventually 11 | * calls main()). 12 | * After Reset the Cortex-M processor is in Thread mode, 13 | * priority is Privileged, and the Stack is set to Main. 14 | ****************************************************************************** 15 | * @attention 16 | * 17 | * Copyright (c) 2019 STMicroelectronics. 18 | * All rights reserved. 19 | * 20 | * This software is licensed under terms that can be found in the LICENSE file 21 | * in the root directory of this software component. 22 | * If no LICENSE file comes with this software, it is provided AS-IS. 23 | * 24 | ****************************************************************************** 25 | */ 26 | 27 | .syntax unified 28 | .cpu cortex-m7 29 | .fpu softvfp 30 | .thumb 31 | 32 | .global g_pfnVectors 33 | .global Default_Handler 34 | 35 | /* start address for the initialization values of the .data section. 36 | defined in linker script */ 37 | .word _sidata 38 | /* start address for the .data section. defined in linker script */ 39 | .word _sdata 40 | /* end address for the .data section. defined in linker script */ 41 | .word _edata 42 | /* start address for the .bss section. defined in linker script */ 43 | .word _sbss 44 | /* end address for the .bss section. defined in linker script */ 45 | .word _ebss 46 | /* stack used for SystemInit_ExtMemCtl; always internal RAM used */ 47 | 48 | /** 49 | * @brief This is the code that gets called when the processor first 50 | * starts execution following a reset event. Only the absolutely 51 | * necessary set is performed, after which the application 52 | * supplied main() routine is called. 53 | * @param None 54 | * @retval : None 55 | */ 56 | 57 | .section .text.Reset_Handler 58 | .weak Reset_Handler 59 | .type Reset_Handler, %function 60 | Reset_Handler: 61 | ldr sp, =_estack /* set stack pointer */ 62 | 63 | /* Call the clock system initialization function.*/ 64 | bl SystemInit 65 | 66 | /* Copy the data segment initializers from flash to SRAM */ 67 | ldr r0, =_sdata 68 | ldr r1, =_edata 69 | ldr r2, =_sidata 70 | movs r3, #0 71 | b LoopCopyDataInit 72 | 73 | CopyDataInit: 74 | ldr r4, [r2, r3] 75 | str r4, [r0, r3] 76 | adds r3, r3, #4 77 | 78 | LoopCopyDataInit: 79 | adds r4, r0, r3 80 | cmp r4, r1 81 | bcc CopyDataInit 82 | /* Zero fill the bss segment. */ 83 | ldr r2, =_sbss 84 | ldr r4, =_ebss 85 | movs r3, #0 86 | b LoopFillZerobss 87 | 88 | FillZerobss: 89 | str r3, [r2] 90 | adds r2, r2, #4 91 | 92 | LoopFillZerobss: 93 | cmp r2, r4 94 | bcc FillZerobss 95 | 96 | /* Call static constructors */ 97 | bl __libc_init_array 98 | /* Call the application's entry point.*/ 99 | bl main 100 | bx lr 101 | .size Reset_Handler, .-Reset_Handler 102 | 103 | /** 104 | * @brief This is the code that gets called when the processor receives an 105 | * unexpected interrupt. This simply enters an infinite loop, preserving 106 | * the system state for examination by a debugger. 107 | * @param None 108 | * @retval None 109 | */ 110 | .section .text.Default_Handler,"ax",%progbits 111 | Default_Handler: 112 | Infinite_Loop: 113 | b Infinite_Loop 114 | .size Default_Handler, .-Default_Handler 115 | /****************************************************************************** 116 | * 117 | * The minimal vector table for a Cortex M. Note that the proper constructs 118 | * must be placed on this to ensure that it ends up at physical address 119 | * 0x0000.0000. 120 | * 121 | *******************************************************************************/ 122 | .section .isr_vector,"a",%progbits 123 | .type g_pfnVectors, %object 124 | 125 | 126 | g_pfnVectors: 127 | .word _estack 128 | .word Reset_Handler 129 | 130 | .word NMI_Handler 131 | .word HardFault_Handler 132 | .word MemManage_Handler 133 | .word BusFault_Handler 134 | .word UsageFault_Handler 135 | .word 0 136 | .word 0 137 | .word 0 138 | .word 0 139 | .word SVC_Handler 140 | .word DebugMon_Handler 141 | .word 0 142 | .word PendSV_Handler 143 | .word SysTick_Handler 144 | 145 | /* External Interrupts */ 146 | .word WWDG_IRQHandler /* Window WatchDog */ 147 | .word PVD_AVD_IRQHandler /* PVD/AVD through EXTI Line detection */ 148 | .word TAMP_STAMP_IRQHandler /* Tamper and TimeStamps through the EXTI line */ 149 | .word RTC_WKUP_IRQHandler /* RTC Wakeup through the EXTI line */ 150 | .word FLASH_IRQHandler /* FLASH */ 151 | .word RCC_IRQHandler /* RCC */ 152 | .word EXTI0_IRQHandler /* EXTI Line0 */ 153 | .word EXTI1_IRQHandler /* EXTI Line1 */ 154 | .word EXTI2_IRQHandler /* EXTI Line2 */ 155 | .word EXTI3_IRQHandler /* EXTI Line3 */ 156 | .word EXTI4_IRQHandler /* EXTI Line4 */ 157 | .word DMA1_Stream0_IRQHandler /* DMA1 Stream 0 */ 158 | .word DMA1_Stream1_IRQHandler /* DMA1 Stream 1 */ 159 | .word DMA1_Stream2_IRQHandler /* DMA1 Stream 2 */ 160 | .word DMA1_Stream3_IRQHandler /* DMA1 Stream 3 */ 161 | .word DMA1_Stream4_IRQHandler /* DMA1 Stream 4 */ 162 | .word DMA1_Stream5_IRQHandler /* DMA1 Stream 5 */ 163 | .word DMA1_Stream6_IRQHandler /* DMA1 Stream 6 */ 164 | .word ADC_IRQHandler /* ADC1, ADC2 and ADC3s */ 165 | .word FDCAN1_IT0_IRQHandler /* FDCAN1 interrupt line 0 */ 166 | .word FDCAN2_IT0_IRQHandler /* FDCAN2 interrupt line 0 */ 167 | .word FDCAN1_IT1_IRQHandler /* FDCAN1 interrupt line 1 */ 168 | .word FDCAN2_IT1_IRQHandler /* FDCAN2 interrupt line 1 */ 169 | .word EXTI9_5_IRQHandler /* External Line[9:5]s */ 170 | .word TIM1_BRK_IRQHandler /* TIM1 Break interrupt */ 171 | .word TIM1_UP_IRQHandler /* TIM1 Update interrupt */ 172 | .word TIM1_TRG_COM_IRQHandler /* TIM1 Trigger and Commutation interrupt */ 173 | .word TIM1_CC_IRQHandler /* TIM1 Capture Compare */ 174 | .word TIM2_IRQHandler /* TIM2 */ 175 | .word TIM3_IRQHandler /* TIM3 */ 176 | .word TIM4_IRQHandler /* TIM4 */ 177 | .word I2C1_EV_IRQHandler /* I2C1 Event */ 178 | .word I2C1_ER_IRQHandler /* I2C1 Error */ 179 | .word I2C2_EV_IRQHandler /* I2C2 Event */ 180 | .word I2C2_ER_IRQHandler /* I2C2 Error */ 181 | .word SPI1_IRQHandler /* SPI1 */ 182 | .word SPI2_IRQHandler /* SPI2 */ 183 | .word USART1_IRQHandler /* USART1 */ 184 | .word USART2_IRQHandler /* USART2 */ 185 | .word USART3_IRQHandler /* USART3 */ 186 | .word EXTI15_10_IRQHandler /* External Line[15:10]s */ 187 | .word RTC_Alarm_IRQHandler /* RTC Alarm (A and B) through EXTI Line */ 188 | .word 0 /* Reserved */ 189 | .word TIM8_BRK_TIM12_IRQHandler /* TIM8 Break and TIM12 */ 190 | .word TIM8_UP_TIM13_IRQHandler /* TIM8 Update and TIM13 */ 191 | .word TIM8_TRG_COM_TIM14_IRQHandler /* TIM8 Trigger and Commutation and TIM14 */ 192 | .word TIM8_CC_IRQHandler /* TIM8 Capture Compare */ 193 | .word DMA1_Stream7_IRQHandler /* DMA1 Stream7 */ 194 | .word FMC_IRQHandler /* FMC */ 195 | .word SDMMC1_IRQHandler /* SDMMC1 */ 196 | .word TIM5_IRQHandler /* TIM5 */ 197 | .word SPI3_IRQHandler /* SPI3 */ 198 | .word UART4_IRQHandler /* UART4 */ 199 | .word UART5_IRQHandler /* UART5 */ 200 | .word TIM6_DAC_IRQHandler /* TIM6 and DAC1&2 underrun errors */ 201 | .word TIM7_IRQHandler /* TIM7 */ 202 | .word DMA2_Stream0_IRQHandler /* DMA2 Stream 0 */ 203 | .word DMA2_Stream1_IRQHandler /* DMA2 Stream 1 */ 204 | .word DMA2_Stream2_IRQHandler /* DMA2 Stream 2 */ 205 | .word DMA2_Stream3_IRQHandler /* DMA2 Stream 3 */ 206 | .word DMA2_Stream4_IRQHandler /* DMA2 Stream 4 */ 207 | .word ETH_IRQHandler /* Ethernet */ 208 | .word ETH_WKUP_IRQHandler /* Ethernet Wakeup through EXTI line */ 209 | .word FDCAN_CAL_IRQHandler /* FDCAN calibration unit interrupt*/ 210 | .word 0 /* Reserved */ 211 | .word 0 /* Reserved */ 212 | .word 0 /* Reserved */ 213 | .word 0 /* Reserved */ 214 | .word DMA2_Stream5_IRQHandler /* DMA2 Stream 5 */ 215 | .word DMA2_Stream6_IRQHandler /* DMA2 Stream 6 */ 216 | .word DMA2_Stream7_IRQHandler /* DMA2 Stream 7 */ 217 | .word USART6_IRQHandler /* USART6 */ 218 | .word I2C3_EV_IRQHandler /* I2C3 event */ 219 | .word I2C3_ER_IRQHandler /* I2C3 error */ 220 | .word OTG_HS_EP1_OUT_IRQHandler /* USB OTG HS End Point 1 Out */ 221 | .word OTG_HS_EP1_IN_IRQHandler /* USB OTG HS End Point 1 In */ 222 | .word OTG_HS_WKUP_IRQHandler /* USB OTG HS Wakeup through EXTI */ 223 | .word OTG_HS_IRQHandler /* USB OTG HS */ 224 | .word DCMI_PSSI_IRQHandler /* DCMI, PSSI */ 225 | .word CRYP_IRQHandler /* CRYP */ 226 | .word HASH_RNG_IRQHandler /* Hash and Rng */ 227 | .word FPU_IRQHandler /* FPU */ 228 | .word UART7_IRQHandler /* UART7 */ 229 | .word UART8_IRQHandler /* UART8 */ 230 | .word SPI4_IRQHandler /* SPI4 */ 231 | .word SPI5_IRQHandler /* SPI5 */ 232 | .word SPI6_IRQHandler /* SPI6 */ 233 | .word SAI1_IRQHandler /* SAI1 */ 234 | .word LTDC_IRQHandler /* LTDC */ 235 | .word LTDC_ER_IRQHandler /* LTDC error */ 236 | .word DMA2D_IRQHandler /* DMA2D */ 237 | .word 0 /* Reserved */ 238 | .word OCTOSPI1_IRQHandler /* OCTOSPI1 */ 239 | .word LPTIM1_IRQHandler /* LPTIM1 */ 240 | .word CEC_IRQHandler /* HDMI_CEC */ 241 | .word I2C4_EV_IRQHandler /* I2C4 Event */ 242 | .word I2C4_ER_IRQHandler /* I2C4 Error */ 243 | .word SPDIF_RX_IRQHandler /* SPDIF_RX */ 244 | .word 0 /* Reserved */ 245 | .word 0 /* Reserved */ 246 | .word 0 /* Reserved */ 247 | .word 0 /* Reserved */ 248 | .word DMAMUX1_OVR_IRQHandler /* DMAMUX1 Overrun interrupt */ 249 | .word 0 /* Reserved */ 250 | .word 0 /* Reserved */ 251 | .word 0 /* Reserved */ 252 | .word 0 /* Reserved */ 253 | .word 0 /* Reserved */ 254 | .word 0 /* Reserved */ 255 | .word 0 /* Reserved */ 256 | .word DFSDM1_FLT0_IRQHandler /* DFSDM Filter0 Interrupt */ 257 | .word DFSDM1_FLT1_IRQHandler /* DFSDM Filter1 Interrupt */ 258 | .word DFSDM1_FLT2_IRQHandler /* DFSDM Filter2 Interrupt */ 259 | .word DFSDM1_FLT3_IRQHandler /* DFSDM Filter3 Interrupt */ 260 | .word 0 /* Reserved */ 261 | .word SWPMI1_IRQHandler /* Serial Wire Interface 1 global interrupt */ 262 | .word TIM15_IRQHandler /* TIM15 global Interrupt */ 263 | .word TIM16_IRQHandler /* TIM16 global Interrupt */ 264 | .word TIM17_IRQHandler /* TIM17 global Interrupt */ 265 | .word MDIOS_WKUP_IRQHandler /* MDIOS Wakeup Interrupt */ 266 | .word MDIOS_IRQHandler /* MDIOS global Interrupt */ 267 | .word 0 /* Reserved */ 268 | .word MDMA_IRQHandler /* MDMA global Interrupt */ 269 | .word 0 /* Reserved */ 270 | .word SDMMC2_IRQHandler /* SDMMC2 global Interrupt */ 271 | .word HSEM1_IRQHandler /* HSEM1 global Interrupt */ 272 | .word 0 /* Reserved */ 273 | .word ADC3_IRQHandler /* ADC3 global Interrupt */ 274 | .word DMAMUX2_OVR_IRQHandler /* DMAMUX Overrun interrupt */ 275 | .word BDMA_Channel0_IRQHandler /* BDMA Channel 0 global Interrupt */ 276 | .word BDMA_Channel1_IRQHandler /* BDMA Channel 1 global Interrupt */ 277 | .word BDMA_Channel2_IRQHandler /* BDMA Channel 2 global Interrupt */ 278 | .word BDMA_Channel3_IRQHandler /* BDMA Channel 3 global Interrupt */ 279 | .word BDMA_Channel4_IRQHandler /* BDMA Channel 4 global Interrupt */ 280 | .word BDMA_Channel5_IRQHandler /* BDMA Channel 5 global Interrupt */ 281 | .word BDMA_Channel6_IRQHandler /* BDMA Channel 6 global Interrupt */ 282 | .word BDMA_Channel7_IRQHandler /* BDMA Channel 7 global Interrupt */ 283 | .word COMP1_IRQHandler /* COMP1 global Interrupt */ 284 | .word LPTIM2_IRQHandler /* LP TIM2 global interrupt */ 285 | .word LPTIM3_IRQHandler /* LP TIM3 global interrupt */ 286 | .word LPTIM4_IRQHandler /* LP TIM4 global interrupt */ 287 | .word LPTIM5_IRQHandler /* LP TIM5 global interrupt */ 288 | .word LPUART1_IRQHandler /* LP UART1 interrupt */ 289 | .word 0 /* Reserved */ 290 | .word CRS_IRQHandler /* Clock Recovery Global Interrupt */ 291 | .word ECC_IRQHandler /* ECC diagnostic Global Interrupt */ 292 | .word SAI4_IRQHandler /* SAI4 global interrupt */ 293 | .word DTS_IRQHandler /* Digital Temperature Sensor interrupt */ 294 | .word 0 /* Reserved */ 295 | .word WAKEUP_PIN_IRQHandler /* Interrupt for all 6 wake-up pins */ 296 | .word OCTOSPI2_IRQHandler /* OCTOSPI2 Interrupt */ 297 | .word OTFDEC1_IRQHandler /* OTFDEC1 Interrupt */ 298 | .word OTFDEC2_IRQHandler /* OTFDEC2 Interrupt */ 299 | .word FMAC_IRQHandler /* FMAC Interrupt */ 300 | .word CORDIC_IRQHandler /* CORDIC Interrupt */ 301 | .word UART9_IRQHandler /* UART9 Interrupt */ 302 | .word USART10_IRQHandler /* UART10 Interrupt */ 303 | .word I2C5_EV_IRQHandler /* I2C5 Event Interrupt */ 304 | .word I2C5_ER_IRQHandler /* I2C5 Error Interrupt */ 305 | .word FDCAN3_IT0_IRQHandler /* FDCAN3 interrupt line 0 */ 306 | .word FDCAN3_IT1_IRQHandler /* FDCAN3 interrupt line 1 */ 307 | .word TIM23_IRQHandler /* TIM23 global interrupt */ 308 | .word TIM24_IRQHandler /* TIM24 global interrupt */ 309 | 310 | .size g_pfnVectors, .-g_pfnVectors 311 | 312 | /******************************************************************************* 313 | * 314 | * Provide weak aliases for each Exception handler to the Default_Handler. 315 | * As they are weak aliases, any function with the same name will override 316 | * this definition. 317 | * 318 | *******************************************************************************/ 319 | .weak NMI_Handler 320 | .thumb_set NMI_Handler,Default_Handler 321 | 322 | .weak HardFault_Handler 323 | .thumb_set HardFault_Handler,Default_Handler 324 | 325 | .weak MemManage_Handler 326 | .thumb_set MemManage_Handler,Default_Handler 327 | 328 | .weak BusFault_Handler 329 | .thumb_set BusFault_Handler,Default_Handler 330 | 331 | .weak UsageFault_Handler 332 | .thumb_set UsageFault_Handler,Default_Handler 333 | 334 | .weak SVC_Handler 335 | .thumb_set SVC_Handler,Default_Handler 336 | 337 | .weak DebugMon_Handler 338 | .thumb_set DebugMon_Handler,Default_Handler 339 | 340 | .weak PendSV_Handler 341 | .thumb_set PendSV_Handler,Default_Handler 342 | 343 | .weak SysTick_Handler 344 | .thumb_set SysTick_Handler,Default_Handler 345 | 346 | .weak WWDG_IRQHandler 347 | .thumb_set WWDG_IRQHandler,Default_Handler 348 | 349 | .weak PVD_AVD_IRQHandler 350 | .thumb_set PVD_AVD_IRQHandler,Default_Handler 351 | 352 | .weak TAMP_STAMP_IRQHandler 353 | .thumb_set TAMP_STAMP_IRQHandler,Default_Handler 354 | 355 | .weak RTC_WKUP_IRQHandler 356 | .thumb_set RTC_WKUP_IRQHandler,Default_Handler 357 | 358 | .weak FLASH_IRQHandler 359 | .thumb_set FLASH_IRQHandler,Default_Handler 360 | 361 | .weak RCC_IRQHandler 362 | .thumb_set RCC_IRQHandler,Default_Handler 363 | 364 | .weak EXTI0_IRQHandler 365 | .thumb_set EXTI0_IRQHandler,Default_Handler 366 | 367 | .weak EXTI1_IRQHandler 368 | .thumb_set EXTI1_IRQHandler,Default_Handler 369 | 370 | .weak EXTI2_IRQHandler 371 | .thumb_set EXTI2_IRQHandler,Default_Handler 372 | 373 | .weak EXTI3_IRQHandler 374 | .thumb_set EXTI3_IRQHandler,Default_Handler 375 | 376 | .weak EXTI4_IRQHandler 377 | .thumb_set EXTI4_IRQHandler,Default_Handler 378 | 379 | .weak DMA1_Stream0_IRQHandler 380 | .thumb_set DMA1_Stream0_IRQHandler,Default_Handler 381 | 382 | .weak DMA1_Stream1_IRQHandler 383 | .thumb_set DMA1_Stream1_IRQHandler,Default_Handler 384 | 385 | .weak DMA1_Stream2_IRQHandler 386 | .thumb_set DMA1_Stream2_IRQHandler,Default_Handler 387 | 388 | .weak DMA1_Stream3_IRQHandler 389 | .thumb_set DMA1_Stream3_IRQHandler,Default_Handler 390 | 391 | .weak DMA1_Stream4_IRQHandler 392 | .thumb_set DMA1_Stream4_IRQHandler,Default_Handler 393 | 394 | .weak DMA1_Stream5_IRQHandler 395 | .thumb_set DMA1_Stream5_IRQHandler,Default_Handler 396 | 397 | .weak DMA1_Stream6_IRQHandler 398 | .thumb_set DMA1_Stream6_IRQHandler,Default_Handler 399 | 400 | .weak ADC_IRQHandler 401 | .thumb_set ADC_IRQHandler,Default_Handler 402 | 403 | .weak FDCAN1_IT0_IRQHandler 404 | .thumb_set FDCAN1_IT0_IRQHandler,Default_Handler 405 | 406 | .weak FDCAN2_IT0_IRQHandler 407 | .thumb_set FDCAN2_IT0_IRQHandler,Default_Handler 408 | 409 | .weak FDCAN1_IT1_IRQHandler 410 | .thumb_set FDCAN1_IT1_IRQHandler,Default_Handler 411 | 412 | .weak FDCAN2_IT1_IRQHandler 413 | .thumb_set FDCAN2_IT1_IRQHandler,Default_Handler 414 | 415 | .weak EXTI9_5_IRQHandler 416 | .thumb_set EXTI9_5_IRQHandler,Default_Handler 417 | 418 | .weak TIM1_BRK_IRQHandler 419 | .thumb_set TIM1_BRK_IRQHandler,Default_Handler 420 | 421 | .weak TIM1_UP_IRQHandler 422 | .thumb_set TIM1_UP_IRQHandler,Default_Handler 423 | 424 | .weak TIM1_TRG_COM_IRQHandler 425 | .thumb_set TIM1_TRG_COM_IRQHandler,Default_Handler 426 | 427 | .weak TIM1_CC_IRQHandler 428 | .thumb_set TIM1_CC_IRQHandler,Default_Handler 429 | 430 | .weak TIM2_IRQHandler 431 | .thumb_set TIM2_IRQHandler,Default_Handler 432 | 433 | .weak TIM3_IRQHandler 434 | .thumb_set TIM3_IRQHandler,Default_Handler 435 | 436 | .weak TIM4_IRQHandler 437 | .thumb_set TIM4_IRQHandler,Default_Handler 438 | 439 | .weak I2C1_EV_IRQHandler 440 | .thumb_set I2C1_EV_IRQHandler,Default_Handler 441 | 442 | .weak I2C1_ER_IRQHandler 443 | .thumb_set I2C1_ER_IRQHandler,Default_Handler 444 | 445 | .weak I2C2_EV_IRQHandler 446 | .thumb_set I2C2_EV_IRQHandler,Default_Handler 447 | 448 | .weak I2C2_ER_IRQHandler 449 | .thumb_set I2C2_ER_IRQHandler,Default_Handler 450 | 451 | .weak SPI1_IRQHandler 452 | .thumb_set SPI1_IRQHandler,Default_Handler 453 | 454 | .weak SPI2_IRQHandler 455 | .thumb_set SPI2_IRQHandler,Default_Handler 456 | 457 | .weak USART1_IRQHandler 458 | .thumb_set USART1_IRQHandler,Default_Handler 459 | 460 | .weak USART2_IRQHandler 461 | .thumb_set USART2_IRQHandler,Default_Handler 462 | 463 | .weak USART3_IRQHandler 464 | .thumb_set USART3_IRQHandler,Default_Handler 465 | 466 | .weak EXTI15_10_IRQHandler 467 | .thumb_set EXTI15_10_IRQHandler,Default_Handler 468 | 469 | .weak RTC_Alarm_IRQHandler 470 | .thumb_set RTC_Alarm_IRQHandler,Default_Handler 471 | 472 | .weak TIM8_BRK_TIM12_IRQHandler 473 | .thumb_set TIM8_BRK_TIM12_IRQHandler,Default_Handler 474 | 475 | .weak TIM8_UP_TIM13_IRQHandler 476 | .thumb_set TIM8_UP_TIM13_IRQHandler,Default_Handler 477 | 478 | .weak TIM8_TRG_COM_TIM14_IRQHandler 479 | .thumb_set TIM8_TRG_COM_TIM14_IRQHandler,Default_Handler 480 | 481 | .weak TIM8_CC_IRQHandler 482 | .thumb_set TIM8_CC_IRQHandler,Default_Handler 483 | 484 | .weak DMA1_Stream7_IRQHandler 485 | .thumb_set DMA1_Stream7_IRQHandler,Default_Handler 486 | 487 | .weak FMC_IRQHandler 488 | .thumb_set FMC_IRQHandler,Default_Handler 489 | 490 | .weak SDMMC1_IRQHandler 491 | .thumb_set SDMMC1_IRQHandler,Default_Handler 492 | 493 | .weak TIM5_IRQHandler 494 | .thumb_set TIM5_IRQHandler,Default_Handler 495 | 496 | .weak SPI3_IRQHandler 497 | .thumb_set SPI3_IRQHandler,Default_Handler 498 | 499 | .weak UART4_IRQHandler 500 | .thumb_set UART4_IRQHandler,Default_Handler 501 | 502 | .weak UART5_IRQHandler 503 | .thumb_set UART5_IRQHandler,Default_Handler 504 | 505 | .weak TIM6_DAC_IRQHandler 506 | .thumb_set TIM6_DAC_IRQHandler,Default_Handler 507 | 508 | .weak TIM7_IRQHandler 509 | .thumb_set TIM7_IRQHandler,Default_Handler 510 | 511 | .weak DMA2_Stream0_IRQHandler 512 | .thumb_set DMA2_Stream0_IRQHandler,Default_Handler 513 | 514 | .weak DMA2_Stream1_IRQHandler 515 | .thumb_set DMA2_Stream1_IRQHandler,Default_Handler 516 | 517 | .weak DMA2_Stream2_IRQHandler 518 | .thumb_set DMA2_Stream2_IRQHandler,Default_Handler 519 | 520 | .weak DMA2_Stream3_IRQHandler 521 | .thumb_set DMA2_Stream3_IRQHandler,Default_Handler 522 | 523 | .weak DMA2_Stream4_IRQHandler 524 | .thumb_set DMA2_Stream4_IRQHandler,Default_Handler 525 | 526 | .weak ETH_IRQHandler 527 | .thumb_set ETH_IRQHandler,Default_Handler 528 | 529 | .weak ETH_WKUP_IRQHandler 530 | .thumb_set ETH_WKUP_IRQHandler,Default_Handler 531 | 532 | .weak FDCAN_CAL_IRQHandler 533 | .thumb_set FDCAN_CAL_IRQHandler,Default_Handler 534 | 535 | .weak DMA2_Stream5_IRQHandler 536 | .thumb_set DMA2_Stream5_IRQHandler,Default_Handler 537 | 538 | .weak DMA2_Stream6_IRQHandler 539 | .thumb_set DMA2_Stream6_IRQHandler,Default_Handler 540 | 541 | .weak DMA2_Stream7_IRQHandler 542 | .thumb_set DMA2_Stream7_IRQHandler,Default_Handler 543 | 544 | .weak USART6_IRQHandler 545 | .thumb_set USART6_IRQHandler,Default_Handler 546 | 547 | .weak I2C3_EV_IRQHandler 548 | .thumb_set I2C3_EV_IRQHandler,Default_Handler 549 | 550 | .weak I2C3_ER_IRQHandler 551 | .thumb_set I2C3_ER_IRQHandler,Default_Handler 552 | 553 | .weak OTG_HS_EP1_OUT_IRQHandler 554 | .thumb_set OTG_HS_EP1_OUT_IRQHandler,Default_Handler 555 | 556 | .weak OTG_HS_EP1_IN_IRQHandler 557 | .thumb_set OTG_HS_EP1_IN_IRQHandler,Default_Handler 558 | 559 | .weak OTG_HS_WKUP_IRQHandler 560 | .thumb_set OTG_HS_WKUP_IRQHandler,Default_Handler 561 | 562 | .weak OTG_HS_IRQHandler 563 | .thumb_set OTG_HS_IRQHandler,Default_Handler 564 | 565 | .weak DCMI_PSSI_IRQHandler 566 | .thumb_set DCMI_PSSI_IRQHandler,Default_Handler 567 | 568 | .weak CRYP_IRQHandler 569 | .thumb_set CRYP_IRQHandler,Default_Handler 570 | 571 | .weak HASH_RNG_IRQHandler 572 | .thumb_set HASH_RNG_IRQHandler,Default_Handler 573 | 574 | .weak FPU_IRQHandler 575 | .thumb_set FPU_IRQHandler,Default_Handler 576 | 577 | .weak UART7_IRQHandler 578 | .thumb_set UART7_IRQHandler,Default_Handler 579 | 580 | .weak UART8_IRQHandler 581 | .thumb_set UART8_IRQHandler,Default_Handler 582 | 583 | .weak SPI4_IRQHandler 584 | .thumb_set SPI4_IRQHandler,Default_Handler 585 | 586 | .weak SPI5_IRQHandler 587 | .thumb_set SPI5_IRQHandler,Default_Handler 588 | 589 | .weak SPI6_IRQHandler 590 | .thumb_set SPI6_IRQHandler,Default_Handler 591 | 592 | .weak SAI1_IRQHandler 593 | .thumb_set SAI1_IRQHandler,Default_Handler 594 | 595 | .weak LTDC_IRQHandler 596 | .thumb_set LTDC_IRQHandler,Default_Handler 597 | 598 | .weak LTDC_ER_IRQHandler 599 | .thumb_set LTDC_ER_IRQHandler,Default_Handler 600 | 601 | .weak DMA2D_IRQHandler 602 | .thumb_set DMA2D_IRQHandler,Default_Handler 603 | 604 | .weak OCTOSPI1_IRQHandler 605 | .thumb_set OCTOSPI1_IRQHandler,Default_Handler 606 | 607 | .weak LPTIM1_IRQHandler 608 | .thumb_set LPTIM1_IRQHandler,Default_Handler 609 | 610 | .weak CEC_IRQHandler 611 | .thumb_set CEC_IRQHandler,Default_Handler 612 | 613 | .weak I2C4_EV_IRQHandler 614 | .thumb_set I2C4_EV_IRQHandler,Default_Handler 615 | 616 | .weak I2C4_ER_IRQHandler 617 | .thumb_set I2C4_ER_IRQHandler,Default_Handler 618 | 619 | .weak SPDIF_RX_IRQHandler 620 | .thumb_set SPDIF_RX_IRQHandler,Default_Handler 621 | 622 | .weak DMAMUX1_OVR_IRQHandler 623 | .thumb_set DMAMUX1_OVR_IRQHandler,Default_Handler 624 | 625 | .weak DFSDM1_FLT0_IRQHandler 626 | .thumb_set DFSDM1_FLT0_IRQHandler,Default_Handler 627 | 628 | .weak DFSDM1_FLT1_IRQHandler 629 | .thumb_set DFSDM1_FLT1_IRQHandler,Default_Handler 630 | 631 | .weak DFSDM1_FLT2_IRQHandler 632 | .thumb_set DFSDM1_FLT2_IRQHandler,Default_Handler 633 | 634 | .weak DFSDM1_FLT3_IRQHandler 635 | .thumb_set DFSDM1_FLT3_IRQHandler,Default_Handler 636 | 637 | .weak SWPMI1_IRQHandler 638 | .thumb_set SWPMI1_IRQHandler,Default_Handler 639 | 640 | .weak TIM15_IRQHandler 641 | .thumb_set TIM15_IRQHandler,Default_Handler 642 | 643 | .weak TIM16_IRQHandler 644 | .thumb_set TIM16_IRQHandler,Default_Handler 645 | 646 | .weak TIM17_IRQHandler 647 | .thumb_set TIM17_IRQHandler,Default_Handler 648 | 649 | .weak MDIOS_WKUP_IRQHandler 650 | .thumb_set MDIOS_WKUP_IRQHandler,Default_Handler 651 | 652 | .weak MDIOS_IRQHandler 653 | .thumb_set MDIOS_IRQHandler,Default_Handler 654 | 655 | .weak MDMA_IRQHandler 656 | .thumb_set MDMA_IRQHandler,Default_Handler 657 | 658 | .weak SDMMC2_IRQHandler 659 | .thumb_set SDMMC2_IRQHandler,Default_Handler 660 | 661 | .weak HSEM1_IRQHandler 662 | .thumb_set HSEM1_IRQHandler,Default_Handler 663 | 664 | .weak ADC3_IRQHandler 665 | .thumb_set ADC3_IRQHandler,Default_Handler 666 | 667 | .weak DMAMUX2_OVR_IRQHandler 668 | .thumb_set DMAMUX2_OVR_IRQHandler,Default_Handler 669 | 670 | .weak BDMA_Channel0_IRQHandler 671 | .thumb_set BDMA_Channel0_IRQHandler,Default_Handler 672 | 673 | .weak BDMA_Channel1_IRQHandler 674 | .thumb_set BDMA_Channel1_IRQHandler,Default_Handler 675 | 676 | .weak BDMA_Channel2_IRQHandler 677 | .thumb_set BDMA_Channel2_IRQHandler,Default_Handler 678 | 679 | .weak BDMA_Channel3_IRQHandler 680 | .thumb_set BDMA_Channel3_IRQHandler,Default_Handler 681 | 682 | .weak BDMA_Channel4_IRQHandler 683 | .thumb_set BDMA_Channel4_IRQHandler,Default_Handler 684 | 685 | .weak BDMA_Channel5_IRQHandler 686 | .thumb_set BDMA_Channel5_IRQHandler,Default_Handler 687 | 688 | .weak BDMA_Channel6_IRQHandler 689 | .thumb_set BDMA_Channel6_IRQHandler,Default_Handler 690 | 691 | .weak BDMA_Channel7_IRQHandler 692 | .thumb_set BDMA_Channel7_IRQHandler,Default_Handler 693 | 694 | .weak COMP1_IRQHandler 695 | .thumb_set COMP1_IRQHandler,Default_Handler 696 | 697 | .weak LPTIM2_IRQHandler 698 | .thumb_set LPTIM2_IRQHandler,Default_Handler 699 | 700 | .weak LPTIM3_IRQHandler 701 | .thumb_set LPTIM3_IRQHandler,Default_Handler 702 | 703 | .weak LPTIM4_IRQHandler 704 | .thumb_set LPTIM4_IRQHandler,Default_Handler 705 | 706 | .weak LPTIM5_IRQHandler 707 | .thumb_set LPTIM5_IRQHandler,Default_Handler 708 | 709 | .weak LPUART1_IRQHandler 710 | .thumb_set LPUART1_IRQHandler,Default_Handler 711 | 712 | .weak CRS_IRQHandler 713 | .thumb_set CRS_IRQHandler,Default_Handler 714 | 715 | .weak ECC_IRQHandler 716 | .thumb_set ECC_IRQHandler,Default_Handler 717 | 718 | .weak SAI4_IRQHandler 719 | .thumb_set SAI4_IRQHandler,Default_Handler 720 | 721 | .weak DTS_IRQHandler 722 | .thumb_set DTS_IRQHandler,Default_Handler 723 | 724 | .weak WAKEUP_PIN_IRQHandler 725 | .thumb_set WAKEUP_PIN_IRQHandler,Default_Handler 726 | 727 | .weak OCTOSPI2_IRQHandler 728 | .thumb_set OCTOSPI2_IRQHandler,Default_Handler 729 | 730 | .weak OTFDEC1_IRQHandler 731 | .thumb_set OTFDEC1_IRQHandler,Default_Handler 732 | 733 | .weak OTFDEC2_IRQHandler 734 | .thumb_set OTFDEC2_IRQHandler,Default_Handler 735 | 736 | .weak FMAC_IRQHandler 737 | .thumb_set FMAC_IRQHandler,Default_Handler 738 | 739 | .weak CORDIC_IRQHandler 740 | .thumb_set CORDIC_IRQHandler,Default_Handler 741 | 742 | .weak UART9_IRQHandler 743 | .thumb_set UART9_IRQHandler,Default_Handler 744 | 745 | .weak USART10_IRQHandler 746 | .thumb_set USART10_IRQHandler,Default_Handler 747 | 748 | .weak I2C5_EV_IRQHandler 749 | .thumb_set I2C5_EV_IRQHandler,Default_Handler 750 | 751 | .weak I2C5_ER_IRQHandler 752 | .thumb_set I2C5_ER_IRQHandler,Default_Handler 753 | 754 | .weak FDCAN3_IT0_IRQHandler 755 | .thumb_set FDCAN3_IT0_IRQHandler,Default_Handler 756 | 757 | .weak FDCAN3_IT1_IRQHandler 758 | .thumb_set FDCAN3_IT1_IRQHandler,Default_Handler 759 | 760 | .weak TIM23_IRQHandler 761 | .thumb_set TIM23_IRQHandler,Default_Handler 762 | 763 | .weak TIM24_IRQHandler 764 | .thumb_set TIM24_IRQHandler,Default_Handler 765 | 766 | 767 | -------------------------------------------------------------------------------- /usb_payload/source/stm32h7xx_hal_conf.h: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * @file stm32h7xx_hal_conf_template.h 4 | * @author MCD Application Team 5 | * @brief HAL configuration template file. 6 | * This file should be copied to the application folder and renamed 7 | * to stm32h7xx_hal_conf.h. 8 | ****************************************************************************** 9 | * @attention 10 | * 11 | * Copyright (c) 2017 STMicroelectronics. 12 | * All rights reserved. 13 | * 14 | * This software is licensed under terms that can be found in the LICENSE file 15 | * in the root directory of this software component. 16 | * If no LICENSE file comes with this software, it is provided AS-IS. 17 | * 18 | ****************************************************************************** 19 | */ 20 | 21 | /* Define to prevent recursive inclusion -------------------------------------*/ 22 | #ifndef STM32H7xx_HAL_CONF_H 23 | #define STM32H7xx_HAL_CONF_H 24 | 25 | #ifdef __cplusplus 26 | extern "C" { 27 | #endif 28 | 29 | /* Exported types ------------------------------------------------------------*/ 30 | /* Exported constants --------------------------------------------------------*/ 31 | 32 | /* ########################## Module Selection ############################## */ 33 | /** 34 | * @brief This is the list of modules to be used in the HAL driver 35 | */ 36 | #define HAL_MODULE_ENABLED 37 | #define HAL_ADC_MODULE_ENABLED 38 | // #define HAL_CEC_MODULE_ENABLED 39 | // #define HAL_COMP_MODULE_ENABLED 40 | // #define HAL_CORDIC_MODULE_ENABLED 41 | #define HAL_CORTEX_MODULE_ENABLED 42 | // #define HAL_CRC_MODULE_ENABLED 43 | // #define HAL_CRYP_MODULE_ENABLED 44 | // #define HAL_DAC_MODULE_ENABLED 45 | // #define HAL_DCMI_MODULE_ENABLED 46 | // #define HAL_DFSDM_MODULE_ENABLED 47 | #define HAL_DMA_MODULE_ENABLED 48 | // #define HAL_DMA2D_MODULE_ENABLED 49 | // #define HAL_DTS_MODULE_ENABLED 50 | // #define HAL_DSI_MODULE_ENABLED 51 | // #define HAL_ETH_MODULE_ENABLED 52 | // #define HAL_ETH_LEGACY_MODULE_ENABLED 53 | // #define HAL_EXTI_MODULE_ENABLED 54 | // #define HAL_FDCAN_MODULE_ENABLED 55 | #define HAL_FLASH_MODULE_ENABLED 56 | // #define HAL_GFXMMU_MODULE_ENABLED 57 | // #define HAL_FMAC_MODULE_ENABLED 58 | #define HAL_GPIO_MODULE_ENABLED 59 | // #define HAL_HASH_MODULE_ENABLED 60 | // #define HAL_HCD_MODULE_ENABLED 61 | // #define HAL_HRTIM_MODULE_ENABLED 62 | // #define HAL_HSEM_MODULE_ENABLED 63 | // #define HAL_I2C_MODULE_ENABLED 64 | // #define HAL_I2S_MODULE_ENABLED 65 | // #define HAL_IRDA_MODULE_ENABLED 66 | // #define HAL_IWDG_MODULE_ENABLED 67 | // #define HAL_JPEG_MODULE_ENABLED 68 | // #define HAL_LPTIM_MODULE_ENABLED 69 | // #define HAL_LTDC_MODULE_ENABLED 70 | // #define HAL_MDIOS_MODULE_ENABLED 71 | #define HAL_MDMA_MODULE_ENABLED 72 | // #define HAL_MMC_MODULE_ENABLED 73 | // #define HAL_NAND_MODULE_ENABLED 74 | // #define HAL_NOR_MODULE_ENABLED 75 | // #define HAL_OPAMP_MODULE_ENABLED 76 | // #define HAL_OSPI_MODULE_ENABLED 77 | // #define HAL_OTFDEC_MODULE_ENABLED 78 | // #define HAL_PCD_MODULE_ENABLED 79 | #define HAL_PWR_MODULE_ENABLED 80 | // #define HAL_PSSI_MODULE_ENABLED 81 | // #define HAL_QSPI_MODULE_ENABLED 82 | // #define HAL_RAMECC_MODULE_ENABLED 83 | #define HAL_RCC_MODULE_ENABLED 84 | // #define HAL_RNG_MODULE_ENABLED 85 | // #define HAL_RTC_MODULE_ENABLED 86 | // #define HAL_SAI_MODULE_ENABLED 87 | // #define HAL_SD_MODULE_ENABLED 88 | // #define HAL_SDRAM_MODULE_ENABLED 89 | // #define HAL_SMARTCARD_MODULE_ENABLED 90 | // #define HAL_SMBUS_MODULE_ENABLED 91 | // #define HAL_SPDIFRX_MODULE_ENABLED 92 | // #define HAL_SPI_MODULE_ENABLED 93 | #define HAL_SRAM_MODULE_ENABLED 94 | // #define HAL_SWPMI_MODULE_ENABLED 95 | #define HAL_TIM_MODULE_ENABLED 96 | // #define HAL_UART_MODULE_ENABLED 97 | // #define HAL_USART_MODULE_ENABLED 98 | // #define HAL_WWDG_MODULE_ENABLED 99 | 100 | /* ########################## Oscillator Values adaptation ####################*/ 101 | /** 102 | * @brief Adjust the value of External High Speed oscillator (HSE) used in your application. 103 | * This value is used by the RCC HAL module to compute the system frequency 104 | * (when HSE is used as system clock source, directly or through the PLL). 105 | */ 106 | #if !defined (HSE_VALUE) 107 | #define HSE_VALUE (25000000UL) /*!< Value of the External oscillator in Hz */ 108 | #endif /* HSE_VALUE */ 109 | 110 | #if !defined (HSE_STARTUP_TIMEOUT) 111 | #define HSE_STARTUP_TIMEOUT (100UL) /*!< Time out for HSE start up, in ms */ 112 | #endif /* HSE_STARTUP_TIMEOUT */ 113 | 114 | /** 115 | * @brief Internal oscillator (CSI) default value. 116 | * This value is the default CSI value after Reset. 117 | */ 118 | #if !defined (CSI_VALUE) 119 | #define CSI_VALUE (4000000UL) /*!< Value of the Internal oscillator in Hz*/ 120 | #endif /* CSI_VALUE */ 121 | 122 | /** 123 | * @brief Internal High Speed oscillator (HSI) value. 124 | * This value is used by the RCC HAL module to compute the system frequency 125 | * (when HSI is used as system clock source, directly or through the PLL). 126 | */ 127 | #if !defined (HSI_VALUE) 128 | #define HSI_VALUE (64000000UL) /*!< Value of the Internal oscillator in Hz*/ 129 | #endif /* HSI_VALUE */ 130 | 131 | /** 132 | * @brief External Low Speed oscillator (LSE) value. 133 | * This value is used by the UART, RTC HAL module to compute the system frequency 134 | */ 135 | #if !defined (LSE_VALUE) 136 | #define LSE_VALUE (32768UL) /*!< Value of the External oscillator in Hz*/ 137 | #endif /* LSE_VALUE */ 138 | 139 | 140 | #if !defined (LSE_STARTUP_TIMEOUT) 141 | #define LSE_STARTUP_TIMEOUT (5000UL) /*!< Time out for LSE start up, in ms */ 142 | #endif /* LSE_STARTUP_TIMEOUT */ 143 | 144 | #if !defined (LSI_VALUE) 145 | #define LSI_VALUE (32000UL) /*!< LSI Typical Value in Hz*/ 146 | #endif /* LSI_VALUE */ /*!< Value of the Internal Low Speed oscillator in Hz 147 | The real value may vary depending on the variations 148 | in voltage and temperature.*/ 149 | 150 | /** 151 | * @brief External clock source for I2S peripheral 152 | * This value is used by the I2S HAL module to compute the I2S clock source 153 | * frequency, this source is inserted directly through I2S_CKIN pad. 154 | */ 155 | #if !defined (EXTERNAL_CLOCK_VALUE) 156 | #define EXTERNAL_CLOCK_VALUE 12288000UL /*!< Value of the External clock in Hz*/ 157 | #endif /* EXTERNAL_CLOCK_VALUE */ 158 | 159 | /* Tip: To avoid modifying this file each time you need to use different HSE, 160 | === you can define the HSE value in your toolchain compiler preprocessor. */ 161 | 162 | /* ########################### System Configuration ######################### */ 163 | /** 164 | * @brief This is the HAL system configuration section 165 | */ 166 | #define VDD_VALUE (3300UL) /*!< Value of VDD in mv */ 167 | #define TICK_INT_PRIORITY (0x00UL) /*!< tick interrupt priority */ //! alarmo edit: 0x0F -> 0x00 168 | #define USE_RTOS 0 169 | #define USE_SD_TRANSCEIVER 0U /*!< use uSD Transceiver */ 170 | #define USE_SPI_CRC 1U /*!< use CRC in SPI */ 171 | #define USE_FLASH_ECC 0U /*!< use ECC error management in FLASH */ 172 | 173 | #define USE_HAL_ADC_REGISTER_CALLBACKS 0U /* ADC register callback disabled */ 174 | #define USE_HAL_CEC_REGISTER_CALLBACKS 0U /* CEC register callback disabled */ 175 | #define USE_HAL_COMP_REGISTER_CALLBACKS 0U /* COMP register callback disabled */ 176 | #define USE_HAL_CORDIC_REGISTER_CALLBACKS 0U /* CORDIC register callback disabled */ 177 | #define USE_HAL_CRYP_REGISTER_CALLBACKS 0U /* CRYP register callback disabled */ 178 | #define USE_HAL_DAC_REGISTER_CALLBACKS 0U /* DAC register callback disabled */ 179 | #define USE_HAL_DCMI_REGISTER_CALLBACKS 0U /* DCMI register callback disabled */ 180 | #define USE_HAL_DFSDM_REGISTER_CALLBACKS 0U /* DFSDM register callback disabled */ 181 | #define USE_HAL_DMA2D_REGISTER_CALLBACKS 0U /* DMA2D register callback disabled */ 182 | #define USE_HAL_DSI_REGISTER_CALLBACKS 0U /* DSI register callback disabled */ 183 | #define USE_HAL_DTS_REGISTER_CALLBACKS 0U /* DTS register callback disabled */ 184 | #define USE_HAL_ETH_REGISTER_CALLBACKS 0U /* ETH register callback disabled */ 185 | #define USE_HAL_FDCAN_REGISTER_CALLBACKS 0U /* FDCAN register callback disabled */ 186 | #define USE_HAL_FMAC_REGISTER_CALLBACKS 0U /* FMAC register callback disabled */ 187 | #define USE_HAL_NAND_REGISTER_CALLBACKS 0U /* NAND register callback disabled */ 188 | #define USE_HAL_NOR_REGISTER_CALLBACKS 0U /* NOR register callback disabled */ 189 | #define USE_HAL_SDRAM_REGISTER_CALLBACKS 0U /* SDRAM register callback disabled */ 190 | #define USE_HAL_SRAM_REGISTER_CALLBACKS 0U /* SRAM register callback disabled */ 191 | #define USE_HAL_HASH_REGISTER_CALLBACKS 0U /* HASH register callback disabled */ 192 | #define USE_HAL_HCD_REGISTER_CALLBACKS 0U /* HCD register callback disabled */ 193 | #define USE_HAL_GFXMMU_REGISTER_CALLBACKS 0U /* GFXMMU register callback disabled */ 194 | #define USE_HAL_HRTIM_REGISTER_CALLBACKS 0U /* HRTIM register callback disabled */ 195 | #define USE_HAL_I2C_REGISTER_CALLBACKS 0U /* I2C register callback disabled */ 196 | #define USE_HAL_I2S_REGISTER_CALLBACKS 0U /* I2S register callback disabled */ 197 | #define USE_HAL_IRDA_REGISTER_CALLBACKS 0U /* IRDA register callback disabled */ 198 | #define USE_HAL_JPEG_REGISTER_CALLBACKS 0U /* JPEG register callback disabled */ 199 | #define USE_HAL_LPTIM_REGISTER_CALLBACKS 0U /* LPTIM register callback disabled */ 200 | #define USE_HAL_LTDC_REGISTER_CALLBACKS 0U /* LTDC register callback disabled */ 201 | #define USE_HAL_MDIOS_REGISTER_CALLBACKS 0U /* MDIO register callback disabled */ 202 | #define USE_HAL_MMC_REGISTER_CALLBACKS 0U /* MMC register callback disabled */ 203 | #define USE_HAL_OPAMP_REGISTER_CALLBACKS 0U /* MDIO register callback disabled */ 204 | #define USE_HAL_OSPI_REGISTER_CALLBACKS 0U /* OSPI register callback disabled */ 205 | #define USE_HAL_OTFDEC_REGISTER_CALLBACKS 0U /* OTFDEC register callback disabled */ 206 | #define USE_HAL_PCD_REGISTER_CALLBACKS 0U /* PCD register callback disabled */ 207 | #define USE_HAL_QSPI_REGISTER_CALLBACKS 0U /* QSPI register callback disabled */ 208 | #define USE_HAL_RNG_REGISTER_CALLBACKS 0U /* RNG register callback disabled */ 209 | #define USE_HAL_RTC_REGISTER_CALLBACKS 0U /* RTC register callback disabled */ 210 | #define USE_HAL_SAI_REGISTER_CALLBACKS 0U /* SAI register callback disabled */ 211 | #define USE_HAL_SD_REGISTER_CALLBACKS 0U /* SD register callback disabled */ 212 | #define USE_HAL_SMARTCARD_REGISTER_CALLBACKS 0U /* SMARTCARD register callback disabled */ 213 | #define USE_HAL_SPDIFRX_REGISTER_CALLBACKS 0U /* SPDIFRX register callback disabled */ 214 | #define USE_HAL_SMBUS_REGISTER_CALLBACKS 0U /* SMBUS register callback disabled */ 215 | #define USE_HAL_SPI_REGISTER_CALLBACKS 0U /* SPI register callback disabled */ 216 | #define USE_HAL_SWPMI_REGISTER_CALLBACKS 0U /* SWPMI register callback disabled */ 217 | #define USE_HAL_TIM_REGISTER_CALLBACKS 0U /* TIM register callback disabled */ 218 | #define USE_HAL_UART_REGISTER_CALLBACKS 0U /* UART register callback disabled */ 219 | #define USE_HAL_USART_REGISTER_CALLBACKS 0U /* USART register callback disabled */ 220 | #define USE_HAL_WWDG_REGISTER_CALLBACKS 0U /* WWDG register callback disabled */ 221 | 222 | /* ########################### Ethernet Configuration ######################### */ 223 | #define ETH_TX_DESC_CNT 4U /* number of Ethernet Tx DMA descriptors */ 224 | #define ETH_RX_DESC_CNT 4U /* number of Ethernet Rx DMA descriptors */ 225 | 226 | #define ETH_MAC_ADDR0 (0x02UL) 227 | #define ETH_MAC_ADDR1 (0x00UL) 228 | #define ETH_MAC_ADDR2 (0x00UL) 229 | #define ETH_MAC_ADDR3 (0x00UL) 230 | #define ETH_MAC_ADDR4 (0x00UL) 231 | #define ETH_MAC_ADDR5 (0x00UL) 232 | 233 | /* ########################## Assert Selection ############################## */ 234 | /** 235 | * @brief Uncomment the line below to expanse the "assert_param" macro in the 236 | * HAL drivers code 237 | */ 238 | /* #define USE_FULL_ASSERT 1 */ 239 | 240 | 241 | /* Includes ------------------------------------------------------------------*/ 242 | /** 243 | * @brief Include module's header file 244 | */ 245 | 246 | #ifdef HAL_RCC_MODULE_ENABLED 247 | #include "stm32h7xx_hal_rcc.h" 248 | #endif /* HAL_RCC_MODULE_ENABLED */ 249 | 250 | #ifdef HAL_GPIO_MODULE_ENABLED 251 | #include "stm32h7xx_hal_gpio.h" 252 | #endif /* HAL_GPIO_MODULE_ENABLED */ 253 | 254 | #ifdef HAL_DMA_MODULE_ENABLED 255 | #include "stm32h7xx_hal_dma.h" 256 | #endif /* HAL_DMA_MODULE_ENABLED */ 257 | 258 | #ifdef HAL_MDMA_MODULE_ENABLED 259 | #include "stm32h7xx_hal_mdma.h" 260 | #endif /* HAL_MDMA_MODULE_ENABLED */ 261 | 262 | #ifdef HAL_HASH_MODULE_ENABLED 263 | #include "stm32h7xx_hal_hash.h" 264 | #endif /* HAL_HASH_MODULE_ENABLED */ 265 | 266 | #ifdef HAL_DCMI_MODULE_ENABLED 267 | #include "stm32h7xx_hal_dcmi.h" 268 | #endif /* HAL_DCMI_MODULE_ENABLED */ 269 | 270 | #ifdef HAL_DMA2D_MODULE_ENABLED 271 | #include "stm32h7xx_hal_dma2d.h" 272 | #endif /* HAL_DMA2D_MODULE_ENABLED */ 273 | 274 | #ifdef HAL_DSI_MODULE_ENABLED 275 | #include "stm32h7xx_hal_dsi.h" 276 | #endif /* HAL_DSI_MODULE_ENABLED */ 277 | 278 | #ifdef HAL_DFSDM_MODULE_ENABLED 279 | #include "stm32h7xx_hal_dfsdm.h" 280 | #endif /* HAL_DFSDM_MODULE_ENABLED */ 281 | 282 | #ifdef HAL_DTS_MODULE_ENABLED 283 | #include "stm32h7xx_hal_dts.h" 284 | #endif /* HAL_DTS_MODULE_ENABLED */ 285 | 286 | #ifdef HAL_ETH_MODULE_ENABLED 287 | #include "stm32h7xx_hal_eth.h" 288 | #endif /* HAL_ETH_MODULE_ENABLED */ 289 | 290 | #ifdef HAL_ETH_LEGACY_MODULE_ENABLED 291 | #include "stm32h7xx_hal_eth_legacy.h" 292 | #endif /* HAL_ETH_LEGACY_MODULE_ENABLED */ 293 | 294 | #ifdef HAL_EXTI_MODULE_ENABLED 295 | #include "stm32h7xx_hal_exti.h" 296 | #endif /* HAL_EXTI_MODULE_ENABLED */ 297 | 298 | #ifdef HAL_CORTEX_MODULE_ENABLED 299 | #include "stm32h7xx_hal_cortex.h" 300 | #endif /* HAL_CORTEX_MODULE_ENABLED */ 301 | 302 | #ifdef HAL_ADC_MODULE_ENABLED 303 | #include "stm32h7xx_hal_adc.h" 304 | #endif /* HAL_ADC_MODULE_ENABLED */ 305 | 306 | #ifdef HAL_FDCAN_MODULE_ENABLED 307 | #include "stm32h7xx_hal_fdcan.h" 308 | #endif /* HAL_FDCAN_MODULE_ENABLED */ 309 | 310 | #ifdef HAL_CEC_MODULE_ENABLED 311 | #include "stm32h7xx_hal_cec.h" 312 | #endif /* HAL_CEC_MODULE_ENABLED */ 313 | 314 | #ifdef HAL_COMP_MODULE_ENABLED 315 | #include "stm32h7xx_hal_comp.h" 316 | #endif /* HAL_COMP_MODULE_ENABLED */ 317 | 318 | #ifdef HAL_CORDIC_MODULE_ENABLED 319 | #include "stm32h7xx_hal_cordic.h" 320 | #endif /* HAL_CORDIC_MODULE_ENABLED */ 321 | 322 | #ifdef HAL_CRC_MODULE_ENABLED 323 | #include "stm32h7xx_hal_crc.h" 324 | #endif /* HAL_CRC_MODULE_ENABLED */ 325 | 326 | #ifdef HAL_CRYP_MODULE_ENABLED 327 | #include "stm32h7xx_hal_cryp.h" 328 | #endif /* HAL_CRYP_MODULE_ENABLED */ 329 | 330 | #ifdef HAL_DAC_MODULE_ENABLED 331 | #include "stm32h7xx_hal_dac.h" 332 | #endif /* HAL_DAC_MODULE_ENABLED */ 333 | 334 | #ifdef HAL_FLASH_MODULE_ENABLED 335 | #include "stm32h7xx_hal_flash.h" 336 | #endif /* HAL_FLASH_MODULE_ENABLED */ 337 | 338 | #ifdef HAL_GFXMMU_MODULE_ENABLED 339 | #include "stm32h7xx_hal_gfxmmu.h" 340 | #endif /* HAL_GFXMMU_MODULE_ENABLED */ 341 | 342 | #ifdef HAL_FMAC_MODULE_ENABLED 343 | #include "stm32h7xx_hal_fmac.h" 344 | #endif /* HAL_FMAC_MODULE_ENABLED */ 345 | 346 | #ifdef HAL_HRTIM_MODULE_ENABLED 347 | #include "stm32h7xx_hal_hrtim.h" 348 | #endif /* HAL_HRTIM_MODULE_ENABLED */ 349 | 350 | #ifdef HAL_HSEM_MODULE_ENABLED 351 | #include "stm32h7xx_hal_hsem.h" 352 | #endif /* HAL_HSEM_MODULE_ENABLED */ 353 | 354 | #ifdef HAL_SRAM_MODULE_ENABLED 355 | #include "stm32h7xx_hal_sram.h" 356 | #endif /* HAL_SRAM_MODULE_ENABLED */ 357 | 358 | #ifdef HAL_NOR_MODULE_ENABLED 359 | #include "stm32h7xx_hal_nor.h" 360 | #endif /* HAL_NOR_MODULE_ENABLED */ 361 | 362 | #ifdef HAL_NAND_MODULE_ENABLED 363 | #include "stm32h7xx_hal_nand.h" 364 | #endif /* HAL_NAND_MODULE_ENABLED */ 365 | 366 | #ifdef HAL_I2C_MODULE_ENABLED 367 | #include "stm32h7xx_hal_i2c.h" 368 | #endif /* HAL_I2C_MODULE_ENABLED */ 369 | 370 | #ifdef HAL_I2S_MODULE_ENABLED 371 | #include "stm32h7xx_hal_i2s.h" 372 | #endif /* HAL_I2S_MODULE_ENABLED */ 373 | 374 | #ifdef HAL_IWDG_MODULE_ENABLED 375 | #include "stm32h7xx_hal_iwdg.h" 376 | #endif /* HAL_IWDG_MODULE_ENABLED */ 377 | 378 | #ifdef HAL_JPEG_MODULE_ENABLED 379 | #include "stm32h7xx_hal_jpeg.h" 380 | #endif /* HAL_JPEG_MODULE_ENABLED */ 381 | 382 | #ifdef HAL_MDIOS_MODULE_ENABLED 383 | #include "stm32h7xx_hal_mdios.h" 384 | #endif /* HAL_MDIOS_MODULE_ENABLED */ 385 | 386 | #ifdef HAL_MMC_MODULE_ENABLED 387 | #include "stm32h7xx_hal_mmc.h" 388 | #endif /* HAL_MMC_MODULE_ENABLED */ 389 | 390 | #ifdef HAL_LPTIM_MODULE_ENABLED 391 | #include "stm32h7xx_hal_lptim.h" 392 | #endif /* HAL_LPTIM_MODULE_ENABLED */ 393 | 394 | #ifdef HAL_LTDC_MODULE_ENABLED 395 | #include "stm32h7xx_hal_ltdc.h" 396 | #endif /* HAL_LTDC_MODULE_ENABLED */ 397 | 398 | #ifdef HAL_OPAMP_MODULE_ENABLED 399 | #include "stm32h7xx_hal_opamp.h" 400 | #endif /* HAL_OPAMP_MODULE_ENABLED */ 401 | 402 | #ifdef HAL_OSPI_MODULE_ENABLED 403 | #include "stm32h7xx_hal_ospi.h" 404 | #endif /* HAL_OSPI_MODULE_ENABLED */ 405 | 406 | #ifdef HAL_OTFDEC_MODULE_ENABLED 407 | #include "stm32h7xx_hal_otfdec.h" 408 | #endif /* HAL_OTFDEC_MODULE_ENABLED */ 409 | 410 | #ifdef HAL_PSSI_MODULE_ENABLED 411 | #include "stm32h7xx_hal_pssi.h" 412 | #endif /* HAL_PSSI_MODULE_ENABLED */ 413 | 414 | #ifdef HAL_PWR_MODULE_ENABLED 415 | #include "stm32h7xx_hal_pwr.h" 416 | #endif /* HAL_PWR_MODULE_ENABLED */ 417 | 418 | #ifdef HAL_QSPI_MODULE_ENABLED 419 | #include "stm32h7xx_hal_qspi.h" 420 | #endif /* HAL_QSPI_MODULE_ENABLED */ 421 | 422 | #ifdef HAL_RAMECC_MODULE_ENABLED 423 | #include "stm32h7xx_hal_ramecc.h" 424 | #endif /* HAL_RAMECC_MODULE_ENABLED */ 425 | 426 | #ifdef HAL_RNG_MODULE_ENABLED 427 | #include "stm32h7xx_hal_rng.h" 428 | #endif /* HAL_RNG_MODULE_ENABLED */ 429 | 430 | #ifdef HAL_RTC_MODULE_ENABLED 431 | #include "stm32h7xx_hal_rtc.h" 432 | #endif /* HAL_RTC_MODULE_ENABLED */ 433 | 434 | #ifdef HAL_SAI_MODULE_ENABLED 435 | #include "stm32h7xx_hal_sai.h" 436 | #endif /* HAL_SAI_MODULE_ENABLED */ 437 | 438 | #ifdef HAL_SD_MODULE_ENABLED 439 | #include "stm32h7xx_hal_sd.h" 440 | #endif /* HAL_SD_MODULE_ENABLED */ 441 | 442 | #ifdef HAL_SDRAM_MODULE_ENABLED 443 | #include "stm32h7xx_hal_sdram.h" 444 | #endif /* HAL_SDRAM_MODULE_ENABLED */ 445 | 446 | #ifdef HAL_SPI_MODULE_ENABLED 447 | #include "stm32h7xx_hal_spi.h" 448 | #endif /* HAL_SPI_MODULE_ENABLED */ 449 | 450 | #ifdef HAL_SPDIFRX_MODULE_ENABLED 451 | #include "stm32h7xx_hal_spdifrx.h" 452 | #endif /* HAL_SPDIFRX_MODULE_ENABLED */ 453 | 454 | #ifdef HAL_SWPMI_MODULE_ENABLED 455 | #include "stm32h7xx_hal_swpmi.h" 456 | #endif /* HAL_SWPMI_MODULE_ENABLED */ 457 | 458 | #ifdef HAL_TIM_MODULE_ENABLED 459 | #include "stm32h7xx_hal_tim.h" 460 | #endif /* HAL_TIM_MODULE_ENABLED */ 461 | 462 | #ifdef HAL_UART_MODULE_ENABLED 463 | #include "stm32h7xx_hal_uart.h" 464 | #endif /* HAL_UART_MODULE_ENABLED */ 465 | 466 | #ifdef HAL_USART_MODULE_ENABLED 467 | #include "stm32h7xx_hal_usart.h" 468 | #endif /* HAL_USART_MODULE_ENABLED */ 469 | 470 | #ifdef HAL_IRDA_MODULE_ENABLED 471 | #include "stm32h7xx_hal_irda.h" 472 | #endif /* HAL_IRDA_MODULE_ENABLED */ 473 | 474 | #ifdef HAL_SMARTCARD_MODULE_ENABLED 475 | #include "stm32h7xx_hal_smartcard.h" 476 | #endif /* HAL_SMARTCARD_MODULE_ENABLED */ 477 | 478 | #ifdef HAL_SMBUS_MODULE_ENABLED 479 | #include "stm32h7xx_hal_smbus.h" 480 | #endif /* HAL_SMBUS_MODULE_ENABLED */ 481 | 482 | #ifdef HAL_WWDG_MODULE_ENABLED 483 | #include "stm32h7xx_hal_wwdg.h" 484 | #endif /* HAL_WWDG_MODULE_ENABLED */ 485 | 486 | #ifdef HAL_PCD_MODULE_ENABLED 487 | #include "stm32h7xx_hal_pcd.h" 488 | #endif /* HAL_PCD_MODULE_ENABLED */ 489 | 490 | #ifdef HAL_HCD_MODULE_ENABLED 491 | #include "stm32h7xx_hal_hcd.h" 492 | #endif /* HAL_HCD_MODULE_ENABLED */ 493 | 494 | /* Exported macro ------------------------------------------------------------*/ 495 | #ifdef USE_FULL_ASSERT 496 | /** 497 | * @brief The assert_param macro is used for function's parameters check. 498 | * @param expr: If expr is false, it calls assert_failed function 499 | * which reports the name of the source file and the source 500 | * line number of the call that failed. 501 | * If expr is true, it returns no value. 502 | * @retval None 503 | */ 504 | #define assert_param(expr) ((expr) ? (void)0U : assert_failed((uint8_t *)__FILE__, __LINE__)) 505 | /* Exported functions ------------------------------------------------------- */ 506 | void assert_failed(uint8_t *file, uint32_t line); 507 | #else 508 | #define assert_param(expr) ((void)0U) 509 | #endif /* USE_FULL_ASSERT */ 510 | 511 | #ifdef __cplusplus 512 | } 513 | #endif 514 | 515 | #endif /* STM32H7xx_HAL_CONF_H */ 516 | 517 | 518 | 519 | -------------------------------------------------------------------------------- /usb_payload/source/stm32h7xx_hal_msp.c: -------------------------------------------------------------------------------- 1 | #include "main.h" 2 | 3 | /** 4 | * Initializes the Global MSP. 5 | */ 6 | void HAL_MspInit(void) 7 | { 8 | __HAL_RCC_SYSCFG_CLK_ENABLE(); 9 | } 10 | 11 | void HAL_SRAM_MspInit(SRAM_HandleTypeDef *hsram) 12 | { 13 | RCC_PeriphCLKInitTypeDef RCC_PeriphCLKInitStruct = {0}; 14 | GPIO_InitTypeDef gpio_init_structure = { 0 }; 15 | HAL_StatusTypeDef ret = HAL_OK; 16 | 17 | RCC_PeriphCLKInitStruct.PeriphClockSelection = RCC_PERIPHCLK_FMC; 18 | RCC_PeriphCLKInitStruct.FmcClockSelection = RCC_FMCCLKSOURCE_CLKP; 19 | ret = HAL_RCCEx_PeriphCLKConfig(&RCC_PeriphCLKInitStruct); 20 | if (ret != HAL_OK) { 21 | while (1) 22 | ; 23 | } 24 | 25 | __HAL_RCC_FMC_CLK_ENABLE(); 26 | 27 | gpio_init_structure.Speed = GPIO_SPEED_FREQ_MEDIUM; 28 | gpio_init_structure.Alternate = GPIO_AF12_FMC; 29 | gpio_init_structure.Mode = GPIO_MODE_AF_PP; 30 | gpio_init_structure.Pull = GPIO_NOPULL; 31 | gpio_init_structure.Pin = GPIO_PIN_4; 32 | HAL_GPIO_Init(GPIOA, &gpio_init_structure); 33 | 34 | gpio_init_structure.Pin = GPIO_PIN_12; 35 | gpio_init_structure.Speed = GPIO_SPEED_FREQ_MEDIUM; 36 | gpio_init_structure.Alternate = GPIO_AF12_FMC; 37 | gpio_init_structure.Mode = GPIO_MODE_AF_PP; 38 | gpio_init_structure.Pull = GPIO_NOPULL; 39 | HAL_GPIO_Init(GPIOF, &gpio_init_structure); 40 | 41 | gpio_init_structure.Pin = GPIO_PIN_15 | GPIO_PIN_12 | GPIO_PIN_10 | GPIO_PIN_9 | GPIO_PIN_8 | GPIO_PIN_7; 42 | gpio_init_structure.Speed = GPIO_SPEED_FREQ_MEDIUM; 43 | gpio_init_structure.Alternate = GPIO_AF12_FMC; 44 | gpio_init_structure.Mode = GPIO_MODE_AF_PP; 45 | gpio_init_structure.Pull = GPIO_NOPULL; 46 | HAL_GPIO_Init(GPIOE, &gpio_init_structure); 47 | 48 | gpio_init_structure.Pin = GPIO_PIN_15 | GPIO_PIN_14; 49 | gpio_init_structure.Speed = GPIO_SPEED_FREQ_MEDIUM; 50 | gpio_init_structure.Alternate = GPIO_AF12_FMC; 51 | gpio_init_structure.Mode = GPIO_MODE_AF_PP; 52 | gpio_init_structure.Pull = GPIO_NOPULL; 53 | HAL_GPIO_Init(GPIOB, &gpio_init_structure); 54 | 55 | gpio_init_structure.Pin = GPIO_PIN_15 | GPIO_PIN_14 | GPIO_PIN_10 | GPIO_PIN_9 | GPIO_PIN_8 | GPIO_PIN_5 | GPIO_PIN_4 | GPIO_PIN_1 | GPIO_PIN_0; 56 | gpio_init_structure.Speed = GPIO_SPEED_FREQ_MEDIUM; 57 | gpio_init_structure.Alternate = GPIO_AF12_FMC; 58 | gpio_init_structure.Mode = GPIO_MODE_AF_PP; 59 | gpio_init_structure.Pull = GPIO_NOPULL; 60 | HAL_GPIO_Init(GPIOD, &gpio_init_structure); 61 | 62 | gpio_init_structure.Mode = GPIO_MODE_AF_PP; 63 | gpio_init_structure.Pull = GPIO_NOPULL; 64 | gpio_init_structure.Speed = GPIO_SPEED_FREQ_MEDIUM; 65 | gpio_init_structure.Alternate = GPIO_AF9_FMC; 66 | gpio_init_structure.Pin = GPIO_PIN_7; 67 | HAL_GPIO_Init(GPIOC, &gpio_init_structure); 68 | 69 | gpio_init_structure.Pull = GPIO_NOPULL; 70 | gpio_init_structure.Speed = GPIO_SPEED_FREQ_MEDIUM; 71 | gpio_init_structure.Alternate = GPIO_AF9_FMC; 72 | gpio_init_structure.Pin = GPIO_PIN_7; 73 | gpio_init_structure.Mode = GPIO_MODE_OUTPUT_PP; 74 | HAL_GPIO_Init(GPIOC, &gpio_init_structure); 75 | 76 | HAL_GPIO_WritePin(GPIOC, GPIO_PIN_7, GPIO_PIN_SET); 77 | } 78 | 79 | void HAL_TIM_PWM_MspInit(TIM_HandleTypeDef *htim) 80 | { 81 | if (htim->Instance == TIM3) { 82 | __HAL_RCC_TIM3_CLK_ENABLE(); 83 | } 84 | } 85 | 86 | void HAL_ADC_MspInit(ADC_HandleTypeDef *hadc) 87 | { 88 | GPIO_InitTypeDef gpioInit = { 0 }; 89 | 90 | if (hadc->Instance == ADC2) { 91 | __HAL_RCC_ADC12_CLK_ENABLE(); 92 | __HAL_RCC_GPIOB_CLK_ENABLE(); 93 | 94 | gpioInit.Pull = GPIO_NOPULL; 95 | gpioInit.Mode = GPIO_MODE_ANALOG; 96 | gpioInit.Pin = GPIO_PIN_0; 97 | HAL_GPIO_Init(GPIOB, &gpioInit); 98 | 99 | dma2Handle.Instance = DMA1_Stream2; 100 | dma2Handle.Init.Priority = DMA_PRIORITY_LOW; 101 | dma2Handle.Init.FIFOMode = DMA_FIFOMODE_DISABLE; 102 | dma2Handle.Init.Request = DMA_REQUEST_ADC2; 103 | dma2Handle.Init.Direction = DMA_PERIPH_TO_MEMORY; 104 | dma2Handle.Init.PeriphInc = DMA_PINC_DISABLE; 105 | dma2Handle.Init.MemInc = DMA_MINC_ENABLE; 106 | dma2Handle.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD; 107 | dma2Handle.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD; 108 | dma2Handle.Init.Mode = DMA_CIRCULAR; 109 | if (HAL_DMA_Init(&dma2Handle) != HAL_OK) { 110 | while (1) 111 | ; 112 | } 113 | 114 | __HAL_LINKDMA(hadc, DMA_Handle, dma2Handle); 115 | } else if (hadc->Instance == ADC1) { 116 | __HAL_RCC_ADC12_CLK_ENABLE(); 117 | __HAL_RCC_GPIOC_CLK_ENABLE(); 118 | 119 | gpioInit.Pull = GPIO_NOPULL; 120 | gpioInit.Mode = GPIO_MODE_ANALOG; 121 | gpioInit.Pin = GPIO_PIN_4 | GPIO_PIN_0; 122 | HAL_GPIO_Init(GPIOC, &gpioInit); 123 | 124 | dmaHandle.Instance = DMA1_Stream1; 125 | dmaHandle.Init.Priority = DMA_PRIORITY_LOW; 126 | dmaHandle.Init.FIFOMode = DMA_FIFOMODE_DISABLE; 127 | dmaHandle.Init.Request = DMA_REQUEST_ADC1; 128 | dmaHandle.Init.Direction = DMA_PERIPH_TO_MEMORY; 129 | dmaHandle.Init.PeriphInc = DMA_PINC_DISABLE; 130 | dmaHandle.Init.MemInc = DMA_MINC_ENABLE; 131 | dmaHandle.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD; 132 | dmaHandle.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD; 133 | dmaHandle.Init.Mode = DMA_CIRCULAR; 134 | if (HAL_DMA_Init(&dmaHandle) != HAL_OK) { 135 | while (1) 136 | ; 137 | } 138 | 139 | __HAL_LINKDMA(hadc, DMA_Handle, dmaHandle); 140 | } 141 | } 142 | -------------------------------------------------------------------------------- /usb_payload/source/stm32h7xx_it.c: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * @file Templates_LL/Src/stm32h7xx_it.c 4 | * @author MCD Application Team 5 | * @brief Main Interrupt Service Routines. 6 | * This file provides template for all exceptions handler and 7 | * peripherals interrupt service routine. 8 | ****************************************************************************** 9 | * @attention 10 | * 11 | * Copyright (c) 2019 STMicroelectronics. 12 | * All rights reserved. 13 | * 14 | * This software is licensed under terms that can be found in the LICENSE file 15 | * in the root directory of this software component. 16 | * If no LICENSE file comes with this software, it is provided AS-IS. 17 | * 18 | ****************************************************************************** 19 | */ 20 | 21 | /* Includes ------------------------------------------------------------------*/ 22 | #include "stm32h7xx_it.h" 23 | #include "main.h" 24 | #include 25 | 26 | /** @addtogroup STM32H7xx_LL_Examples 27 | * @{ 28 | */ 29 | 30 | /** @addtogroup Templates_LL 31 | * @{ 32 | */ 33 | 34 | /* Private typedef -----------------------------------------------------------*/ 35 | /* Private define ------------------------------------------------------------*/ 36 | /* Private macro -------------------------------------------------------------*/ 37 | /* Private variables ---------------------------------------------------------*/ 38 | /* Private function prototypes -----------------------------------------------*/ 39 | /* Private functions ---------------------------------------------------------*/ 40 | 41 | /******************************************************************************/ 42 | /* Cortex-M7 Processor Exceptions Handlers */ 43 | /******************************************************************************/ 44 | 45 | /** 46 | * @brief This function handles NMI exception. 47 | * @param None 48 | * @retval None 49 | */ 50 | void NMI_Handler(void) 51 | { 52 | } 53 | 54 | /** 55 | * @brief This function handles Hard Fault exception. 56 | * @param None 57 | * @retval None 58 | */ 59 | void HardFault_Handler(void) 60 | { 61 | /* Go to infinite loop when Hard Fault exception occurs */ 62 | while (1) 63 | { 64 | } 65 | } 66 | 67 | /** 68 | * @brief This function handles Memory Manage exception. 69 | * @param None 70 | * @retval None 71 | */ 72 | void MemManage_Handler(void) 73 | { 74 | /* Go to infinite loop when Memory Manage exception occurs */ 75 | while (1) 76 | { 77 | } 78 | } 79 | 80 | /** 81 | * @brief This function handles Bus Fault exception. 82 | * @param None 83 | * @retval None 84 | */ 85 | void BusFault_Handler(void) 86 | { 87 | /* Go to infinite loop when Bus Fault exception occurs */ 88 | while (1) 89 | { 90 | } 91 | } 92 | 93 | /** 94 | * @brief This function handles Usage Fault exception. 95 | * @param None 96 | * @retval None 97 | */ 98 | void UsageFault_Handler(void) 99 | { 100 | /* Go to infinite loop when Usage Fault exception occurs */ 101 | while (1) 102 | { 103 | } 104 | } 105 | 106 | /** 107 | * @brief This function handles SVCall exception. 108 | * @param None 109 | * @retval None 110 | */ 111 | void SVC_Handler(void) 112 | { 113 | } 114 | 115 | /** 116 | * @brief This function handles Debug Monitor exception. 117 | * @param None 118 | * @retval None 119 | */ 120 | void DebugMon_Handler(void) 121 | { 122 | } 123 | 124 | /** 125 | * @brief This function handles PendSVC exception. 126 | * @param None 127 | * @retval None 128 | */ 129 | void PendSV_Handler(void) 130 | { 131 | } 132 | 133 | /** 134 | * @brief This function handles SysTick Handler. 135 | * @param None 136 | * @retval None 137 | */ 138 | void SysTick_Handler(void) 139 | { 140 | HAL_IncTick(); 141 | } 142 | 143 | 144 | /******************************************************************************/ 145 | /* STM32H7xx Peripherals Interrupt Handlers */ 146 | /* Add here the Interrupt Handler for the used peripheral(s) (PPP), for the */ 147 | /* available peripheral interrupt handler's name please refer to the startup */ 148 | /* file (startup_stm32h7xx.s). */ 149 | /******************************************************************************/ 150 | 151 | /** 152 | * @brief This function handles PPP interrupt request. 153 | * @param None 154 | * @retval None 155 | */ 156 | /*void PPP_IRQHandler(void) 157 | { 158 | }*/ 159 | 160 | void MDMA_IRQHandler(void) 161 | { 162 | HAL_MDMA_IRQHandler(&mdmaHandle); 163 | } 164 | 165 | void DMA1_Stream1_IRQHandler(void) 166 | { 167 | HAL_DMA_IRQHandler(adcHandle.DMA_Handle); 168 | } 169 | 170 | void DMA1_Stream2_IRQHandler(void) 171 | { 172 | HAL_DMA_IRQHandler(adc2Handle.DMA_Handle); 173 | } 174 | 175 | /** 176 | * @} 177 | */ 178 | 179 | /** 180 | * @} 181 | */ 182 | 183 | -------------------------------------------------------------------------------- /usb_payload/source/stm32h7xx_it.h: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * @file Templates_LL/Inc/stm32h7xx_it.h 4 | * @author MCD Application Team 5 | * @brief This file contains the headers of the interrupt handlers. 6 | ****************************************************************************** 7 | * @attention 8 | * 9 | * Copyright (c) 2019 STMicroelectronics. 10 | * All rights reserved. 11 | * 12 | * This software is licensed under terms that can be found in the LICENSE file 13 | * in the root directory of this software component. 14 | * If no LICENSE file comes with this software, it is provided AS-IS. 15 | * 16 | ****************************************************************************** 17 | */ 18 | 19 | /* Define to prevent recursive inclusion -------------------------------------*/ 20 | #ifndef __STM32H7xx_IT_H 21 | #define __STM32H7xx_IT_H 22 | 23 | #ifdef __cplusplus 24 | extern "C" { 25 | #endif 26 | 27 | /* Includes ------------------------------------------------------------------*/ 28 | /* Exported types ------------------------------------------------------------*/ 29 | /* Exported constants --------------------------------------------------------*/ 30 | /* Exported macro ------------------------------------------------------------*/ 31 | /* Exported functions ------------------------------------------------------- */ 32 | 33 | void NMI_Handler(void); 34 | void HardFault_Handler(void); 35 | void MemManage_Handler(void); 36 | void BusFault_Handler(void); 37 | void UsageFault_Handler(void); 38 | void SVC_Handler(void); 39 | void DebugMon_Handler(void); 40 | void PendSV_Handler(void); 41 | void SysTick_Handler(void); 42 | 43 | #ifdef __cplusplus 44 | } 45 | #endif 46 | 47 | #endif /* __STM32H7xx_IT_H */ 48 | 49 | -------------------------------------------------------------------------------- /usb_payload/source/string.c: -------------------------------------------------------------------------------- 1 | /* memset( void *, int, size_t ) 2 | 3 | This file is part of the Public Domain C Library (PDCLib). 4 | Permission is granted to use, modify, and / or redistribute at will. 5 | */ 6 | #include 7 | 8 | void * memset( void * s, int c, size_t n ) 9 | { 10 | unsigned char * p = ( unsigned char * ) s; 11 | 12 | while ( n-- ) 13 | { 14 | *p++ = ( unsigned char ) c; 15 | } 16 | 17 | return s; 18 | } 19 | -------------------------------------------------------------------------------- /usb_payload/source/syscalls.c: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * @file syscalls.c 4 | * @author Auto-generated by STM32CubeMX 5 | * @brief Minimal System calls file 6 | * 7 | * For more information about which c-functions 8 | * need which of these lowlevel functions 9 | * please consult the Newlib libc-manual 10 | ****************************************************************************** 11 | * @attention 12 | * 13 | * Copyright (c) 2020-2024 STMicroelectronics. 14 | * All rights reserved. 15 | * 16 | * This software is licensed under terms that can be found in the LICENSE file 17 | * in the root directory of this software component. 18 | * If no LICENSE file comes with this software, it is provided AS-IS. 19 | * 20 | ****************************************************************************** 21 | */ 22 | 23 | /* Includes */ 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | 33 | 34 | /* Variables */ 35 | extern int __io_putchar(int ch) __attribute__((weak)); 36 | extern int __io_getchar(void) __attribute__((weak)); 37 | 38 | 39 | char *__env[1] = { 0 }; 40 | char **environ = __env; 41 | 42 | 43 | /* Functions */ 44 | void initialise_monitor_handles() 45 | { 46 | } 47 | 48 | int _getpid(void) 49 | { 50 | return 1; 51 | } 52 | 53 | int _kill(int pid, int sig) 54 | { 55 | (void)pid; 56 | (void)sig; 57 | errno = EINVAL; 58 | return -1; 59 | } 60 | 61 | void _exit (int status) 62 | { 63 | _kill(status, -1); 64 | while (1) {} /* Make sure we hang here */ 65 | } 66 | 67 | __attribute__((weak)) int _read(int file, char *ptr, int len) 68 | { 69 | (void)file; 70 | int DataIdx; 71 | 72 | for (DataIdx = 0; DataIdx < len; DataIdx++) 73 | { 74 | *ptr++ = __io_getchar(); 75 | } 76 | 77 | return len; 78 | } 79 | 80 | __attribute__((weak)) int _write(int file, char *ptr, int len) 81 | { 82 | (void)file; 83 | int DataIdx; 84 | 85 | for (DataIdx = 0; DataIdx < len; DataIdx++) 86 | { 87 | __io_putchar(*ptr++); 88 | } 89 | return len; 90 | } 91 | 92 | int _close(int file) 93 | { 94 | (void)file; 95 | return -1; 96 | } 97 | 98 | 99 | int _fstat(int file, struct stat *st) 100 | { 101 | (void)file; 102 | st->st_mode = S_IFCHR; 103 | return 0; 104 | } 105 | 106 | int _isatty(int file) 107 | { 108 | (void)file; 109 | return 1; 110 | } 111 | 112 | int _lseek(int file, int ptr, int dir) 113 | { 114 | (void)file; 115 | (void)ptr; 116 | (void)dir; 117 | return 0; 118 | } 119 | 120 | int _open(char *path, int flags, ...) 121 | { 122 | (void)path; 123 | (void)flags; 124 | /* Pretend like we always fail */ 125 | return -1; 126 | } 127 | 128 | int _wait(int *status) 129 | { 130 | (void)status; 131 | errno = ECHILD; 132 | return -1; 133 | } 134 | 135 | int _unlink(char *name) 136 | { 137 | (void)name; 138 | errno = ENOENT; 139 | return -1; 140 | } 141 | 142 | int _times(struct tms *buf) 143 | { 144 | (void)buf; 145 | return -1; 146 | } 147 | 148 | int _stat(char *file, struct stat *st) 149 | { 150 | (void)file; 151 | st->st_mode = S_IFCHR; 152 | return 0; 153 | } 154 | 155 | int _link(char *old, char *new) 156 | { 157 | (void)old; 158 | (void)new; 159 | errno = EMLINK; 160 | return -1; 161 | } 162 | 163 | int _fork(void) 164 | { 165 | errno = EAGAIN; 166 | return -1; 167 | } 168 | 169 | int _execve(char *name, char **argv, char **env) 170 | { 171 | (void)name; 172 | (void)argv; 173 | (void)env; 174 | errno = ENOMEM; 175 | return -1; 176 | } 177 | -------------------------------------------------------------------------------- /usb_payload/source/system_stm32h7xx.c: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * @file system_stm32h7xx.c 4 | * @author MCD Application Team 5 | * @brief CMSIS Cortex-M7 Device Peripheral Access Layer System Source File. 6 | * This provides system initialization template function is case of 7 | * an application using a single core STM32H7 device 8 | * 9 | * This file provides two functions and one global variable to be called from 10 | * user application: 11 | * - SystemInit(): This function is called at startup just after reset and 12 | * before branch to main program. This call is made inside 13 | * the "startup_stm32h7xx.s" file. 14 | * 15 | * - SystemCoreClock variable: Contains the core clock (HCLK), it can be used 16 | * by the user application to setup the SysTick 17 | * timer or configure other parameters. 18 | * 19 | * - SystemCoreClockUpdate(): Updates the variable SystemCoreClock and must 20 | * be called whenever the core clock is changed 21 | * during program execution. 22 | * 23 | * 24 | ****************************************************************************** 25 | * @attention 26 | * 27 | * Copyright (c) 2017 STMicroelectronics. 28 | * All rights reserved. 29 | * 30 | * This software is licensed under terms that can be found in the LICENSE file 31 | * in the root directory of this software component. 32 | * If no LICENSE file comes with this software, it is provided AS-IS. 33 | * 34 | ****************************************************************************** 35 | */ 36 | 37 | /** @addtogroup CMSIS 38 | * @{ 39 | */ 40 | 41 | /** @addtogroup stm32h7xx_system 42 | * @{ 43 | */ 44 | 45 | /** @addtogroup STM32H7xx_System_Private_Includes 46 | * @{ 47 | */ 48 | 49 | #include "stm32h7xx.h" 50 | #include 51 | 52 | #if !defined (HSE_VALUE) 53 | #define HSE_VALUE ((uint32_t)25000000) /*!< Value of the External oscillator in Hz */ 54 | #endif /* HSE_VALUE */ 55 | 56 | #if !defined (CSI_VALUE) 57 | #define CSI_VALUE ((uint32_t)4000000) /*!< Value of the Internal oscillator in Hz*/ 58 | #endif /* CSI_VALUE */ 59 | 60 | #if !defined (HSI_VALUE) 61 | #define HSI_VALUE ((uint32_t)64000000) /*!< Value of the Internal oscillator in Hz*/ 62 | #endif /* HSI_VALUE */ 63 | 64 | 65 | /** 66 | * @} 67 | */ 68 | 69 | /** @addtogroup STM32H7xx_System_Private_TypesDefinitions 70 | * @{ 71 | */ 72 | 73 | /** 74 | * @} 75 | */ 76 | 77 | /** @addtogroup STM32H7xx_System_Private_Defines 78 | * @{ 79 | */ 80 | 81 | /************************* Miscellaneous Configuration ************************/ 82 | /*!< Uncomment the following line if you need to use initialized data in D2 domain SRAM (AHB SRAM) */ 83 | /* #define DATA_IN_D2_SRAM */ 84 | 85 | /* Note: Following vector table addresses must be defined in line with linker 86 | configuration. */ 87 | /*!< Uncomment the following line if you need to relocate the vector table, 88 | else the vector table is kept at the automatic remap of boot address selected */ 89 | #define USER_VECT_TAB_ADDRESS 90 | 91 | #if defined(USER_VECT_TAB_ADDRESS) 92 | #define VECT_TAB_BASE_ADDRESS OCTOSPI2_BASE /*!< Vector Table base address field. 93 | This value must be a multiple of 0x400. */ 94 | #define VECT_TAB_OFFSET 0x00000400U /*!< Vector Table base offset field. 95 | This value must be a multiple of 0x400. */ 96 | #endif /* USER_VECT_TAB_ADDRESS */ 97 | /******************************************************************************/ 98 | 99 | /** 100 | * @} 101 | */ 102 | 103 | /** @addtogroup STM32H7xx_System_Private_Macros 104 | * @{ 105 | */ 106 | 107 | /** 108 | * @} 109 | */ 110 | 111 | /** @addtogroup STM32H7xx_System_Private_Variables 112 | * @{ 113 | */ 114 | /* This variable is updated in three ways: 115 | 1) by calling CMSIS function SystemCoreClockUpdate() 116 | 2) by calling HAL API function HAL_RCC_GetHCLKFreq() 117 | 3) each time HAL_RCC_ClockConfig() is called to configure the system clock frequency 118 | Note: If you use this function to configure the system clock; then there 119 | is no need to call the 2 first functions listed above, since SystemCoreClock 120 | variable is updated automatically. 121 | */ 122 | uint32_t SystemCoreClock = 64000000; 123 | uint32_t SystemD2Clock = 64000000; 124 | const uint8_t D1CorePrescTable[16] = {0, 0, 0, 0, 1, 2, 3, 4, 1, 2, 3, 4, 6, 7, 8, 9}; 125 | 126 | /** 127 | * @} 128 | */ 129 | 130 | /** @addtogroup STM32H7xx_System_Private_FunctionPrototypes 131 | * @{ 132 | */ 133 | 134 | /** 135 | * @} 136 | */ 137 | 138 | /** @addtogroup STM32H7xx_System_Private_Functions 139 | * @{ 140 | */ 141 | 142 | /** 143 | * @brief Setup the microcontroller system 144 | * Initialize the FPU setting and vector table location 145 | * configuration. 146 | * @param None 147 | * @retval None 148 | */ 149 | void SystemInit (void) 150 | { 151 | #if defined (DATA_IN_D2_SRAM) 152 | __IO uint32_t tmpreg; 153 | #endif /* DATA_IN_D2_SRAM */ 154 | 155 | /* FPU settings ------------------------------------------------------------*/ 156 | #if (__FPU_PRESENT == 1) && (__FPU_USED == 1) 157 | SCB->CPACR |= ((3UL << (10*2))|(3UL << (11*2))); /* set CP10 and CP11 Full Access */ 158 | #endif 159 | /* Reset the RCC clock configuration to the default reset state ------------*/ 160 | 161 | /* Increasing the CPU frequency */ 162 | if(FLASH_LATENCY_DEFAULT > (READ_BIT((FLASH->ACR), FLASH_ACR_LATENCY))) 163 | { 164 | /* Program the new number of wait states to the LATENCY bits in the FLASH_ACR register */ 165 | MODIFY_REG(FLASH->ACR, FLASH_ACR_LATENCY, (uint32_t)(FLASH_LATENCY_DEFAULT)); 166 | } 167 | 168 | /* Set HSION bit */ 169 | RCC->CR |= RCC_CR_HSION; 170 | 171 | /* Reset CFGR register */ 172 | RCC->CFGR = 0x00000000; 173 | 174 | /* Reset HSEON, HSECSSON, CSION, HSI48ON, CSIKERON, PLL1ON, PLL2ON and PLL3ON bits */ 175 | RCC->CR &= 0xEAF6ED7FU; 176 | 177 | /* Decreasing the number of wait states because of lower CPU frequency */ 178 | if(FLASH_LATENCY_DEFAULT < (READ_BIT((FLASH->ACR), FLASH_ACR_LATENCY))) 179 | { 180 | /* Program the new number of wait states to the LATENCY bits in the FLASH_ACR register */ 181 | MODIFY_REG(FLASH->ACR, FLASH_ACR_LATENCY, (uint32_t)(FLASH_LATENCY_DEFAULT)); 182 | } 183 | 184 | #if defined(D3_SRAM_BASE) 185 | /* Reset D1CFGR register */ 186 | RCC->D1CFGR = 0x00000000; 187 | 188 | /* Reset D2CFGR register */ 189 | RCC->D2CFGR = 0x00000000; 190 | 191 | /* Reset D3CFGR register */ 192 | RCC->D3CFGR = 0x00000000; 193 | #else 194 | /* Reset CDCFGR1 register */ 195 | RCC->CDCFGR1 = 0x00000000; 196 | 197 | /* Reset CDCFGR2 register */ 198 | RCC->CDCFGR2 = 0x00000000; 199 | 200 | /* Reset SRDCFGR register */ 201 | RCC->SRDCFGR = 0x00000000; 202 | #endif 203 | /* Reset PLLCKSELR register */ 204 | RCC->PLLCKSELR = 0x02020200; 205 | 206 | /* Reset PLLCFGR register */ 207 | RCC->PLLCFGR = 0x01FF0000; 208 | /* Reset PLL1DIVR register */ 209 | RCC->PLL1DIVR = 0x01010280; 210 | /* Reset PLL1FRACR register */ 211 | RCC->PLL1FRACR = 0x00000000; 212 | 213 | /* Reset PLL2DIVR register */ 214 | RCC->PLL2DIVR = 0x01010280; 215 | 216 | /* Reset PLL2FRACR register */ 217 | 218 | RCC->PLL2FRACR = 0x00000000; 219 | /* Reset PLL3DIVR register */ 220 | RCC->PLL3DIVR = 0x01010280; 221 | 222 | /* Reset PLL3FRACR register */ 223 | RCC->PLL3FRACR = 0x00000000; 224 | 225 | /* Reset HSEBYP bit */ 226 | RCC->CR &= 0xFFFBFFFFU; 227 | 228 | /* Disable all interrupts */ 229 | RCC->CIER = 0x00000000; 230 | 231 | #if (STM32H7_DEV_ID == 0x450UL) 232 | /* single core line */ 233 | if((DBGMCU->IDCODE & 0xFFFF0000U) < 0x20000000U) 234 | { 235 | /* if stm32h7 revY*/ 236 | /* Change the switch matrix read issuing capability to 1 for the AXI SRAM target (Target 7) */ 237 | *((__IO uint32_t*)0x51008108) = 0x000000001U; 238 | } 239 | #endif 240 | 241 | #if defined (DATA_IN_D2_SRAM) 242 | /* in case of initialized data in D2 SRAM (AHB SRAM), enable the D2 SRAM clock (AHB SRAM clock) */ 243 | #if defined(RCC_AHB2ENR_D2SRAM3EN) 244 | RCC->AHB2ENR |= (RCC_AHB2ENR_D2SRAM1EN | RCC_AHB2ENR_D2SRAM2EN | RCC_AHB2ENR_D2SRAM3EN); 245 | #elif defined(RCC_AHB2ENR_D2SRAM2EN) 246 | RCC->AHB2ENR |= (RCC_AHB2ENR_D2SRAM1EN | RCC_AHB2ENR_D2SRAM2EN); 247 | #else 248 | RCC->AHB2ENR |= (RCC_AHB2ENR_AHBSRAM1EN | RCC_AHB2ENR_AHBSRAM2EN); 249 | #endif /* RCC_AHB2ENR_D2SRAM3EN */ 250 | 251 | tmpreg = RCC->AHB2ENR; 252 | (void) tmpreg; 253 | #endif /* DATA_IN_D2_SRAM */ 254 | 255 | /* 256 | * Disable the FMC bank1 (enabled after reset). 257 | * This, prevents CPU speculation access on this bank which blocks the use of FMC during 258 | * 24us. During this time the others FMC master (such as LTDC) cannot use it! 259 | */ 260 | FMC_Bank1_R->BTCR[0] = 0x000030D2; 261 | 262 | /* Configure the Vector Table location add offset address ------------------*/ 263 | #if defined(USER_VECT_TAB_ADDRESS) 264 | SCB->VTOR = VECT_TAB_BASE_ADDRESS | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal D1 AXI-RAM or in Internal FLASH */ 265 | #endif /* USER_VECT_TAB_ADDRESS */ 266 | } 267 | 268 | /** 269 | * @brief Update SystemCoreClock variable according to Clock Register Values. 270 | * The SystemCoreClock variable contains the core clock , it can 271 | * be used by the user application to setup the SysTick timer or configure 272 | * other parameters. 273 | * 274 | * @note Each time the core clock changes, this function must be called 275 | * to update SystemCoreClock variable value. Otherwise, any configuration 276 | * based on this variable will be incorrect. 277 | * 278 | * @note - The system frequency computed by this function is not the real 279 | * frequency in the chip. It is calculated based on the predefined 280 | * constant and the selected clock source: 281 | * 282 | * - If SYSCLK source is CSI, SystemCoreClock will contain the CSI_VALUE(*) 283 | * - If SYSCLK source is HSI, SystemCoreClock will contain the HSI_VALUE(**) 284 | * - If SYSCLK source is HSE, SystemCoreClock will contain the HSE_VALUE(***) 285 | * - If SYSCLK source is PLL, SystemCoreClock will contain the CSI_VALUE(*), 286 | * HSI_VALUE(**) or HSE_VALUE(***) multiplied/divided by the PLL factors. 287 | * 288 | * (*) CSI_VALUE is a constant defined in stm32h7xx_hal.h file (default value 289 | * 4 MHz) but the real value may vary depending on the variations 290 | * in voltage and temperature. 291 | * (**) HSI_VALUE is a constant defined in stm32h7xx_hal.h file (default value 292 | * 64 MHz) but the real value may vary depending on the variations 293 | * in voltage and temperature. 294 | * 295 | * (***)HSE_VALUE is a constant defined in stm32h7xx_hal.h file (default value 296 | * 25 MHz), user has to ensure that HSE_VALUE is same as the real 297 | * frequency of the crystal used. Otherwise, this function may 298 | * have wrong result. 299 | * 300 | * - The result of this function could be not correct when using fractional 301 | * value for HSE crystal. 302 | * @param None 303 | * @retval None 304 | */ 305 | void SystemCoreClockUpdate (void) 306 | { 307 | uint32_t pllp, pllsource, pllm, pllfracen, hsivalue, tmp; 308 | float_t fracn1, pllvco; 309 | 310 | /* Get SYSCLK source -------------------------------------------------------*/ 311 | 312 | switch (RCC->CFGR & RCC_CFGR_SWS) 313 | { 314 | case RCC_CFGR_SWS_HSI: /* HSI used as system clock source */ 315 | SystemCoreClock = (uint32_t) (HSI_VALUE >> ((RCC->CR & RCC_CR_HSIDIV)>> 3)); 316 | 317 | break; 318 | 319 | case RCC_CFGR_SWS_CSI: /* CSI used as system clock source */ 320 | SystemCoreClock = CSI_VALUE; 321 | break; 322 | 323 | case RCC_CFGR_SWS_HSE: /* HSE used as system clock source */ 324 | SystemCoreClock = HSE_VALUE; 325 | break; 326 | 327 | case RCC_CFGR_SWS_PLL1: /* PLL1 used as system clock source */ 328 | 329 | /* PLL_VCO = (HSE_VALUE or HSI_VALUE or CSI_VALUE/ PLLM) * PLLN 330 | SYSCLK = PLL_VCO / PLLR 331 | */ 332 | pllsource = (RCC->PLLCKSELR & RCC_PLLCKSELR_PLLSRC); 333 | pllm = ((RCC->PLLCKSELR & RCC_PLLCKSELR_DIVM1)>> 4) ; 334 | pllfracen = ((RCC->PLLCFGR & RCC_PLLCFGR_PLL1FRACEN)>>RCC_PLLCFGR_PLL1FRACEN_Pos); 335 | fracn1 = (float_t)(uint32_t)(pllfracen* ((RCC->PLL1FRACR & RCC_PLL1FRACR_FRACN1)>> 3)); 336 | 337 | if (pllm != 0U) 338 | { 339 | switch (pllsource) 340 | { 341 | case RCC_PLLCKSELR_PLLSRC_HSI: /* HSI used as PLL clock source */ 342 | 343 | hsivalue = (HSI_VALUE >> ((RCC->CR & RCC_CR_HSIDIV)>> 3)) ; 344 | pllvco = ( (float_t)hsivalue / (float_t)pllm) * ((float_t)(uint32_t)(RCC->PLL1DIVR & RCC_PLL1DIVR_N1) + (fracn1/(float_t)0x2000) +(float_t)1 ); 345 | 346 | break; 347 | 348 | case RCC_PLLCKSELR_PLLSRC_CSI: /* CSI used as PLL clock source */ 349 | pllvco = ((float_t)CSI_VALUE / (float_t)pllm) * ((float_t)(uint32_t)(RCC->PLL1DIVR & RCC_PLL1DIVR_N1) + (fracn1/(float_t)0x2000) +(float_t)1 ); 350 | break; 351 | 352 | case RCC_PLLCKSELR_PLLSRC_HSE: /* HSE used as PLL clock source */ 353 | pllvco = ((float_t)HSE_VALUE / (float_t)pllm) * ((float_t)(uint32_t)(RCC->PLL1DIVR & RCC_PLL1DIVR_N1) + (fracn1/(float_t)0x2000) +(float_t)1 ); 354 | break; 355 | 356 | default: 357 | hsivalue = (HSI_VALUE >> ((RCC->CR & RCC_CR_HSIDIV)>> 3)) ; 358 | pllvco = ((float_t)hsivalue / (float_t)pllm) * ((float_t)(uint32_t)(RCC->PLL1DIVR & RCC_PLL1DIVR_N1) + (fracn1/(float_t)0x2000) +(float_t)1 ); 359 | break; 360 | } 361 | pllp = (((RCC->PLL1DIVR & RCC_PLL1DIVR_P1) >>9) + 1U ) ; 362 | SystemCoreClock = (uint32_t)(float_t)(pllvco/(float_t)pllp); 363 | } 364 | else 365 | { 366 | SystemCoreClock = 0U; 367 | } 368 | break; 369 | 370 | default: 371 | SystemCoreClock = (uint32_t) (HSI_VALUE >> ((RCC->CR & RCC_CR_HSIDIV)>> 3)); 372 | break; 373 | } 374 | 375 | /* Compute SystemClock frequency --------------------------------------------------*/ 376 | #if defined (RCC_D1CFGR_D1CPRE) 377 | tmp = D1CorePrescTable[(RCC->D1CFGR & RCC_D1CFGR_D1CPRE)>> RCC_D1CFGR_D1CPRE_Pos]; 378 | 379 | /* SystemCoreClock frequency : CM7 CPU frequency */ 380 | SystemCoreClock >>= tmp; 381 | 382 | /* SystemD2Clock frequency : AXI and AHBs Clock frequency */ 383 | SystemD2Clock = (SystemCoreClock >> ((D1CorePrescTable[(RCC->D1CFGR & RCC_D1CFGR_HPRE)>> RCC_D1CFGR_HPRE_Pos]) & 0x1FU)); 384 | #else 385 | tmp = D1CorePrescTable[(RCC->CDCFGR1 & RCC_CDCFGR1_CDCPRE)>> RCC_CDCFGR1_CDCPRE_Pos]; 386 | 387 | SystemCoreClock >>= tmp; 388 | /* SystemD2Clock frequency : AXI and AHBs Clock frequency */ 389 | SystemD2Clock = (SystemCoreClock >> ((D1CorePrescTable[(RCC->CDCFGR1 & RCC_CDCFGR1_HPRE)>> RCC_CDCFGR1_HPRE_Pos]) & 0x1FU)); 390 | #endif 391 | } 392 | 393 | /** 394 | * @} 395 | */ 396 | 397 | /** 398 | * @} 399 | */ 400 | 401 | /** 402 | * @} 403 | */ 404 | --------------------------------------------------------------------------------