├── alsa_test.sh ├── blue_pill.h ├── build.sh ├── cmsis ├── cmsis_compiler.h ├── cmsis_gcc.h ├── cmsis_version.h ├── core_cm3.h ├── dummy ├── stm32f103xb.h ├── stm32f1xx.h └── system_stm32f1xx.h ├── descriptors_audio.s ├── ldscripts ├── blue_pill.ld ├── dummy └── vectors.ld ├── readme.txt ├── screenshots ├── dummy ├── middle point.png ├── mp norm.png └── test signal.png ├── usb.h ├── usb_audio.c └── usb_audio_flash.bin /alsa_test.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/bash 2 | 3 | arecord -D hw:Prod -f S16_LE -r 192000 -d 1 record.wav 4 | 5 | -------------------------------------------------------------------------------- /blue_pill.h: -------------------------------------------------------------------------------- 1 | /* 2 | `blue_pill.h` - header file for the Blue Pill board (STM32F103). 3 | 4 | Include tree and dependencies: 5 | 6 | blue_pill.h - this file 7 | '-stm32f1xx.h + STM peripheral library header 8 | |-stm32f103xb.h - library core 9 | |-{system_stm32f1xx.h} - {this header is useless, but included} 10 | '-core_cm3.h + ARM CMSIS library core 11 | |-cmsis_version.h - library version 12 | '-cmsis_compiler.h - compiler selection 13 | '-cmsis_gcc.h - compiler specific CM3 intrinsics 14 | 15 | Standard CMSIS headers can be downloaded 16 | from official ST and ARM GitHub repos: 17 | 18 | https://github.com/STMicroelectronics/STM32Cube_MCU_Overall_Offer#stm32cube-cmsis 19 | https://github.com/ARM-software/CMSIS_5 20 | 21 | Linker scripts are also provided: 22 | 23 | blue_pill.ld - main linker script 24 | `-vectors.ld - interrupts vectors loctions table 25 | */ 26 | 27 | 28 | #ifndef __BLUE_PILL 29 | #define __BLUE_PILL 30 | 31 | 32 | /* Standard ST and Arm CMSIS headers */ 33 | 34 | #define STM32F103xB 35 | #include 36 | 37 | 38 | /* Stack pointer value initialization; 39 | `_estack` must be provided by a linker script */ 40 | 41 | asm(" .pushsection .isr_vector.__sp_val,\"aG\",%progbits,_grp_sp_val,comdat "); 42 | asm(" .word _estack "); 43 | asm(" .popsection "); 44 | 45 | 46 | /* Vector definition macro: 47 | `vn` - IRQ number or vector name in form of 48 | `IRQ_`, where `` corresponds 49 | to a vector Acronym from the Reference Manual; 50 | `fname` - exception handler function. 51 | 52 | Example: 53 | void my_handler(void); 54 | VECTOR(IRQ_NMI, my_handler); */ 55 | 56 | #define VECTOR(vn, fname) __VECTOR(vn, fname) 57 | 58 | #define __VECTOR(vn, fname) \ 59 | volatile void *__vec_##vn \ 60 | __attribute__((section(".isr_vector.__vec_"#vn",\"aG\",%progbits,_grp_vec_"#vn",comdat @;"), used)) \ 61 | = (void*)(fname + 1) 62 | 63 | 64 | /* System exceptions names for using with `VECTOR()` calls 65 | (they cannot be used with `NVIC_*` CMSIS functions) */ 66 | #define IRQ_Reset IRQ_Reset 67 | #define IRQ_NMI IRQ_NMI 68 | #define IRQ_HardFault IRQ_HardFault 69 | #define IRQ_MemManage IRQ_MemManage 70 | #define IRQ_BusFault IRQ_BusFault 71 | #define IRQ_UsageFault IRQ_UsageFault 72 | #define IRQ_SVCall IRQ_SVCall 73 | #define IRQ_DebugMonitor IRQ_DebugMonitor 74 | #define IRQ_PendSV IRQ_PendSV 75 | #define IRQ_SysTick IRQ_SysTick 76 | 77 | 78 | /* IRQs names for using with `VECTOR()` calls instead of numers */ 79 | #define IRQ_WWDG 0 80 | #define IRQ_PVD 1 81 | #define IRQ_TAMPER 2 82 | #define IRQ_RTC 3 83 | #define IRQ_FLASH 4 84 | #define IRQ_RCC 5 85 | #define IRQ_EXTI0 6 86 | #define IRQ_EXTI1 7 87 | #define IRQ_EXTI2 8 88 | #define IRQ_EXTI3 9 89 | #define IRQ_EXTI4 10 90 | #define IRQ_DMA1_Channel1 11 91 | #define IRQ_DMA1_Channel2 12 92 | #define IRQ_DMA1_Channel3 13 93 | #define IRQ_DMA1_Channel4 14 94 | #define IRQ_DMA1_Channel5 15 95 | #define IRQ_DMA1_Channel6 16 96 | #define IRQ_DMA1_Channel7 17 97 | #define IRQ_ADC1_2 18 98 | #define IRQ_USB_HP_CAN_TX 19 99 | #define IRQ_USB_LP_CAN_RX0 20 100 | #define IRQ_CAN_RX1 21 101 | #define IRQ_CAN_SCE 22 102 | #define IRQ_EXTI9_5 23 103 | #define IRQ_TIM1_BRK 24 104 | #define IRQ_TIM1_UP 25 105 | #define IRQ_TIM1_TRG_COM 26 106 | #define IRQ_TIM1_CC 27 107 | #define IRQ_TIM2 28 108 | #define IRQ_TIM3 29 109 | #define IRQ_TIM4 30 110 | #define IRQ_I2C1_EV 31 111 | #define IRQ_I2C1_ER 32 112 | #define IRQ_I2C2_EV 33 113 | #define IRQ_I2C2_ER 34 114 | #define IRQ_SPI1 35 115 | #define IRQ_SPI2 36 116 | #define IRQ_USART1 37 117 | #define IRQ_USART2 38 118 | #define IRQ_USART3 39 119 | #define IRQ_EXTI15_10 40 120 | #define IRQ_RTCAlarm 41 121 | #define IRQ_USBWakeup 42 122 | 123 | 124 | /* Interrupt enable/disable (one at a time) */ 125 | #define INTERRUPT_ENABLE(n) NVIC->ISER[(n)/32] = 1 << ((n)%32) 126 | #define INTERRUPT_DISABLE(n) NVIC->ICER[(n)/32] = 1 << ((n)%32) 127 | #define INTERRUPT_SET_PENDING(n) NVIC->ISPR[(n)/32] = 1 << ((n)%32) 128 | #define INTERRUPT_CLEAR_PENDING(n) NVIC->ICPR[(n)/32] = 1 << ((n)%32) 129 | #define INTERRUPT_PRIORITY(n, p) NVIC->IP[n] = (p) << 4 130 | 131 | 132 | /* Software interrupts 133 | `n` - softint consecutive number, must start with 0 134 | 135 | Example: 136 | #define IRQ_MySoftInt 0 137 | 138 | void my_softint_handler(void); 139 | SOFTINT_VECTOR(IRQ_MySoftInt, my_softint_handler); 140 | ... 141 | SOFTINT_ENABLE(IRQ_MySoftInt); 142 | ... 143 | SOFTINT_SET_PENDING(IRQ_MySoftInt); */ 144 | 145 | #define SOFTINT_VECTOR(vn, fname) VECTOR(IRQ_Soft(vn), fname) 146 | 147 | /* `SORT_BY_NAME` must be used in a linker script */ 148 | #define IRQ_Soft(n) IRQ_Soft_##n 149 | 150 | #define _IRQ_Soft_Num 43 151 | 152 | #define SOFTINT_ENABLE(n) INTERRUPT_ENABLE((n) + _IRQ_Soft_Num) 153 | #define SOFTINT_DISABLE(n) INTERRUPT_DISABLE((n) + _IRQ_Soft_Num) 154 | #define SOFTINT_SET_PENDING(n) INTERRUPT_SET_PENDING((n) + _IRQ_Soft_Num) 155 | #define SOFTINT_CLEAR_PENDING(n) INTERRUPT_CLEAR_PENDING((n) + _IRQ_Soft_Num) 156 | #define SOFTINT_PRIORITY(n, p) INTERRUPT_PRIORITY((n) + _IRQ_Soft_Num, p) 157 | 158 | 159 | /* Data segment break is stored at `CoreDebug->DCRDR` */ 160 | 161 | #define BRKR (*(volatile uint32_t*)&CoreDebug->DCRDR) 162 | 163 | void* sbrk(uint32_t n) { 164 | uint32_t 165 | *b = (uint32_t*)&BRKR, 166 | t; 167 | 168 | t = *b; 169 | *b += n; 170 | 171 | return (void*)t; 172 | } 173 | 174 | 175 | /* Startup code and reset vector initialization 176 | (NMI, HardFault and other vectors must be defined by user) */ 177 | 178 | int main() asm("_start") __attribute__((noreturn)); 179 | 180 | #ifndef NO_INIT 181 | 182 | __attribute__((naked, noreturn)) 183 | __attribute__((section(".text.reset_handler,\"axG\",%progbits,_grp_reset_handler,comdat @;"))) 184 | void reset_handler(void) { 185 | /* 186 | Default reset handler. 187 | */ 188 | 189 | /* Symbols must be provided by a linker script */ 190 | extern uint8_t 191 | _sidata, _sdata, _edata, 192 | _sbss, _ebss; 193 | extern uint32_t 194 | _sivt; 195 | 196 | register uint8_t 197 | *src = &_sidata, 198 | *dst = &_sdata; 199 | 200 | if (src != dst) { 201 | while (dst < &_edata) { 202 | *dst++ = *src++; 203 | } 204 | } 205 | 206 | dst = &_sbss; 207 | 208 | while (dst < &_ebss) { 209 | *dst++ = 0; 210 | } 211 | 212 | SCB->VTOR = (uint32_t)&_sivt; 213 | 214 | BRKR = (uint32_t)&_ebss; 215 | 216 | /* main(); */ 217 | asm("b _start"); 218 | } 219 | 220 | VECTOR(IRQ_Reset, reset_handler); 221 | 222 | #else 223 | 224 | VECTOR(IRQ_Reset, main); 225 | 226 | #endif /* NO_INIT */ 227 | 228 | 229 | /* Simple wait loop */ 230 | __attribute__((naked)) 231 | void wait_x3_cycles(uint32_t c) { 232 | asm(" 1: "); 233 | asm(" subs r0, #1 "); 234 | asm(" bne 1b "); 235 | asm(" bx lr "); 236 | } 237 | 238 | /* Time wait definitions (accurate only when running from 239 | flash and when CPU frequency or `n` is divisible by 3): 240 | `n` - time to wait; 241 | `MHz` - CPU frequency in MHz. 242 | 243 | Example: 244 | #define F_CPU_MHz 72 245 | wait_μs(1000, F_CPU_MHz); */ 246 | 247 | #define wait_μs(n, MHz) wait_x3_cycles((n)*(MHz)/3) 248 | #define wait_ms(n, MHz) wait_μs((n)*1000, MHz) 249 | #define wait_s(n, MHz) wait_μs((n)*1000000, MHz) 250 | 251 | 252 | /* Converts normal address to bit-band address: 253 | `addr` - register address; 254 | `bit` - bit number. 255 | 256 | Example: 257 | #define BB_PC14_OUT BITBAND(GPIOC->ODR, 14) */ 258 | 259 | #define BITBAND(reg, bit) \ 260 | ( \ 261 | *(volatile uint32_t*) ( \ 262 | ( (uint32_t)(&(reg)) & 0xf0000000 ) + 0x02000000 \ 263 | + ( (uint32_t)(&(reg)) & 0x000fffff ) * 32 \ 264 | + bit * 4 \ 265 | ) \ 266 | ) 267 | 268 | 269 | /* GPIO pin configure macro: 270 | `gpio` - GPIO address; 271 | `pin_n` - pin number; 272 | `conf_bits` - 4 bits of configuration. 273 | 274 | Example: 275 | CONFIGURE_PIN(GPIOC, 13, O_OPEN_DRAIN); */ 276 | 277 | #define CONFIGURE_PIN(gpio, pin_n, conf_bits) \ 278 | ( \ 279 | *((volatile uint32_t*)gpio + pin_n/8) = \ 280 | (*((volatile uint32_t*)gpio + pin_n/8) \ 281 | & ~(0b1111 << pin_n%8*4)) \ 282 | | conf_bits << pin_n%8*4 \ 283 | ) 284 | 285 | #define I_ANALOG 0b0000 286 | #define I_FLOATING 0b0100 287 | #define I_PULLED 0b1000 288 | #define O_PUSH_PULL 0b0001 289 | #define O_OPEN_DRAIN 0b0101 290 | #define O_ALT_PUSH_PULL 0b1001 291 | #define O_ALT_OPEN_DRAIN 0b1101 292 | 293 | #define BB_PC13_OUT BITBAND(GPIOC->ODR, 13) 294 | #define LED BB_PC13_OUT 295 | #define LED_ON() BB_PC13_OUT = 0 296 | #define LED_OFF() BB_PC13_OUT = 1 297 | #define LED_TOGGLE() BB_PC13_OUT ^= 1 298 | 299 | 300 | /* PLL and SYSCLK configuration; 301 | (the macro works only after MC reset, 302 | it will NOT work if PLL is already running): 303 | `src` - input clock: HSI2, HSE or HSE2, 304 | `MHz` - PLL output frequency in MHz. 305 | 306 | Possible `MHz` values are: 307 | for HSI2 and HSE2: 308 | 12, 16,20,24,28,32,36,40,44,48,52,56,60,64 309 | (8 — not guaranteed) 310 | for HSE: 311 | 16, 24, 32, 40, 48, 56, 64, 72 312 | (80,88,96,104,112,120,128 - not guaranteed) 313 | 314 | Example 1: 315 | #define F_CPU_MHz 72 316 | CONFIGURE_PLL(HSE, F_CPU_MHz); 317 | 318 | Example 2: 319 | #define F_CPU_MHz 8 320 | SW_EXTERNAL_8MHZ(); */ 321 | 322 | #define CONFIGURE_PLL(src, MHz) do { \ 323 | FLASH->ACR = 0x10 | (MHz <= 24 ? 0 : (MHz <= 48 ? 1 : 2)); \ 324 | RCC->CFGR = ((MHz / (src==HSE ? 2:1) - 8) | src) << 16; \ 325 | RCC->CR = src==HSI2 ? HSION : HSEON; \ 326 | while (!(src==HSI2 ? BB_HSIRDY : BB_HSERDY)); \ 327 | RCC->CR = PLLON | (src==HSI2 ? HSION : HSEON); \ 328 | while (!(BB_PLLRDY)); \ 329 | RCC->CFGR = PLL | (MHz > 36 ? RCC_CFGR_PPRE1_DIV2 : 0); \ 330 | } while(0) 331 | 332 | #define SW_EXTERNAL_8MHZ() do { \ 333 | RCC->CR = HSEON; while (!BB_HSERDY); RCC->CFGR = HSE; \ 334 | } while(0) 335 | 336 | /* PLL sources, (PLLXTPRE | PLLSRC) */ 337 | #define HSI2 0b00 338 | #define HSE 0b01 339 | #define HSE2 0b11 340 | 341 | /* RCC_CFGR_SW value for PLL */ 342 | #define PLL 0b10 343 | 344 | /* RCC_CR bits */ 345 | #define PLLON (1<<24) 346 | #define HSEON (1<<16) 347 | #define HSION (1<<0) 348 | #define BB_PLLRDY BITBAND(RCC->CR, 25) 349 | #define BB_HSERDY BITBAND(RCC->CR, 17) 350 | #define BB_HSIRDY BITBAND(RCC->CR, 1) 351 | 352 | 353 | /* Other definitions */ 354 | 355 | #define NULL ((void*)0) 356 | 357 | 358 | #endif /* __BLUE_PILL */ 359 | 360 | /* end. */ 361 | -------------------------------------------------------------------------------- /build.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/sh 2 | 3 | # Provided linker scripts can easily be used 4 | # for compilation against RAM. Do not forget 5 | # to change address in your flashing program. 6 | 7 | FLASH_BASE=0x08000000 8 | SRAM_BASE=0x20000200 9 | 10 | ORIGIN=$FLASH_BASE 11 | # ORIGIN=$SRAM_BASE 12 | 13 | arm-none-eabi-gcc \ 14 | -c -O2 usb_audio.c -I cmsis -mcpu=cortex-m3 -mthumb -Wall -Wno-unused \ 15 | -fno-hosted -ffunction-sections -fdata-sections -fno-inline -fno-align-functions && 16 | 17 | arm-none-eabi-ld \ 18 | usb_audio.o -o usb_audio.elf -Ttext=$ORIGIN \ 19 | --gc-sections -L ldscripts -T blue_pill.ld --strip-debug && 20 | 21 | arm-none-eabi-objcopy \ 22 | -O binary usb_audio.elf usb_audio.bin && 23 | 24 | ( echo Origin: $ORIGIN 25 | echo Binary size: `wc -c usb_audio.bin` ) 26 | -------------------------------------------------------------------------------- /cmsis/cmsis_compiler.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************//** 2 | * @file cmsis_compiler.h 3 | * @brief CMSIS compiler generic header file 4 | * @version V5.1.0 5 | * @date 09. October 2018 6 | ******************************************************************************/ 7 | /* 8 | * Copyright (c) 2009-2018 Arm Limited. All rights reserved. 9 | * 10 | * SPDX-License-Identifier: Apache-2.0 11 | * 12 | * Licensed under the Apache License, Version 2.0 (the License); you may 13 | * not use this file except in compliance with the License. 14 | * You may obtain a copy of the License at 15 | * 16 | * www.apache.org/licenses/LICENSE-2.0 17 | * 18 | * Unless required by applicable law or agreed to in writing, software 19 | * distributed under the License is distributed on an AS IS BASIS, WITHOUT 20 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 21 | * See the License for the specific language governing permissions and 22 | * limitations under the License. 23 | */ 24 | 25 | #ifndef __CMSIS_COMPILER_H 26 | #define __CMSIS_COMPILER_H 27 | 28 | #include 29 | 30 | /* 31 | * Arm Compiler 4/5 32 | */ 33 | #if defined ( __CC_ARM ) 34 | #include "cmsis_armcc.h" 35 | 36 | 37 | /* 38 | * Arm Compiler 6.6 LTM (armclang) 39 | */ 40 | #elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) && (__ARMCC_VERSION < 6100100) 41 | #include "cmsis_armclang_ltm.h" 42 | 43 | /* 44 | * Arm Compiler above 6.10.1 (armclang) 45 | */ 46 | #elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6100100) 47 | #include "cmsis_armclang.h" 48 | 49 | 50 | /* 51 | * GNU Compiler 52 | */ 53 | #elif defined ( __GNUC__ ) 54 | #include "cmsis_gcc.h" 55 | 56 | 57 | /* 58 | * IAR Compiler 59 | */ 60 | #elif defined ( __ICCARM__ ) 61 | #include 62 | 63 | 64 | /* 65 | * TI Arm Compiler 66 | */ 67 | #elif defined ( __TI_ARM__ ) 68 | #include 69 | 70 | #ifndef __ASM 71 | #define __ASM __asm 72 | #endif 73 | #ifndef __INLINE 74 | #define __INLINE inline 75 | #endif 76 | #ifndef __STATIC_INLINE 77 | #define __STATIC_INLINE static inline 78 | #endif 79 | #ifndef __STATIC_FORCEINLINE 80 | #define __STATIC_FORCEINLINE __STATIC_INLINE 81 | #endif 82 | #ifndef __NO_RETURN 83 | #define __NO_RETURN __attribute__((noreturn)) 84 | #endif 85 | #ifndef __USED 86 | #define __USED __attribute__((used)) 87 | #endif 88 | #ifndef __WEAK 89 | #define __WEAK __attribute__((weak)) 90 | #endif 91 | #ifndef __PACKED 92 | #define __PACKED __attribute__((packed)) 93 | #endif 94 | #ifndef __PACKED_STRUCT 95 | #define __PACKED_STRUCT struct __attribute__((packed)) 96 | #endif 97 | #ifndef __PACKED_UNION 98 | #define __PACKED_UNION union __attribute__((packed)) 99 | #endif 100 | #ifndef __UNALIGNED_UINT32 /* deprecated */ 101 | struct __attribute__((packed)) T_UINT32 { uint32_t v; }; 102 | #define __UNALIGNED_UINT32(x) (((struct T_UINT32 *)(x))->v) 103 | #endif 104 | #ifndef __UNALIGNED_UINT16_WRITE 105 | __PACKED_STRUCT T_UINT16_WRITE { uint16_t v; }; 106 | #define __UNALIGNED_UINT16_WRITE(addr, val) (void)((((struct T_UINT16_WRITE *)(void*)(addr))->v) = (val)) 107 | #endif 108 | #ifndef __UNALIGNED_UINT16_READ 109 | __PACKED_STRUCT T_UINT16_READ { uint16_t v; }; 110 | #define __UNALIGNED_UINT16_READ(addr) (((const struct T_UINT16_READ *)(const void *)(addr))->v) 111 | #endif 112 | #ifndef __UNALIGNED_UINT32_WRITE 113 | __PACKED_STRUCT T_UINT32_WRITE { uint32_t v; }; 114 | #define __UNALIGNED_UINT32_WRITE(addr, val) (void)((((struct T_UINT32_WRITE *)(void *)(addr))->v) = (val)) 115 | #endif 116 | #ifndef __UNALIGNED_UINT32_READ 117 | __PACKED_STRUCT T_UINT32_READ { uint32_t v; }; 118 | #define __UNALIGNED_UINT32_READ(addr) (((const struct T_UINT32_READ *)(const void *)(addr))->v) 119 | #endif 120 | #ifndef __ALIGNED 121 | #define __ALIGNED(x) __attribute__((aligned(x))) 122 | #endif 123 | #ifndef __RESTRICT 124 | #define __RESTRICT __restrict 125 | #endif 126 | #ifndef __COMPILER_BARRIER 127 | #warning No compiler specific solution for __COMPILER_BARRIER. __COMPILER_BARRIER is ignored. 128 | #define __COMPILER_BARRIER() (void)0 129 | #endif 130 | 131 | 132 | /* 133 | * TASKING Compiler 134 | */ 135 | #elif defined ( __TASKING__ ) 136 | /* 137 | * The CMSIS functions have been implemented as intrinsics in the compiler. 138 | * Please use "carm -?i" to get an up to date list of all intrinsics, 139 | * Including the CMSIS ones. 140 | */ 141 | 142 | #ifndef __ASM 143 | #define __ASM __asm 144 | #endif 145 | #ifndef __INLINE 146 | #define __INLINE inline 147 | #endif 148 | #ifndef __STATIC_INLINE 149 | #define __STATIC_INLINE static inline 150 | #endif 151 | #ifndef __STATIC_FORCEINLINE 152 | #define __STATIC_FORCEINLINE __STATIC_INLINE 153 | #endif 154 | #ifndef __NO_RETURN 155 | #define __NO_RETURN __attribute__((noreturn)) 156 | #endif 157 | #ifndef __USED 158 | #define __USED __attribute__((used)) 159 | #endif 160 | #ifndef __WEAK 161 | #define __WEAK __attribute__((weak)) 162 | #endif 163 | #ifndef __PACKED 164 | #define __PACKED __packed__ 165 | #endif 166 | #ifndef __PACKED_STRUCT 167 | #define __PACKED_STRUCT struct __packed__ 168 | #endif 169 | #ifndef __PACKED_UNION 170 | #define __PACKED_UNION union __packed__ 171 | #endif 172 | #ifndef __UNALIGNED_UINT32 /* deprecated */ 173 | struct __packed__ T_UINT32 { uint32_t v; }; 174 | #define __UNALIGNED_UINT32(x) (((struct T_UINT32 *)(x))->v) 175 | #endif 176 | #ifndef __UNALIGNED_UINT16_WRITE 177 | __PACKED_STRUCT T_UINT16_WRITE { uint16_t v; }; 178 | #define __UNALIGNED_UINT16_WRITE(addr, val) (void)((((struct T_UINT16_WRITE *)(void *)(addr))->v) = (val)) 179 | #endif 180 | #ifndef __UNALIGNED_UINT16_READ 181 | __PACKED_STRUCT T_UINT16_READ { uint16_t v; }; 182 | #define __UNALIGNED_UINT16_READ(addr) (((const struct T_UINT16_READ *)(const void *)(addr))->v) 183 | #endif 184 | #ifndef __UNALIGNED_UINT32_WRITE 185 | __PACKED_STRUCT T_UINT32_WRITE { uint32_t v; }; 186 | #define __UNALIGNED_UINT32_WRITE(addr, val) (void)((((struct T_UINT32_WRITE *)(void *)(addr))->v) = (val)) 187 | #endif 188 | #ifndef __UNALIGNED_UINT32_READ 189 | __PACKED_STRUCT T_UINT32_READ { uint32_t v; }; 190 | #define __UNALIGNED_UINT32_READ(addr) (((const struct T_UINT32_READ *)(const void *)(addr))->v) 191 | #endif 192 | #ifndef __ALIGNED 193 | #define __ALIGNED(x) __align(x) 194 | #endif 195 | #ifndef __RESTRICT 196 | #warning No compiler specific solution for __RESTRICT. __RESTRICT is ignored. 197 | #define __RESTRICT 198 | #endif 199 | #ifndef __COMPILER_BARRIER 200 | #warning No compiler specific solution for __COMPILER_BARRIER. __COMPILER_BARRIER is ignored. 201 | #define __COMPILER_BARRIER() (void)0 202 | #endif 203 | 204 | 205 | /* 206 | * COSMIC Compiler 207 | */ 208 | #elif defined ( __CSMC__ ) 209 | #include 210 | 211 | #ifndef __ASM 212 | #define __ASM _asm 213 | #endif 214 | #ifndef __INLINE 215 | #define __INLINE inline 216 | #endif 217 | #ifndef __STATIC_INLINE 218 | #define __STATIC_INLINE static inline 219 | #endif 220 | #ifndef __STATIC_FORCEINLINE 221 | #define __STATIC_FORCEINLINE __STATIC_INLINE 222 | #endif 223 | #ifndef __NO_RETURN 224 | // NO RETURN is automatically detected hence no warning here 225 | #define __NO_RETURN 226 | #endif 227 | #ifndef __USED 228 | #warning No compiler specific solution for __USED. __USED is ignored. 229 | #define __USED 230 | #endif 231 | #ifndef __WEAK 232 | #define __WEAK __weak 233 | #endif 234 | #ifndef __PACKED 235 | #define __PACKED @packed 236 | #endif 237 | #ifndef __PACKED_STRUCT 238 | #define __PACKED_STRUCT @packed struct 239 | #endif 240 | #ifndef __PACKED_UNION 241 | #define __PACKED_UNION @packed union 242 | #endif 243 | #ifndef __UNALIGNED_UINT32 /* deprecated */ 244 | @packed struct T_UINT32 { uint32_t v; }; 245 | #define __UNALIGNED_UINT32(x) (((struct T_UINT32 *)(x))->v) 246 | #endif 247 | #ifndef __UNALIGNED_UINT16_WRITE 248 | __PACKED_STRUCT T_UINT16_WRITE { uint16_t v; }; 249 | #define __UNALIGNED_UINT16_WRITE(addr, val) (void)((((struct T_UINT16_WRITE *)(void *)(addr))->v) = (val)) 250 | #endif 251 | #ifndef __UNALIGNED_UINT16_READ 252 | __PACKED_STRUCT T_UINT16_READ { uint16_t v; }; 253 | #define __UNALIGNED_UINT16_READ(addr) (((const struct T_UINT16_READ *)(const void *)(addr))->v) 254 | #endif 255 | #ifndef __UNALIGNED_UINT32_WRITE 256 | __PACKED_STRUCT T_UINT32_WRITE { uint32_t v; }; 257 | #define __UNALIGNED_UINT32_WRITE(addr, val) (void)((((struct T_UINT32_WRITE *)(void *)(addr))->v) = (val)) 258 | #endif 259 | #ifndef __UNALIGNED_UINT32_READ 260 | __PACKED_STRUCT T_UINT32_READ { uint32_t v; }; 261 | #define __UNALIGNED_UINT32_READ(addr) (((const struct T_UINT32_READ *)(const void *)(addr))->v) 262 | #endif 263 | #ifndef __ALIGNED 264 | #warning No compiler specific solution for __ALIGNED. __ALIGNED is ignored. 265 | #define __ALIGNED(x) 266 | #endif 267 | #ifndef __RESTRICT 268 | #warning No compiler specific solution for __RESTRICT. __RESTRICT is ignored. 269 | #define __RESTRICT 270 | #endif 271 | #ifndef __COMPILER_BARRIER 272 | #warning No compiler specific solution for __COMPILER_BARRIER. __COMPILER_BARRIER is ignored. 273 | #define __COMPILER_BARRIER() (void)0 274 | #endif 275 | 276 | 277 | #else 278 | #error Unknown compiler. 279 | #endif 280 | 281 | 282 | #endif /* __CMSIS_COMPILER_H */ 283 | 284 | -------------------------------------------------------------------------------- /cmsis/cmsis_gcc.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************//** 2 | * @file cmsis_gcc.h 3 | * @brief CMSIS compiler GCC header file 4 | * @version V5.2.0 5 | * @date 08. May 2019 6 | ******************************************************************************/ 7 | /* 8 | * Copyright (c) 2009-2019 Arm Limited. All rights reserved. 9 | * 10 | * SPDX-License-Identifier: Apache-2.0 11 | * 12 | * Licensed under the Apache License, Version 2.0 (the License); you may 13 | * not use this file except in compliance with the License. 14 | * You may obtain a copy of the License at 15 | * 16 | * www.apache.org/licenses/LICENSE-2.0 17 | * 18 | * Unless required by applicable law or agreed to in writing, software 19 | * distributed under the License is distributed on an AS IS BASIS, WITHOUT 20 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 21 | * See the License for the specific language governing permissions and 22 | * limitations under the License. 23 | */ 24 | 25 | #ifndef __CMSIS_GCC_H 26 | #define __CMSIS_GCC_H 27 | 28 | /* ignore some GCC warnings */ 29 | #pragma GCC diagnostic push 30 | #pragma GCC diagnostic ignored "-Wsign-conversion" 31 | #pragma GCC diagnostic ignored "-Wconversion" 32 | #pragma GCC diagnostic ignored "-Wunused-parameter" 33 | 34 | /* Fallback for __has_builtin */ 35 | #ifndef __has_builtin 36 | #define __has_builtin(x) (0) 37 | #endif 38 | 39 | /* CMSIS compiler specific defines */ 40 | #ifndef __ASM 41 | #define __ASM __asm 42 | #endif 43 | #ifndef __INLINE 44 | #define __INLINE inline 45 | #endif 46 | #ifndef __STATIC_INLINE 47 | #define __STATIC_INLINE static inline 48 | #endif 49 | #ifndef __STATIC_FORCEINLINE 50 | #define __STATIC_FORCEINLINE __attribute__((always_inline)) static inline 51 | #endif 52 | #ifndef __NO_RETURN 53 | #define __NO_RETURN __attribute__((__noreturn__)) 54 | #endif 55 | #ifndef __USED 56 | #define __USED __attribute__((used)) 57 | #endif 58 | #ifndef __WEAK 59 | #define __WEAK __attribute__((weak)) 60 | #endif 61 | #ifndef __PACKED 62 | #define __PACKED __attribute__((packed, aligned(1))) 63 | #endif 64 | #ifndef __PACKED_STRUCT 65 | #define __PACKED_STRUCT struct __attribute__((packed, aligned(1))) 66 | #endif 67 | #ifndef __PACKED_UNION 68 | #define __PACKED_UNION union __attribute__((packed, aligned(1))) 69 | #endif 70 | #ifndef __UNALIGNED_UINT32 /* deprecated */ 71 | #pragma GCC diagnostic push 72 | #pragma GCC diagnostic ignored "-Wpacked" 73 | #pragma GCC diagnostic ignored "-Wattributes" 74 | struct __attribute__((packed)) T_UINT32 { uint32_t v; }; 75 | #pragma GCC diagnostic pop 76 | #define __UNALIGNED_UINT32(x) (((struct T_UINT32 *)(x))->v) 77 | #endif 78 | #ifndef __UNALIGNED_UINT16_WRITE 79 | #pragma GCC diagnostic push 80 | #pragma GCC diagnostic ignored "-Wpacked" 81 | #pragma GCC diagnostic ignored "-Wattributes" 82 | __PACKED_STRUCT T_UINT16_WRITE { uint16_t v; }; 83 | #pragma GCC diagnostic pop 84 | #define __UNALIGNED_UINT16_WRITE(addr, val) (void)((((struct T_UINT16_WRITE *)(void *)(addr))->v) = (val)) 85 | #endif 86 | #ifndef __UNALIGNED_UINT16_READ 87 | #pragma GCC diagnostic push 88 | #pragma GCC diagnostic ignored "-Wpacked" 89 | #pragma GCC diagnostic ignored "-Wattributes" 90 | __PACKED_STRUCT T_UINT16_READ { uint16_t v; }; 91 | #pragma GCC diagnostic pop 92 | #define __UNALIGNED_UINT16_READ(addr) (((const struct T_UINT16_READ *)(const void *)(addr))->v) 93 | #endif 94 | #ifndef __UNALIGNED_UINT32_WRITE 95 | #pragma GCC diagnostic push 96 | #pragma GCC diagnostic ignored "-Wpacked" 97 | #pragma GCC diagnostic ignored "-Wattributes" 98 | __PACKED_STRUCT T_UINT32_WRITE { uint32_t v; }; 99 | #pragma GCC diagnostic pop 100 | #define __UNALIGNED_UINT32_WRITE(addr, val) (void)((((struct T_UINT32_WRITE *)(void *)(addr))->v) = (val)) 101 | #endif 102 | #ifndef __UNALIGNED_UINT32_READ 103 | #pragma GCC diagnostic push 104 | #pragma GCC diagnostic ignored "-Wpacked" 105 | #pragma GCC diagnostic ignored "-Wattributes" 106 | __PACKED_STRUCT T_UINT32_READ { uint32_t v; }; 107 | #pragma GCC diagnostic pop 108 | #define __UNALIGNED_UINT32_READ(addr) (((const struct T_UINT32_READ *)(const void *)(addr))->v) 109 | #endif 110 | #ifndef __ALIGNED 111 | #define __ALIGNED(x) __attribute__((aligned(x))) 112 | #endif 113 | #ifndef __RESTRICT 114 | #define __RESTRICT __restrict 115 | #endif 116 | #ifndef __COMPILER_BARRIER 117 | #define __COMPILER_BARRIER() __ASM volatile("":::"memory") 118 | #endif 119 | 120 | /* ######################### Startup and Lowlevel Init ######################## */ 121 | 122 | #ifndef __PROGRAM_START 123 | 124 | /** 125 | \brief Initializes data and bss sections 126 | \details This default implementations initialized all data and additional bss 127 | sections relying on .copy.table and .zero.table specified properly 128 | in the used linker script. 129 | 130 | */ 131 | __STATIC_FORCEINLINE __NO_RETURN void __cmsis_start(void) 132 | { 133 | extern void _start(void) __NO_RETURN; 134 | 135 | typedef struct { 136 | uint32_t const* src; 137 | uint32_t* dest; 138 | uint32_t wlen; 139 | } __copy_table_t; 140 | 141 | typedef struct { 142 | uint32_t* dest; 143 | uint32_t wlen; 144 | } __zero_table_t; 145 | 146 | extern const __copy_table_t __copy_table_start__; 147 | extern const __copy_table_t __copy_table_end__; 148 | extern const __zero_table_t __zero_table_start__; 149 | extern const __zero_table_t __zero_table_end__; 150 | 151 | for (__copy_table_t const* pTable = &__copy_table_start__; pTable < &__copy_table_end__; ++pTable) { 152 | for(uint32_t i=0u; iwlen; ++i) { 153 | pTable->dest[i] = pTable->src[i]; 154 | } 155 | } 156 | 157 | for (__zero_table_t const* pTable = &__zero_table_start__; pTable < &__zero_table_end__; ++pTable) { 158 | for(uint32_t i=0u; iwlen; ++i) { 159 | pTable->dest[i] = 0u; 160 | } 161 | } 162 | 163 | _start(); 164 | } 165 | 166 | #define __PROGRAM_START __cmsis_start 167 | #endif 168 | 169 | #ifndef __INITIAL_SP 170 | #define __INITIAL_SP __StackTop 171 | #endif 172 | 173 | #ifndef __STACK_LIMIT 174 | #define __STACK_LIMIT __StackLimit 175 | #endif 176 | 177 | #ifndef __VECTOR_TABLE 178 | #define __VECTOR_TABLE __Vectors 179 | #endif 180 | 181 | #ifndef __VECTOR_TABLE_ATTRIBUTE 182 | #define __VECTOR_TABLE_ATTRIBUTE __attribute((used, section(".vectors"))) 183 | #endif 184 | 185 | /* ########################### Core Function Access ########################### */ 186 | /** \ingroup CMSIS_Core_FunctionInterface 187 | \defgroup CMSIS_Core_RegAccFunctions CMSIS Core Register Access Functions 188 | @{ 189 | */ 190 | 191 | /** 192 | \brief Enable IRQ Interrupts 193 | \details Enables IRQ interrupts by clearing the I-bit in the CPSR. 194 | Can only be executed in Privileged modes. 195 | */ 196 | __STATIC_FORCEINLINE void __enable_irq(void) 197 | { 198 | __ASM volatile ("cpsie i" : : : "memory"); 199 | } 200 | 201 | 202 | /** 203 | \brief Disable IRQ Interrupts 204 | \details Disables IRQ interrupts by setting the I-bit in the CPSR. 205 | Can only be executed in Privileged modes. 206 | */ 207 | __STATIC_FORCEINLINE void __disable_irq(void) 208 | { 209 | __ASM volatile ("cpsid i" : : : "memory"); 210 | } 211 | 212 | 213 | /** 214 | \brief Get Control Register 215 | \details Returns the content of the Control Register. 216 | \return Control Register value 217 | */ 218 | __STATIC_FORCEINLINE uint32_t __get_CONTROL(void) 219 | { 220 | uint32_t result; 221 | 222 | __ASM volatile ("MRS %0, control" : "=r" (result) ); 223 | return(result); 224 | } 225 | 226 | 227 | #if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) 228 | /** 229 | \brief Get Control Register (non-secure) 230 | \details Returns the content of the non-secure Control Register when in secure mode. 231 | \return non-secure Control Register value 232 | */ 233 | __STATIC_FORCEINLINE uint32_t __TZ_get_CONTROL_NS(void) 234 | { 235 | uint32_t result; 236 | 237 | __ASM volatile ("MRS %0, control_ns" : "=r" (result) ); 238 | return(result); 239 | } 240 | #endif 241 | 242 | 243 | /** 244 | \brief Set Control Register 245 | \details Writes the given value to the Control Register. 246 | \param [in] control Control Register value to set 247 | */ 248 | __STATIC_FORCEINLINE void __set_CONTROL(uint32_t control) 249 | { 250 | __ASM volatile ("MSR control, %0" : : "r" (control) : "memory"); 251 | } 252 | 253 | 254 | #if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) 255 | /** 256 | \brief Set Control Register (non-secure) 257 | \details Writes the given value to the non-secure Control Register when in secure state. 258 | \param [in] control Control Register value to set 259 | */ 260 | __STATIC_FORCEINLINE void __TZ_set_CONTROL_NS(uint32_t control) 261 | { 262 | __ASM volatile ("MSR control_ns, %0" : : "r" (control) : "memory"); 263 | } 264 | #endif 265 | 266 | 267 | /** 268 | \brief Get IPSR Register 269 | \details Returns the content of the IPSR Register. 270 | \return IPSR Register value 271 | */ 272 | __STATIC_FORCEINLINE uint32_t __get_IPSR(void) 273 | { 274 | uint32_t result; 275 | 276 | __ASM volatile ("MRS %0, ipsr" : "=r" (result) ); 277 | return(result); 278 | } 279 | 280 | 281 | /** 282 | \brief Get APSR Register 283 | \details Returns the content of the APSR Register. 284 | \return APSR Register value 285 | */ 286 | __STATIC_FORCEINLINE uint32_t __get_APSR(void) 287 | { 288 | uint32_t result; 289 | 290 | __ASM volatile ("MRS %0, apsr" : "=r" (result) ); 291 | return(result); 292 | } 293 | 294 | 295 | /** 296 | \brief Get xPSR Register 297 | \details Returns the content of the xPSR Register. 298 | \return xPSR Register value 299 | */ 300 | __STATIC_FORCEINLINE uint32_t __get_xPSR(void) 301 | { 302 | uint32_t result; 303 | 304 | __ASM volatile ("MRS %0, xpsr" : "=r" (result) ); 305 | return(result); 306 | } 307 | 308 | 309 | /** 310 | \brief Get Process Stack Pointer 311 | \details Returns the current value of the Process Stack Pointer (PSP). 312 | \return PSP Register value 313 | */ 314 | __STATIC_FORCEINLINE uint32_t __get_PSP(void) 315 | { 316 | uint32_t result; 317 | 318 | __ASM volatile ("MRS %0, psp" : "=r" (result) ); 319 | return(result); 320 | } 321 | 322 | 323 | #if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) 324 | /** 325 | \brief Get Process Stack Pointer (non-secure) 326 | \details Returns the current value of the non-secure Process Stack Pointer (PSP) when in secure state. 327 | \return PSP Register value 328 | */ 329 | __STATIC_FORCEINLINE uint32_t __TZ_get_PSP_NS(void) 330 | { 331 | uint32_t result; 332 | 333 | __ASM volatile ("MRS %0, psp_ns" : "=r" (result) ); 334 | return(result); 335 | } 336 | #endif 337 | 338 | 339 | /** 340 | \brief Set Process Stack Pointer 341 | \details Assigns the given value to the Process Stack Pointer (PSP). 342 | \param [in] topOfProcStack Process Stack Pointer value to set 343 | */ 344 | __STATIC_FORCEINLINE void __set_PSP(uint32_t topOfProcStack) 345 | { 346 | __ASM volatile ("MSR psp, %0" : : "r" (topOfProcStack) : ); 347 | } 348 | 349 | 350 | #if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) 351 | /** 352 | \brief Set Process Stack Pointer (non-secure) 353 | \details Assigns the given value to the non-secure Process Stack Pointer (PSP) when in secure state. 354 | \param [in] topOfProcStack Process Stack Pointer value to set 355 | */ 356 | __STATIC_FORCEINLINE void __TZ_set_PSP_NS(uint32_t topOfProcStack) 357 | { 358 | __ASM volatile ("MSR psp_ns, %0" : : "r" (topOfProcStack) : ); 359 | } 360 | #endif 361 | 362 | 363 | /** 364 | \brief Get Main Stack Pointer 365 | \details Returns the current value of the Main Stack Pointer (MSP). 366 | \return MSP Register value 367 | */ 368 | __STATIC_FORCEINLINE uint32_t __get_MSP(void) 369 | { 370 | uint32_t result; 371 | 372 | __ASM volatile ("MRS %0, msp" : "=r" (result) ); 373 | return(result); 374 | } 375 | 376 | 377 | #if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) 378 | /** 379 | \brief Get Main Stack Pointer (non-secure) 380 | \details Returns the current value of the non-secure Main Stack Pointer (MSP) when in secure state. 381 | \return MSP Register value 382 | */ 383 | __STATIC_FORCEINLINE uint32_t __TZ_get_MSP_NS(void) 384 | { 385 | uint32_t result; 386 | 387 | __ASM volatile ("MRS %0, msp_ns" : "=r" (result) ); 388 | return(result); 389 | } 390 | #endif 391 | 392 | 393 | /** 394 | \brief Set Main Stack Pointer 395 | \details Assigns the given value to the Main Stack Pointer (MSP). 396 | \param [in] topOfMainStack Main Stack Pointer value to set 397 | */ 398 | __STATIC_FORCEINLINE void __set_MSP(uint32_t topOfMainStack) 399 | { 400 | __ASM volatile ("MSR msp, %0" : : "r" (topOfMainStack) : ); 401 | } 402 | 403 | 404 | #if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) 405 | /** 406 | \brief Set Main Stack Pointer (non-secure) 407 | \details Assigns the given value to the non-secure Main Stack Pointer (MSP) when in secure state. 408 | \param [in] topOfMainStack Main Stack Pointer value to set 409 | */ 410 | __STATIC_FORCEINLINE void __TZ_set_MSP_NS(uint32_t topOfMainStack) 411 | { 412 | __ASM volatile ("MSR msp_ns, %0" : : "r" (topOfMainStack) : ); 413 | } 414 | #endif 415 | 416 | 417 | #if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) 418 | /** 419 | \brief Get Stack Pointer (non-secure) 420 | \details Returns the current value of the non-secure Stack Pointer (SP) when in secure state. 421 | \return SP Register value 422 | */ 423 | __STATIC_FORCEINLINE uint32_t __TZ_get_SP_NS(void) 424 | { 425 | uint32_t result; 426 | 427 | __ASM volatile ("MRS %0, sp_ns" : "=r" (result) ); 428 | return(result); 429 | } 430 | 431 | 432 | /** 433 | \brief Set Stack Pointer (non-secure) 434 | \details Assigns the given value to the non-secure Stack Pointer (SP) when in secure state. 435 | \param [in] topOfStack Stack Pointer value to set 436 | */ 437 | __STATIC_FORCEINLINE void __TZ_set_SP_NS(uint32_t topOfStack) 438 | { 439 | __ASM volatile ("MSR sp_ns, %0" : : "r" (topOfStack) : ); 440 | } 441 | #endif 442 | 443 | 444 | /** 445 | \brief Get Priority Mask 446 | \details Returns the current state of the priority mask bit from the Priority Mask Register. 447 | \return Priority Mask value 448 | */ 449 | __STATIC_FORCEINLINE uint32_t __get_PRIMASK(void) 450 | { 451 | uint32_t result; 452 | 453 | __ASM volatile ("MRS %0, primask" : "=r" (result) :: "memory"); 454 | return(result); 455 | } 456 | 457 | 458 | #if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) 459 | /** 460 | \brief Get Priority Mask (non-secure) 461 | \details Returns the current state of the non-secure priority mask bit from the Priority Mask Register when in secure state. 462 | \return Priority Mask value 463 | */ 464 | __STATIC_FORCEINLINE uint32_t __TZ_get_PRIMASK_NS(void) 465 | { 466 | uint32_t result; 467 | 468 | __ASM volatile ("MRS %0, primask_ns" : "=r" (result) :: "memory"); 469 | return(result); 470 | } 471 | #endif 472 | 473 | 474 | /** 475 | \brief Set Priority Mask 476 | \details Assigns the given value to the Priority Mask Register. 477 | \param [in] priMask Priority Mask 478 | */ 479 | __STATIC_FORCEINLINE void __set_PRIMASK(uint32_t priMask) 480 | { 481 | __ASM volatile ("MSR primask, %0" : : "r" (priMask) : "memory"); 482 | } 483 | 484 | 485 | #if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) 486 | /** 487 | \brief Set Priority Mask (non-secure) 488 | \details Assigns the given value to the non-secure Priority Mask Register when in secure state. 489 | \param [in] priMask Priority Mask 490 | */ 491 | __STATIC_FORCEINLINE void __TZ_set_PRIMASK_NS(uint32_t priMask) 492 | { 493 | __ASM volatile ("MSR primask_ns, %0" : : "r" (priMask) : "memory"); 494 | } 495 | #endif 496 | 497 | 498 | #if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ 499 | (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ 500 | (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) ) 501 | /** 502 | \brief Enable FIQ 503 | \details Enables FIQ interrupts by clearing the F-bit in the CPSR. 504 | Can only be executed in Privileged modes. 505 | */ 506 | __STATIC_FORCEINLINE void __enable_fault_irq(void) 507 | { 508 | __ASM volatile ("cpsie f" : : : "memory"); 509 | } 510 | 511 | 512 | /** 513 | \brief Disable FIQ 514 | \details Disables FIQ interrupts by setting the F-bit in the CPSR. 515 | Can only be executed in Privileged modes. 516 | */ 517 | __STATIC_FORCEINLINE void __disable_fault_irq(void) 518 | { 519 | __ASM volatile ("cpsid f" : : : "memory"); 520 | } 521 | 522 | 523 | /** 524 | \brief Get Base Priority 525 | \details Returns the current value of the Base Priority register. 526 | \return Base Priority register value 527 | */ 528 | __STATIC_FORCEINLINE uint32_t __get_BASEPRI(void) 529 | { 530 | uint32_t result; 531 | 532 | __ASM volatile ("MRS %0, basepri" : "=r" (result) ); 533 | return(result); 534 | } 535 | 536 | 537 | #if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) 538 | /** 539 | \brief Get Base Priority (non-secure) 540 | \details Returns the current value of the non-secure Base Priority register when in secure state. 541 | \return Base Priority register value 542 | */ 543 | __STATIC_FORCEINLINE uint32_t __TZ_get_BASEPRI_NS(void) 544 | { 545 | uint32_t result; 546 | 547 | __ASM volatile ("MRS %0, basepri_ns" : "=r" (result) ); 548 | return(result); 549 | } 550 | #endif 551 | 552 | 553 | /** 554 | \brief Set Base Priority 555 | \details Assigns the given value to the Base Priority register. 556 | \param [in] basePri Base Priority value to set 557 | */ 558 | __STATIC_FORCEINLINE void __set_BASEPRI(uint32_t basePri) 559 | { 560 | __ASM volatile ("MSR basepri, %0" : : "r" (basePri) : "memory"); 561 | } 562 | 563 | 564 | #if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) 565 | /** 566 | \brief Set Base Priority (non-secure) 567 | \details Assigns the given value to the non-secure Base Priority register when in secure state. 568 | \param [in] basePri Base Priority value to set 569 | */ 570 | __STATIC_FORCEINLINE void __TZ_set_BASEPRI_NS(uint32_t basePri) 571 | { 572 | __ASM volatile ("MSR basepri_ns, %0" : : "r" (basePri) : "memory"); 573 | } 574 | #endif 575 | 576 | 577 | /** 578 | \brief Set Base Priority with condition 579 | \details Assigns the given value to the Base Priority register only if BASEPRI masking is disabled, 580 | or the new value increases the BASEPRI priority level. 581 | \param [in] basePri Base Priority value to set 582 | */ 583 | __STATIC_FORCEINLINE void __set_BASEPRI_MAX(uint32_t basePri) 584 | { 585 | __ASM volatile ("MSR basepri_max, %0" : : "r" (basePri) : "memory"); 586 | } 587 | 588 | 589 | /** 590 | \brief Get Fault Mask 591 | \details Returns the current value of the Fault Mask register. 592 | \return Fault Mask register value 593 | */ 594 | __STATIC_FORCEINLINE uint32_t __get_FAULTMASK(void) 595 | { 596 | uint32_t result; 597 | 598 | __ASM volatile ("MRS %0, faultmask" : "=r" (result) ); 599 | return(result); 600 | } 601 | 602 | 603 | #if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) 604 | /** 605 | \brief Get Fault Mask (non-secure) 606 | \details Returns the current value of the non-secure Fault Mask register when in secure state. 607 | \return Fault Mask register value 608 | */ 609 | __STATIC_FORCEINLINE uint32_t __TZ_get_FAULTMASK_NS(void) 610 | { 611 | uint32_t result; 612 | 613 | __ASM volatile ("MRS %0, faultmask_ns" : "=r" (result) ); 614 | return(result); 615 | } 616 | #endif 617 | 618 | 619 | /** 620 | \brief Set Fault Mask 621 | \details Assigns the given value to the Fault Mask register. 622 | \param [in] faultMask Fault Mask value to set 623 | */ 624 | __STATIC_FORCEINLINE void __set_FAULTMASK(uint32_t faultMask) 625 | { 626 | __ASM volatile ("MSR faultmask, %0" : : "r" (faultMask) : "memory"); 627 | } 628 | 629 | 630 | #if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) 631 | /** 632 | \brief Set Fault Mask (non-secure) 633 | \details Assigns the given value to the non-secure Fault Mask register when in secure state. 634 | \param [in] faultMask Fault Mask value to set 635 | */ 636 | __STATIC_FORCEINLINE void __TZ_set_FAULTMASK_NS(uint32_t faultMask) 637 | { 638 | __ASM volatile ("MSR faultmask_ns, %0" : : "r" (faultMask) : "memory"); 639 | } 640 | #endif 641 | 642 | #endif /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ 643 | (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ 644 | (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) ) */ 645 | 646 | 647 | #if ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ 648 | (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) 649 | 650 | /** 651 | \brief Get Process Stack Pointer Limit 652 | Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure 653 | Stack Pointer Limit register hence zero is returned always in non-secure 654 | mode. 655 | 656 | \details Returns the current value of the Process Stack Pointer Limit (PSPLIM). 657 | \return PSPLIM Register value 658 | */ 659 | __STATIC_FORCEINLINE uint32_t __get_PSPLIM(void) 660 | { 661 | #if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ 662 | (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) 663 | // without main extensions, the non-secure PSPLIM is RAZ/WI 664 | return 0U; 665 | #else 666 | uint32_t result; 667 | __ASM volatile ("MRS %0, psplim" : "=r" (result) ); 668 | return result; 669 | #endif 670 | } 671 | 672 | #if (defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3)) 673 | /** 674 | \brief Get Process Stack Pointer Limit (non-secure) 675 | Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure 676 | Stack Pointer Limit register hence zero is returned always. 677 | 678 | \details Returns the current value of the non-secure Process Stack Pointer Limit (PSPLIM) when in secure state. 679 | \return PSPLIM Register value 680 | */ 681 | __STATIC_FORCEINLINE uint32_t __TZ_get_PSPLIM_NS(void) 682 | { 683 | #if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1))) 684 | // without main extensions, the non-secure PSPLIM is RAZ/WI 685 | return 0U; 686 | #else 687 | uint32_t result; 688 | __ASM volatile ("MRS %0, psplim_ns" : "=r" (result) ); 689 | return result; 690 | #endif 691 | } 692 | #endif 693 | 694 | 695 | /** 696 | \brief Set Process Stack Pointer Limit 697 | Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure 698 | Stack Pointer Limit register hence the write is silently ignored in non-secure 699 | mode. 700 | 701 | \details Assigns the given value to the Process Stack Pointer Limit (PSPLIM). 702 | \param [in] ProcStackPtrLimit Process Stack Pointer Limit value to set 703 | */ 704 | __STATIC_FORCEINLINE void __set_PSPLIM(uint32_t ProcStackPtrLimit) 705 | { 706 | #if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ 707 | (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) 708 | // without main extensions, the non-secure PSPLIM is RAZ/WI 709 | (void)ProcStackPtrLimit; 710 | #else 711 | __ASM volatile ("MSR psplim, %0" : : "r" (ProcStackPtrLimit)); 712 | #endif 713 | } 714 | 715 | 716 | #if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) 717 | /** 718 | \brief Set Process Stack Pointer (non-secure) 719 | Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure 720 | Stack Pointer Limit register hence the write is silently ignored. 721 | 722 | \details Assigns the given value to the non-secure Process Stack Pointer Limit (PSPLIM) when in secure state. 723 | \param [in] ProcStackPtrLimit Process Stack Pointer Limit value to set 724 | */ 725 | __STATIC_FORCEINLINE void __TZ_set_PSPLIM_NS(uint32_t ProcStackPtrLimit) 726 | { 727 | #if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1))) 728 | // without main extensions, the non-secure PSPLIM is RAZ/WI 729 | (void)ProcStackPtrLimit; 730 | #else 731 | __ASM volatile ("MSR psplim_ns, %0\n" : : "r" (ProcStackPtrLimit)); 732 | #endif 733 | } 734 | #endif 735 | 736 | 737 | /** 738 | \brief Get Main Stack Pointer Limit 739 | Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure 740 | Stack Pointer Limit register hence zero is returned always in non-secure 741 | mode. 742 | 743 | \details Returns the current value of the Main Stack Pointer Limit (MSPLIM). 744 | \return MSPLIM Register value 745 | */ 746 | __STATIC_FORCEINLINE uint32_t __get_MSPLIM(void) 747 | { 748 | #if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ 749 | (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) 750 | // without main extensions, the non-secure MSPLIM is RAZ/WI 751 | return 0U; 752 | #else 753 | uint32_t result; 754 | __ASM volatile ("MRS %0, msplim" : "=r" (result) ); 755 | return result; 756 | #endif 757 | } 758 | 759 | 760 | #if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) 761 | /** 762 | \brief Get Main Stack Pointer Limit (non-secure) 763 | Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure 764 | Stack Pointer Limit register hence zero is returned always. 765 | 766 | \details Returns the current value of the non-secure Main Stack Pointer Limit(MSPLIM) when in secure state. 767 | \return MSPLIM Register value 768 | */ 769 | __STATIC_FORCEINLINE uint32_t __TZ_get_MSPLIM_NS(void) 770 | { 771 | #if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1))) 772 | // without main extensions, the non-secure MSPLIM is RAZ/WI 773 | return 0U; 774 | #else 775 | uint32_t result; 776 | __ASM volatile ("MRS %0, msplim_ns" : "=r" (result) ); 777 | return result; 778 | #endif 779 | } 780 | #endif 781 | 782 | 783 | /** 784 | \brief Set Main Stack Pointer Limit 785 | Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure 786 | Stack Pointer Limit register hence the write is silently ignored in non-secure 787 | mode. 788 | 789 | \details Assigns the given value to the Main Stack Pointer Limit (MSPLIM). 790 | \param [in] MainStackPtrLimit Main Stack Pointer Limit value to set 791 | */ 792 | __STATIC_FORCEINLINE void __set_MSPLIM(uint32_t MainStackPtrLimit) 793 | { 794 | #if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ 795 | (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) 796 | // without main extensions, the non-secure MSPLIM is RAZ/WI 797 | (void)MainStackPtrLimit; 798 | #else 799 | __ASM volatile ("MSR msplim, %0" : : "r" (MainStackPtrLimit)); 800 | #endif 801 | } 802 | 803 | 804 | #if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) 805 | /** 806 | \brief Set Main Stack Pointer Limit (non-secure) 807 | Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure 808 | Stack Pointer Limit register hence the write is silently ignored. 809 | 810 | \details Assigns the given value to the non-secure Main Stack Pointer Limit (MSPLIM) when in secure state. 811 | \param [in] MainStackPtrLimit Main Stack Pointer value to set 812 | */ 813 | __STATIC_FORCEINLINE void __TZ_set_MSPLIM_NS(uint32_t MainStackPtrLimit) 814 | { 815 | #if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1))) 816 | // without main extensions, the non-secure MSPLIM is RAZ/WI 817 | (void)MainStackPtrLimit; 818 | #else 819 | __ASM volatile ("MSR msplim_ns, %0" : : "r" (MainStackPtrLimit)); 820 | #endif 821 | } 822 | #endif 823 | 824 | #endif /* ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ 825 | (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) */ 826 | 827 | 828 | /** 829 | \brief Get FPSCR 830 | \details Returns the current value of the Floating Point Status/Control register. 831 | \return Floating Point Status/Control register value 832 | */ 833 | __STATIC_FORCEINLINE uint32_t __get_FPSCR(void) 834 | { 835 | #if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \ 836 | (defined (__FPU_USED ) && (__FPU_USED == 1U)) ) 837 | #if __has_builtin(__builtin_arm_get_fpscr) 838 | // Re-enable using built-in when GCC has been fixed 839 | // || (__GNUC__ > 7) || (__GNUC__ == 7 && __GNUC_MINOR__ >= 2) 840 | /* see https://gcc.gnu.org/ml/gcc-patches/2017-04/msg00443.html */ 841 | return __builtin_arm_get_fpscr(); 842 | #else 843 | uint32_t result; 844 | 845 | __ASM volatile ("VMRS %0, fpscr" : "=r" (result) ); 846 | return(result); 847 | #endif 848 | #else 849 | return(0U); 850 | #endif 851 | } 852 | 853 | 854 | /** 855 | \brief Set FPSCR 856 | \details Assigns the given value to the Floating Point Status/Control register. 857 | \param [in] fpscr Floating Point Status/Control value to set 858 | */ 859 | __STATIC_FORCEINLINE void __set_FPSCR(uint32_t fpscr) 860 | { 861 | #if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \ 862 | (defined (__FPU_USED ) && (__FPU_USED == 1U)) ) 863 | #if __has_builtin(__builtin_arm_set_fpscr) 864 | // Re-enable using built-in when GCC has been fixed 865 | // || (__GNUC__ > 7) || (__GNUC__ == 7 && __GNUC_MINOR__ >= 2) 866 | /* see https://gcc.gnu.org/ml/gcc-patches/2017-04/msg00443.html */ 867 | __builtin_arm_set_fpscr(fpscr); 868 | #else 869 | __ASM volatile ("VMSR fpscr, %0" : : "r" (fpscr) : "vfpcc", "memory"); 870 | #endif 871 | #else 872 | (void)fpscr; 873 | #endif 874 | } 875 | 876 | 877 | /*@} end of CMSIS_Core_RegAccFunctions */ 878 | 879 | 880 | /* ########################## Core Instruction Access ######################### */ 881 | /** \defgroup CMSIS_Core_InstructionInterface CMSIS Core Instruction Interface 882 | Access to dedicated instructions 883 | @{ 884 | */ 885 | 886 | /* Define macros for porting to both thumb1 and thumb2. 887 | * For thumb1, use low register (r0-r7), specified by constraint "l" 888 | * Otherwise, use general registers, specified by constraint "r" */ 889 | #if defined (__thumb__) && !defined (__thumb2__) 890 | #define __CMSIS_GCC_OUT_REG(r) "=l" (r) 891 | #define __CMSIS_GCC_RW_REG(r) "+l" (r) 892 | #define __CMSIS_GCC_USE_REG(r) "l" (r) 893 | #else 894 | #define __CMSIS_GCC_OUT_REG(r) "=r" (r) 895 | #define __CMSIS_GCC_RW_REG(r) "+r" (r) 896 | #define __CMSIS_GCC_USE_REG(r) "r" (r) 897 | #endif 898 | 899 | /** 900 | \brief No Operation 901 | \details No Operation does nothing. This instruction can be used for code alignment purposes. 902 | */ 903 | #define __NOP() __ASM volatile ("nop") 904 | 905 | /** 906 | \brief Wait For Interrupt 907 | \details Wait For Interrupt is a hint instruction that suspends execution until one of a number of events occurs. 908 | */ 909 | #define __WFI() __ASM volatile ("wfi") 910 | 911 | 912 | /** 913 | \brief Wait For Event 914 | \details Wait For Event is a hint instruction that permits the processor to enter 915 | a low-power state until one of a number of events occurs. 916 | */ 917 | #define __WFE() __ASM volatile ("wfe") 918 | 919 | 920 | /** 921 | \brief Send Event 922 | \details Send Event is a hint instruction. It causes an event to be signaled to the CPU. 923 | */ 924 | #define __SEV() __ASM volatile ("sev") 925 | 926 | 927 | /** 928 | \brief Instruction Synchronization Barrier 929 | \details Instruction Synchronization Barrier flushes the pipeline in the processor, 930 | so that all instructions following the ISB are fetched from cache or memory, 931 | after the instruction has been completed. 932 | */ 933 | __STATIC_FORCEINLINE void __ISB(void) 934 | { 935 | __ASM volatile ("isb 0xF":::"memory"); 936 | } 937 | 938 | 939 | /** 940 | \brief Data Synchronization Barrier 941 | \details Acts as a special kind of Data Memory Barrier. 942 | It completes when all explicit memory accesses before this instruction complete. 943 | */ 944 | __STATIC_FORCEINLINE void __DSB(void) 945 | { 946 | __ASM volatile ("dsb 0xF":::"memory"); 947 | } 948 | 949 | 950 | /** 951 | \brief Data Memory Barrier 952 | \details Ensures the apparent order of the explicit memory operations before 953 | and after the instruction, without ensuring their completion. 954 | */ 955 | __STATIC_FORCEINLINE void __DMB(void) 956 | { 957 | __ASM volatile ("dmb 0xF":::"memory"); 958 | } 959 | 960 | 961 | /** 962 | \brief Reverse byte order (32 bit) 963 | \details Reverses the byte order in unsigned integer value. For example, 0x12345678 becomes 0x78563412. 964 | \param [in] value Value to reverse 965 | \return Reversed value 966 | */ 967 | __STATIC_FORCEINLINE uint32_t __REV(uint32_t value) 968 | { 969 | #if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5) 970 | return __builtin_bswap32(value); 971 | #else 972 | uint32_t result; 973 | 974 | __ASM volatile ("rev %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) ); 975 | return result; 976 | #endif 977 | } 978 | 979 | 980 | /** 981 | \brief Reverse byte order (16 bit) 982 | \details Reverses the byte order within each halfword of a word. For example, 0x12345678 becomes 0x34127856. 983 | \param [in] value Value to reverse 984 | \return Reversed value 985 | */ 986 | __STATIC_FORCEINLINE uint32_t __REV16(uint32_t value) 987 | { 988 | uint32_t result; 989 | 990 | __ASM volatile ("rev16 %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) ); 991 | return result; 992 | } 993 | 994 | 995 | /** 996 | \brief Reverse byte order (16 bit) 997 | \details Reverses the byte order in a 16-bit value and returns the signed 16-bit result. For example, 0x0080 becomes 0x8000. 998 | \param [in] value Value to reverse 999 | \return Reversed value 1000 | */ 1001 | __STATIC_FORCEINLINE int16_t __REVSH(int16_t value) 1002 | { 1003 | #if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) 1004 | return (int16_t)__builtin_bswap16(value); 1005 | #else 1006 | int16_t result; 1007 | 1008 | __ASM volatile ("revsh %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) ); 1009 | return result; 1010 | #endif 1011 | } 1012 | 1013 | 1014 | /** 1015 | \brief Rotate Right in unsigned value (32 bit) 1016 | \details Rotate Right (immediate) provides the value of the contents of a register rotated by a variable number of bits. 1017 | \param [in] op1 Value to rotate 1018 | \param [in] op2 Number of Bits to rotate 1019 | \return Rotated value 1020 | */ 1021 | __STATIC_FORCEINLINE uint32_t __ROR(uint32_t op1, uint32_t op2) 1022 | { 1023 | op2 %= 32U; 1024 | if (op2 == 0U) 1025 | { 1026 | return op1; 1027 | } 1028 | return (op1 >> op2) | (op1 << (32U - op2)); 1029 | } 1030 | 1031 | 1032 | /** 1033 | \brief Breakpoint 1034 | \details Causes the processor to enter Debug state. 1035 | Debug tools can use this to investigate system state when the instruction at a particular address is reached. 1036 | \param [in] value is ignored by the processor. 1037 | If required, a debugger can use it to store additional information about the breakpoint. 1038 | */ 1039 | #define __BKPT(value) __ASM volatile ("bkpt "#value) 1040 | 1041 | 1042 | /** 1043 | \brief Reverse bit order of value 1044 | \details Reverses the bit order of the given value. 1045 | \param [in] value Value to reverse 1046 | \return Reversed value 1047 | */ 1048 | __STATIC_FORCEINLINE uint32_t __RBIT(uint32_t value) 1049 | { 1050 | uint32_t result; 1051 | 1052 | #if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ 1053 | (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ 1054 | (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) ) 1055 | __ASM volatile ("rbit %0, %1" : "=r" (result) : "r" (value) ); 1056 | #else 1057 | uint32_t s = (4U /*sizeof(v)*/ * 8U) - 1U; /* extra shift needed at end */ 1058 | 1059 | result = value; /* r will be reversed bits of v; first get LSB of v */ 1060 | for (value >>= 1U; value != 0U; value >>= 1U) 1061 | { 1062 | result <<= 1U; 1063 | result |= value & 1U; 1064 | s--; 1065 | } 1066 | result <<= s; /* shift when v's highest bits are zero */ 1067 | #endif 1068 | return result; 1069 | } 1070 | 1071 | 1072 | /** 1073 | \brief Count leading zeros 1074 | \details Counts the number of leading zeros of a data value. 1075 | \param [in] value Value to count the leading zeros 1076 | \return number of leading zeros in value 1077 | */ 1078 | __STATIC_FORCEINLINE uint8_t __CLZ(uint32_t value) 1079 | { 1080 | /* Even though __builtin_clz produces a CLZ instruction on ARM, formally 1081 | __builtin_clz(0) is undefined behaviour, so handle this case specially. 1082 | This guarantees ARM-compatible results if happening to compile on a non-ARM 1083 | target, and ensures the compiler doesn't decide to activate any 1084 | optimisations using the logic "value was passed to __builtin_clz, so it 1085 | is non-zero". 1086 | ARM GCC 7.3 and possibly earlier will optimise this test away, leaving a 1087 | single CLZ instruction. 1088 | */ 1089 | if (value == 0U) 1090 | { 1091 | return 32U; 1092 | } 1093 | return __builtin_clz(value); 1094 | } 1095 | 1096 | 1097 | #if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ 1098 | (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ 1099 | (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ 1100 | (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) 1101 | /** 1102 | \brief LDR Exclusive (8 bit) 1103 | \details Executes a exclusive LDR instruction for 8 bit value. 1104 | \param [in] ptr Pointer to data 1105 | \return value of type uint8_t at (*ptr) 1106 | */ 1107 | __STATIC_FORCEINLINE uint8_t __LDREXB(volatile uint8_t *addr) 1108 | { 1109 | uint32_t result; 1110 | 1111 | #if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) 1112 | __ASM volatile ("ldrexb %0, %1" : "=r" (result) : "Q" (*addr) ); 1113 | #else 1114 | /* Prior to GCC 4.8, "Q" will be expanded to [rx, #0] which is not 1115 | accepted by assembler. So has to use following less efficient pattern. 1116 | */ 1117 | __ASM volatile ("ldrexb %0, [%1]" : "=r" (result) : "r" (addr) : "memory" ); 1118 | #endif 1119 | return ((uint8_t) result); /* Add explicit type cast here */ 1120 | } 1121 | 1122 | 1123 | /** 1124 | \brief LDR Exclusive (16 bit) 1125 | \details Executes a exclusive LDR instruction for 16 bit values. 1126 | \param [in] ptr Pointer to data 1127 | \return value of type uint16_t at (*ptr) 1128 | */ 1129 | __STATIC_FORCEINLINE uint16_t __LDREXH(volatile uint16_t *addr) 1130 | { 1131 | uint32_t result; 1132 | 1133 | #if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) 1134 | __ASM volatile ("ldrexh %0, %1" : "=r" (result) : "Q" (*addr) ); 1135 | #else 1136 | /* Prior to GCC 4.8, "Q" will be expanded to [rx, #0] which is not 1137 | accepted by assembler. So has to use following less efficient pattern. 1138 | */ 1139 | __ASM volatile ("ldrexh %0, [%1]" : "=r" (result) : "r" (addr) : "memory" ); 1140 | #endif 1141 | return ((uint16_t) result); /* Add explicit type cast here */ 1142 | } 1143 | 1144 | 1145 | /** 1146 | \brief LDR Exclusive (32 bit) 1147 | \details Executes a exclusive LDR instruction for 32 bit values. 1148 | \param [in] ptr Pointer to data 1149 | \return value of type uint32_t at (*ptr) 1150 | */ 1151 | __STATIC_FORCEINLINE uint32_t __LDREXW(volatile uint32_t *addr) 1152 | { 1153 | uint32_t result; 1154 | 1155 | __ASM volatile ("ldrex %0, %1" : "=r" (result) : "Q" (*addr) ); 1156 | return(result); 1157 | } 1158 | 1159 | 1160 | /** 1161 | \brief STR Exclusive (8 bit) 1162 | \details Executes a exclusive STR instruction for 8 bit values. 1163 | \param [in] value Value to store 1164 | \param [in] ptr Pointer to location 1165 | \return 0 Function succeeded 1166 | \return 1 Function failed 1167 | */ 1168 | __STATIC_FORCEINLINE uint32_t __STREXB(uint8_t value, volatile uint8_t *addr) 1169 | { 1170 | uint32_t result; 1171 | 1172 | __ASM volatile ("strexb %0, %2, %1" : "=&r" (result), "=Q" (*addr) : "r" ((uint32_t)value) ); 1173 | return(result); 1174 | } 1175 | 1176 | 1177 | /** 1178 | \brief STR Exclusive (16 bit) 1179 | \details Executes a exclusive STR instruction for 16 bit values. 1180 | \param [in] value Value to store 1181 | \param [in] ptr Pointer to location 1182 | \return 0 Function succeeded 1183 | \return 1 Function failed 1184 | */ 1185 | __STATIC_FORCEINLINE uint32_t __STREXH(uint16_t value, volatile uint16_t *addr) 1186 | { 1187 | uint32_t result; 1188 | 1189 | __ASM volatile ("strexh %0, %2, %1" : "=&r" (result), "=Q" (*addr) : "r" ((uint32_t)value) ); 1190 | return(result); 1191 | } 1192 | 1193 | 1194 | /** 1195 | \brief STR Exclusive (32 bit) 1196 | \details Executes a exclusive STR instruction for 32 bit values. 1197 | \param [in] value Value to store 1198 | \param [in] ptr Pointer to location 1199 | \return 0 Function succeeded 1200 | \return 1 Function failed 1201 | */ 1202 | __STATIC_FORCEINLINE uint32_t __STREXW(uint32_t value, volatile uint32_t *addr) 1203 | { 1204 | uint32_t result; 1205 | 1206 | __ASM volatile ("strex %0, %2, %1" : "=&r" (result), "=Q" (*addr) : "r" (value) ); 1207 | return(result); 1208 | } 1209 | 1210 | 1211 | /** 1212 | \brief Remove the exclusive lock 1213 | \details Removes the exclusive lock which is created by LDREX. 1214 | */ 1215 | __STATIC_FORCEINLINE void __CLREX(void) 1216 | { 1217 | __ASM volatile ("clrex" ::: "memory"); 1218 | } 1219 | 1220 | #endif /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ 1221 | (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ 1222 | (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ 1223 | (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) */ 1224 | 1225 | 1226 | #if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ 1227 | (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ 1228 | (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) ) 1229 | /** 1230 | \brief Signed Saturate 1231 | \details Saturates a signed value. 1232 | \param [in] ARG1 Value to be saturated 1233 | \param [in] ARG2 Bit position to saturate to (1..32) 1234 | \return Saturated value 1235 | */ 1236 | #define __SSAT(ARG1,ARG2) \ 1237 | __extension__ \ 1238 | ({ \ 1239 | int32_t __RES, __ARG1 = (ARG1); \ 1240 | __ASM ("ssat %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ 1241 | __RES; \ 1242 | }) 1243 | 1244 | 1245 | /** 1246 | \brief Unsigned Saturate 1247 | \details Saturates an unsigned value. 1248 | \param [in] ARG1 Value to be saturated 1249 | \param [in] ARG2 Bit position to saturate to (0..31) 1250 | \return Saturated value 1251 | */ 1252 | #define __USAT(ARG1,ARG2) \ 1253 | __extension__ \ 1254 | ({ \ 1255 | uint32_t __RES, __ARG1 = (ARG1); \ 1256 | __ASM ("usat %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ 1257 | __RES; \ 1258 | }) 1259 | 1260 | 1261 | /** 1262 | \brief Rotate Right with Extend (32 bit) 1263 | \details Moves each bit of a bitstring right by one bit. 1264 | The carry input is shifted in at the left end of the bitstring. 1265 | \param [in] value Value to rotate 1266 | \return Rotated value 1267 | */ 1268 | __STATIC_FORCEINLINE uint32_t __RRX(uint32_t value) 1269 | { 1270 | uint32_t result; 1271 | 1272 | __ASM volatile ("rrx %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) ); 1273 | return(result); 1274 | } 1275 | 1276 | 1277 | /** 1278 | \brief LDRT Unprivileged (8 bit) 1279 | \details Executes a Unprivileged LDRT instruction for 8 bit value. 1280 | \param [in] ptr Pointer to data 1281 | \return value of type uint8_t at (*ptr) 1282 | */ 1283 | __STATIC_FORCEINLINE uint8_t __LDRBT(volatile uint8_t *ptr) 1284 | { 1285 | uint32_t result; 1286 | 1287 | #if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) 1288 | __ASM volatile ("ldrbt %0, %1" : "=r" (result) : "Q" (*ptr) ); 1289 | #else 1290 | /* Prior to GCC 4.8, "Q" will be expanded to [rx, #0] which is not 1291 | accepted by assembler. So has to use following less efficient pattern. 1292 | */ 1293 | __ASM volatile ("ldrbt %0, [%1]" : "=r" (result) : "r" (ptr) : "memory" ); 1294 | #endif 1295 | return ((uint8_t) result); /* Add explicit type cast here */ 1296 | } 1297 | 1298 | 1299 | /** 1300 | \brief LDRT Unprivileged (16 bit) 1301 | \details Executes a Unprivileged LDRT instruction for 16 bit values. 1302 | \param [in] ptr Pointer to data 1303 | \return value of type uint16_t at (*ptr) 1304 | */ 1305 | __STATIC_FORCEINLINE uint16_t __LDRHT(volatile uint16_t *ptr) 1306 | { 1307 | uint32_t result; 1308 | 1309 | #if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) 1310 | __ASM volatile ("ldrht %0, %1" : "=r" (result) : "Q" (*ptr) ); 1311 | #else 1312 | /* Prior to GCC 4.8, "Q" will be expanded to [rx, #0] which is not 1313 | accepted by assembler. So has to use following less efficient pattern. 1314 | */ 1315 | __ASM volatile ("ldrht %0, [%1]" : "=r" (result) : "r" (ptr) : "memory" ); 1316 | #endif 1317 | return ((uint16_t) result); /* Add explicit type cast here */ 1318 | } 1319 | 1320 | 1321 | /** 1322 | \brief LDRT Unprivileged (32 bit) 1323 | \details Executes a Unprivileged LDRT instruction for 32 bit values. 1324 | \param [in] ptr Pointer to data 1325 | \return value of type uint32_t at (*ptr) 1326 | */ 1327 | __STATIC_FORCEINLINE uint32_t __LDRT(volatile uint32_t *ptr) 1328 | { 1329 | uint32_t result; 1330 | 1331 | __ASM volatile ("ldrt %0, %1" : "=r" (result) : "Q" (*ptr) ); 1332 | return(result); 1333 | } 1334 | 1335 | 1336 | /** 1337 | \brief STRT Unprivileged (8 bit) 1338 | \details Executes a Unprivileged STRT instruction for 8 bit values. 1339 | \param [in] value Value to store 1340 | \param [in] ptr Pointer to location 1341 | */ 1342 | __STATIC_FORCEINLINE void __STRBT(uint8_t value, volatile uint8_t *ptr) 1343 | { 1344 | __ASM volatile ("strbt %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) ); 1345 | } 1346 | 1347 | 1348 | /** 1349 | \brief STRT Unprivileged (16 bit) 1350 | \details Executes a Unprivileged STRT instruction for 16 bit values. 1351 | \param [in] value Value to store 1352 | \param [in] ptr Pointer to location 1353 | */ 1354 | __STATIC_FORCEINLINE void __STRHT(uint16_t value, volatile uint16_t *ptr) 1355 | { 1356 | __ASM volatile ("strht %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) ); 1357 | } 1358 | 1359 | 1360 | /** 1361 | \brief STRT Unprivileged (32 bit) 1362 | \details Executes a Unprivileged STRT instruction for 32 bit values. 1363 | \param [in] value Value to store 1364 | \param [in] ptr Pointer to location 1365 | */ 1366 | __STATIC_FORCEINLINE void __STRT(uint32_t value, volatile uint32_t *ptr) 1367 | { 1368 | __ASM volatile ("strt %1, %0" : "=Q" (*ptr) : "r" (value) ); 1369 | } 1370 | 1371 | #else /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ 1372 | (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ 1373 | (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) ) */ 1374 | 1375 | /** 1376 | \brief Signed Saturate 1377 | \details Saturates a signed value. 1378 | \param [in] value Value to be saturated 1379 | \param [in] sat Bit position to saturate to (1..32) 1380 | \return Saturated value 1381 | */ 1382 | __STATIC_FORCEINLINE int32_t __SSAT(int32_t val, uint32_t sat) 1383 | { 1384 | if ((sat >= 1U) && (sat <= 32U)) 1385 | { 1386 | const int32_t max = (int32_t)((1U << (sat - 1U)) - 1U); 1387 | const int32_t min = -1 - max ; 1388 | if (val > max) 1389 | { 1390 | return max; 1391 | } 1392 | else if (val < min) 1393 | { 1394 | return min; 1395 | } 1396 | } 1397 | return val; 1398 | } 1399 | 1400 | /** 1401 | \brief Unsigned Saturate 1402 | \details Saturates an unsigned value. 1403 | \param [in] value Value to be saturated 1404 | \param [in] sat Bit position to saturate to (0..31) 1405 | \return Saturated value 1406 | */ 1407 | __STATIC_FORCEINLINE uint32_t __USAT(int32_t val, uint32_t sat) 1408 | { 1409 | if (sat <= 31U) 1410 | { 1411 | const uint32_t max = ((1U << sat) - 1U); 1412 | if (val > (int32_t)max) 1413 | { 1414 | return max; 1415 | } 1416 | else if (val < 0) 1417 | { 1418 | return 0U; 1419 | } 1420 | } 1421 | return (uint32_t)val; 1422 | } 1423 | 1424 | #endif /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ 1425 | (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ 1426 | (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) ) */ 1427 | 1428 | 1429 | #if ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ 1430 | (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) 1431 | /** 1432 | \brief Load-Acquire (8 bit) 1433 | \details Executes a LDAB instruction for 8 bit value. 1434 | \param [in] ptr Pointer to data 1435 | \return value of type uint8_t at (*ptr) 1436 | */ 1437 | __STATIC_FORCEINLINE uint8_t __LDAB(volatile uint8_t *ptr) 1438 | { 1439 | uint32_t result; 1440 | 1441 | __ASM volatile ("ldab %0, %1" : "=r" (result) : "Q" (*ptr) ); 1442 | return ((uint8_t) result); 1443 | } 1444 | 1445 | 1446 | /** 1447 | \brief Load-Acquire (16 bit) 1448 | \details Executes a LDAH instruction for 16 bit values. 1449 | \param [in] ptr Pointer to data 1450 | \return value of type uint16_t at (*ptr) 1451 | */ 1452 | __STATIC_FORCEINLINE uint16_t __LDAH(volatile uint16_t *ptr) 1453 | { 1454 | uint32_t result; 1455 | 1456 | __ASM volatile ("ldah %0, %1" : "=r" (result) : "Q" (*ptr) ); 1457 | return ((uint16_t) result); 1458 | } 1459 | 1460 | 1461 | /** 1462 | \brief Load-Acquire (32 bit) 1463 | \details Executes a LDA instruction for 32 bit values. 1464 | \param [in] ptr Pointer to data 1465 | \return value of type uint32_t at (*ptr) 1466 | */ 1467 | __STATIC_FORCEINLINE uint32_t __LDA(volatile uint32_t *ptr) 1468 | { 1469 | uint32_t result; 1470 | 1471 | __ASM volatile ("lda %0, %1" : "=r" (result) : "Q" (*ptr) ); 1472 | return(result); 1473 | } 1474 | 1475 | 1476 | /** 1477 | \brief Store-Release (8 bit) 1478 | \details Executes a STLB instruction for 8 bit values. 1479 | \param [in] value Value to store 1480 | \param [in] ptr Pointer to location 1481 | */ 1482 | __STATIC_FORCEINLINE void __STLB(uint8_t value, volatile uint8_t *ptr) 1483 | { 1484 | __ASM volatile ("stlb %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) ); 1485 | } 1486 | 1487 | 1488 | /** 1489 | \brief Store-Release (16 bit) 1490 | \details Executes a STLH instruction for 16 bit values. 1491 | \param [in] value Value to store 1492 | \param [in] ptr Pointer to location 1493 | */ 1494 | __STATIC_FORCEINLINE void __STLH(uint16_t value, volatile uint16_t *ptr) 1495 | { 1496 | __ASM volatile ("stlh %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) ); 1497 | } 1498 | 1499 | 1500 | /** 1501 | \brief Store-Release (32 bit) 1502 | \details Executes a STL instruction for 32 bit values. 1503 | \param [in] value Value to store 1504 | \param [in] ptr Pointer to location 1505 | */ 1506 | __STATIC_FORCEINLINE void __STL(uint32_t value, volatile uint32_t *ptr) 1507 | { 1508 | __ASM volatile ("stl %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) ); 1509 | } 1510 | 1511 | 1512 | /** 1513 | \brief Load-Acquire Exclusive (8 bit) 1514 | \details Executes a LDAB exclusive instruction for 8 bit value. 1515 | \param [in] ptr Pointer to data 1516 | \return value of type uint8_t at (*ptr) 1517 | */ 1518 | __STATIC_FORCEINLINE uint8_t __LDAEXB(volatile uint8_t *ptr) 1519 | { 1520 | uint32_t result; 1521 | 1522 | __ASM volatile ("ldaexb %0, %1" : "=r" (result) : "Q" (*ptr) ); 1523 | return ((uint8_t) result); 1524 | } 1525 | 1526 | 1527 | /** 1528 | \brief Load-Acquire Exclusive (16 bit) 1529 | \details Executes a LDAH exclusive instruction for 16 bit values. 1530 | \param [in] ptr Pointer to data 1531 | \return value of type uint16_t at (*ptr) 1532 | */ 1533 | __STATIC_FORCEINLINE uint16_t __LDAEXH(volatile uint16_t *ptr) 1534 | { 1535 | uint32_t result; 1536 | 1537 | __ASM volatile ("ldaexh %0, %1" : "=r" (result) : "Q" (*ptr) ); 1538 | return ((uint16_t) result); 1539 | } 1540 | 1541 | 1542 | /** 1543 | \brief Load-Acquire Exclusive (32 bit) 1544 | \details Executes a LDA exclusive instruction for 32 bit values. 1545 | \param [in] ptr Pointer to data 1546 | \return value of type uint32_t at (*ptr) 1547 | */ 1548 | __STATIC_FORCEINLINE uint32_t __LDAEX(volatile uint32_t *ptr) 1549 | { 1550 | uint32_t result; 1551 | 1552 | __ASM volatile ("ldaex %0, %1" : "=r" (result) : "Q" (*ptr) ); 1553 | return(result); 1554 | } 1555 | 1556 | 1557 | /** 1558 | \brief Store-Release Exclusive (8 bit) 1559 | \details Executes a STLB exclusive instruction for 8 bit values. 1560 | \param [in] value Value to store 1561 | \param [in] ptr Pointer to location 1562 | \return 0 Function succeeded 1563 | \return 1 Function failed 1564 | */ 1565 | __STATIC_FORCEINLINE uint32_t __STLEXB(uint8_t value, volatile uint8_t *ptr) 1566 | { 1567 | uint32_t result; 1568 | 1569 | __ASM volatile ("stlexb %0, %2, %1" : "=&r" (result), "=Q" (*ptr) : "r" ((uint32_t)value) ); 1570 | return(result); 1571 | } 1572 | 1573 | 1574 | /** 1575 | \brief Store-Release Exclusive (16 bit) 1576 | \details Executes a STLH exclusive instruction for 16 bit values. 1577 | \param [in] value Value to store 1578 | \param [in] ptr Pointer to location 1579 | \return 0 Function succeeded 1580 | \return 1 Function failed 1581 | */ 1582 | __STATIC_FORCEINLINE uint32_t __STLEXH(uint16_t value, volatile uint16_t *ptr) 1583 | { 1584 | uint32_t result; 1585 | 1586 | __ASM volatile ("stlexh %0, %2, %1" : "=&r" (result), "=Q" (*ptr) : "r" ((uint32_t)value) ); 1587 | return(result); 1588 | } 1589 | 1590 | 1591 | /** 1592 | \brief Store-Release Exclusive (32 bit) 1593 | \details Executes a STL exclusive instruction for 32 bit values. 1594 | \param [in] value Value to store 1595 | \param [in] ptr Pointer to location 1596 | \return 0 Function succeeded 1597 | \return 1 Function failed 1598 | */ 1599 | __STATIC_FORCEINLINE uint32_t __STLEX(uint32_t value, volatile uint32_t *ptr) 1600 | { 1601 | uint32_t result; 1602 | 1603 | __ASM volatile ("stlex %0, %2, %1" : "=&r" (result), "=Q" (*ptr) : "r" ((uint32_t)value) ); 1604 | return(result); 1605 | } 1606 | 1607 | #endif /* ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ 1608 | (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) */ 1609 | 1610 | /*@}*/ /* end of group CMSIS_Core_InstructionInterface */ 1611 | 1612 | 1613 | /* ################### Compiler specific Intrinsics ########################### */ 1614 | /** \defgroup CMSIS_SIMD_intrinsics CMSIS SIMD Intrinsics 1615 | Access to dedicated SIMD instructions 1616 | @{ 1617 | */ 1618 | 1619 | #if (defined (__ARM_FEATURE_DSP) && (__ARM_FEATURE_DSP == 1)) 1620 | 1621 | __STATIC_FORCEINLINE uint32_t __SADD8(uint32_t op1, uint32_t op2) 1622 | { 1623 | uint32_t result; 1624 | 1625 | __ASM volatile ("sadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1626 | return(result); 1627 | } 1628 | 1629 | __STATIC_FORCEINLINE uint32_t __QADD8(uint32_t op1, uint32_t op2) 1630 | { 1631 | uint32_t result; 1632 | 1633 | __ASM volatile ("qadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1634 | return(result); 1635 | } 1636 | 1637 | __STATIC_FORCEINLINE uint32_t __SHADD8(uint32_t op1, uint32_t op2) 1638 | { 1639 | uint32_t result; 1640 | 1641 | __ASM volatile ("shadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1642 | return(result); 1643 | } 1644 | 1645 | __STATIC_FORCEINLINE uint32_t __UADD8(uint32_t op1, uint32_t op2) 1646 | { 1647 | uint32_t result; 1648 | 1649 | __ASM volatile ("uadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1650 | return(result); 1651 | } 1652 | 1653 | __STATIC_FORCEINLINE uint32_t __UQADD8(uint32_t op1, uint32_t op2) 1654 | { 1655 | uint32_t result; 1656 | 1657 | __ASM volatile ("uqadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1658 | return(result); 1659 | } 1660 | 1661 | __STATIC_FORCEINLINE uint32_t __UHADD8(uint32_t op1, uint32_t op2) 1662 | { 1663 | uint32_t result; 1664 | 1665 | __ASM volatile ("uhadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1666 | return(result); 1667 | } 1668 | 1669 | 1670 | __STATIC_FORCEINLINE uint32_t __SSUB8(uint32_t op1, uint32_t op2) 1671 | { 1672 | uint32_t result; 1673 | 1674 | __ASM volatile ("ssub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1675 | return(result); 1676 | } 1677 | 1678 | __STATIC_FORCEINLINE uint32_t __QSUB8(uint32_t op1, uint32_t op2) 1679 | { 1680 | uint32_t result; 1681 | 1682 | __ASM volatile ("qsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1683 | return(result); 1684 | } 1685 | 1686 | __STATIC_FORCEINLINE uint32_t __SHSUB8(uint32_t op1, uint32_t op2) 1687 | { 1688 | uint32_t result; 1689 | 1690 | __ASM volatile ("shsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1691 | return(result); 1692 | } 1693 | 1694 | __STATIC_FORCEINLINE uint32_t __USUB8(uint32_t op1, uint32_t op2) 1695 | { 1696 | uint32_t result; 1697 | 1698 | __ASM volatile ("usub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1699 | return(result); 1700 | } 1701 | 1702 | __STATIC_FORCEINLINE uint32_t __UQSUB8(uint32_t op1, uint32_t op2) 1703 | { 1704 | uint32_t result; 1705 | 1706 | __ASM volatile ("uqsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1707 | return(result); 1708 | } 1709 | 1710 | __STATIC_FORCEINLINE uint32_t __UHSUB8(uint32_t op1, uint32_t op2) 1711 | { 1712 | uint32_t result; 1713 | 1714 | __ASM volatile ("uhsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1715 | return(result); 1716 | } 1717 | 1718 | 1719 | __STATIC_FORCEINLINE uint32_t __SADD16(uint32_t op1, uint32_t op2) 1720 | { 1721 | uint32_t result; 1722 | 1723 | __ASM volatile ("sadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1724 | return(result); 1725 | } 1726 | 1727 | __STATIC_FORCEINLINE uint32_t __QADD16(uint32_t op1, uint32_t op2) 1728 | { 1729 | uint32_t result; 1730 | 1731 | __ASM volatile ("qadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1732 | return(result); 1733 | } 1734 | 1735 | __STATIC_FORCEINLINE uint32_t __SHADD16(uint32_t op1, uint32_t op2) 1736 | { 1737 | uint32_t result; 1738 | 1739 | __ASM volatile ("shadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1740 | return(result); 1741 | } 1742 | 1743 | __STATIC_FORCEINLINE uint32_t __UADD16(uint32_t op1, uint32_t op2) 1744 | { 1745 | uint32_t result; 1746 | 1747 | __ASM volatile ("uadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1748 | return(result); 1749 | } 1750 | 1751 | __STATIC_FORCEINLINE uint32_t __UQADD16(uint32_t op1, uint32_t op2) 1752 | { 1753 | uint32_t result; 1754 | 1755 | __ASM volatile ("uqadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1756 | return(result); 1757 | } 1758 | 1759 | __STATIC_FORCEINLINE uint32_t __UHADD16(uint32_t op1, uint32_t op2) 1760 | { 1761 | uint32_t result; 1762 | 1763 | __ASM volatile ("uhadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1764 | return(result); 1765 | } 1766 | 1767 | __STATIC_FORCEINLINE uint32_t __SSUB16(uint32_t op1, uint32_t op2) 1768 | { 1769 | uint32_t result; 1770 | 1771 | __ASM volatile ("ssub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1772 | return(result); 1773 | } 1774 | 1775 | __STATIC_FORCEINLINE uint32_t __QSUB16(uint32_t op1, uint32_t op2) 1776 | { 1777 | uint32_t result; 1778 | 1779 | __ASM volatile ("qsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1780 | return(result); 1781 | } 1782 | 1783 | __STATIC_FORCEINLINE uint32_t __SHSUB16(uint32_t op1, uint32_t op2) 1784 | { 1785 | uint32_t result; 1786 | 1787 | __ASM volatile ("shsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1788 | return(result); 1789 | } 1790 | 1791 | __STATIC_FORCEINLINE uint32_t __USUB16(uint32_t op1, uint32_t op2) 1792 | { 1793 | uint32_t result; 1794 | 1795 | __ASM volatile ("usub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1796 | return(result); 1797 | } 1798 | 1799 | __STATIC_FORCEINLINE uint32_t __UQSUB16(uint32_t op1, uint32_t op2) 1800 | { 1801 | uint32_t result; 1802 | 1803 | __ASM volatile ("uqsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1804 | return(result); 1805 | } 1806 | 1807 | __STATIC_FORCEINLINE uint32_t __UHSUB16(uint32_t op1, uint32_t op2) 1808 | { 1809 | uint32_t result; 1810 | 1811 | __ASM volatile ("uhsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1812 | return(result); 1813 | } 1814 | 1815 | __STATIC_FORCEINLINE uint32_t __SASX(uint32_t op1, uint32_t op2) 1816 | { 1817 | uint32_t result; 1818 | 1819 | __ASM volatile ("sasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1820 | return(result); 1821 | } 1822 | 1823 | __STATIC_FORCEINLINE uint32_t __QASX(uint32_t op1, uint32_t op2) 1824 | { 1825 | uint32_t result; 1826 | 1827 | __ASM volatile ("qasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1828 | return(result); 1829 | } 1830 | 1831 | __STATIC_FORCEINLINE uint32_t __SHASX(uint32_t op1, uint32_t op2) 1832 | { 1833 | uint32_t result; 1834 | 1835 | __ASM volatile ("shasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1836 | return(result); 1837 | } 1838 | 1839 | __STATIC_FORCEINLINE uint32_t __UASX(uint32_t op1, uint32_t op2) 1840 | { 1841 | uint32_t result; 1842 | 1843 | __ASM volatile ("uasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1844 | return(result); 1845 | } 1846 | 1847 | __STATIC_FORCEINLINE uint32_t __UQASX(uint32_t op1, uint32_t op2) 1848 | { 1849 | uint32_t result; 1850 | 1851 | __ASM volatile ("uqasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1852 | return(result); 1853 | } 1854 | 1855 | __STATIC_FORCEINLINE uint32_t __UHASX(uint32_t op1, uint32_t op2) 1856 | { 1857 | uint32_t result; 1858 | 1859 | __ASM volatile ("uhasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1860 | return(result); 1861 | } 1862 | 1863 | __STATIC_FORCEINLINE uint32_t __SSAX(uint32_t op1, uint32_t op2) 1864 | { 1865 | uint32_t result; 1866 | 1867 | __ASM volatile ("ssax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1868 | return(result); 1869 | } 1870 | 1871 | __STATIC_FORCEINLINE uint32_t __QSAX(uint32_t op1, uint32_t op2) 1872 | { 1873 | uint32_t result; 1874 | 1875 | __ASM volatile ("qsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1876 | return(result); 1877 | } 1878 | 1879 | __STATIC_FORCEINLINE uint32_t __SHSAX(uint32_t op1, uint32_t op2) 1880 | { 1881 | uint32_t result; 1882 | 1883 | __ASM volatile ("shsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1884 | return(result); 1885 | } 1886 | 1887 | __STATIC_FORCEINLINE uint32_t __USAX(uint32_t op1, uint32_t op2) 1888 | { 1889 | uint32_t result; 1890 | 1891 | __ASM volatile ("usax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1892 | return(result); 1893 | } 1894 | 1895 | __STATIC_FORCEINLINE uint32_t __UQSAX(uint32_t op1, uint32_t op2) 1896 | { 1897 | uint32_t result; 1898 | 1899 | __ASM volatile ("uqsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1900 | return(result); 1901 | } 1902 | 1903 | __STATIC_FORCEINLINE uint32_t __UHSAX(uint32_t op1, uint32_t op2) 1904 | { 1905 | uint32_t result; 1906 | 1907 | __ASM volatile ("uhsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1908 | return(result); 1909 | } 1910 | 1911 | __STATIC_FORCEINLINE uint32_t __USAD8(uint32_t op1, uint32_t op2) 1912 | { 1913 | uint32_t result; 1914 | 1915 | __ASM volatile ("usad8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1916 | return(result); 1917 | } 1918 | 1919 | __STATIC_FORCEINLINE uint32_t __USADA8(uint32_t op1, uint32_t op2, uint32_t op3) 1920 | { 1921 | uint32_t result; 1922 | 1923 | __ASM volatile ("usada8 %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); 1924 | return(result); 1925 | } 1926 | 1927 | #define __SSAT16(ARG1,ARG2) \ 1928 | ({ \ 1929 | int32_t __RES, __ARG1 = (ARG1); \ 1930 | __ASM ("ssat16 %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ 1931 | __RES; \ 1932 | }) 1933 | 1934 | #define __USAT16(ARG1,ARG2) \ 1935 | ({ \ 1936 | uint32_t __RES, __ARG1 = (ARG1); \ 1937 | __ASM ("usat16 %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ 1938 | __RES; \ 1939 | }) 1940 | 1941 | __STATIC_FORCEINLINE uint32_t __UXTB16(uint32_t op1) 1942 | { 1943 | uint32_t result; 1944 | 1945 | __ASM volatile ("uxtb16 %0, %1" : "=r" (result) : "r" (op1)); 1946 | return(result); 1947 | } 1948 | 1949 | __STATIC_FORCEINLINE uint32_t __UXTAB16(uint32_t op1, uint32_t op2) 1950 | { 1951 | uint32_t result; 1952 | 1953 | __ASM volatile ("uxtab16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1954 | return(result); 1955 | } 1956 | 1957 | __STATIC_FORCEINLINE uint32_t __SXTB16(uint32_t op1) 1958 | { 1959 | uint32_t result; 1960 | 1961 | __ASM volatile ("sxtb16 %0, %1" : "=r" (result) : "r" (op1)); 1962 | return(result); 1963 | } 1964 | 1965 | __STATIC_FORCEINLINE uint32_t __SXTAB16(uint32_t op1, uint32_t op2) 1966 | { 1967 | uint32_t result; 1968 | 1969 | __ASM volatile ("sxtab16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1970 | return(result); 1971 | } 1972 | 1973 | __STATIC_FORCEINLINE uint32_t __SMUAD (uint32_t op1, uint32_t op2) 1974 | { 1975 | uint32_t result; 1976 | 1977 | __ASM volatile ("smuad %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1978 | return(result); 1979 | } 1980 | 1981 | __STATIC_FORCEINLINE uint32_t __SMUADX (uint32_t op1, uint32_t op2) 1982 | { 1983 | uint32_t result; 1984 | 1985 | __ASM volatile ("smuadx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1986 | return(result); 1987 | } 1988 | 1989 | __STATIC_FORCEINLINE uint32_t __SMLAD (uint32_t op1, uint32_t op2, uint32_t op3) 1990 | { 1991 | uint32_t result; 1992 | 1993 | __ASM volatile ("smlad %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); 1994 | return(result); 1995 | } 1996 | 1997 | __STATIC_FORCEINLINE uint32_t __SMLADX (uint32_t op1, uint32_t op2, uint32_t op3) 1998 | { 1999 | uint32_t result; 2000 | 2001 | __ASM volatile ("smladx %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); 2002 | return(result); 2003 | } 2004 | 2005 | __STATIC_FORCEINLINE uint64_t __SMLALD (uint32_t op1, uint32_t op2, uint64_t acc) 2006 | { 2007 | union llreg_u{ 2008 | uint32_t w32[2]; 2009 | uint64_t w64; 2010 | } llr; 2011 | llr.w64 = acc; 2012 | 2013 | #ifndef __ARMEB__ /* Little endian */ 2014 | __ASM volatile ("smlald %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) ); 2015 | #else /* Big endian */ 2016 | __ASM volatile ("smlald %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) ); 2017 | #endif 2018 | 2019 | return(llr.w64); 2020 | } 2021 | 2022 | __STATIC_FORCEINLINE uint64_t __SMLALDX (uint32_t op1, uint32_t op2, uint64_t acc) 2023 | { 2024 | union llreg_u{ 2025 | uint32_t w32[2]; 2026 | uint64_t w64; 2027 | } llr; 2028 | llr.w64 = acc; 2029 | 2030 | #ifndef __ARMEB__ /* Little endian */ 2031 | __ASM volatile ("smlaldx %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) ); 2032 | #else /* Big endian */ 2033 | __ASM volatile ("smlaldx %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) ); 2034 | #endif 2035 | 2036 | return(llr.w64); 2037 | } 2038 | 2039 | __STATIC_FORCEINLINE uint32_t __SMUSD (uint32_t op1, uint32_t op2) 2040 | { 2041 | uint32_t result; 2042 | 2043 | __ASM volatile ("smusd %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 2044 | return(result); 2045 | } 2046 | 2047 | __STATIC_FORCEINLINE uint32_t __SMUSDX (uint32_t op1, uint32_t op2) 2048 | { 2049 | uint32_t result; 2050 | 2051 | __ASM volatile ("smusdx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 2052 | return(result); 2053 | } 2054 | 2055 | __STATIC_FORCEINLINE uint32_t __SMLSD (uint32_t op1, uint32_t op2, uint32_t op3) 2056 | { 2057 | uint32_t result; 2058 | 2059 | __ASM volatile ("smlsd %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); 2060 | return(result); 2061 | } 2062 | 2063 | __STATIC_FORCEINLINE uint32_t __SMLSDX (uint32_t op1, uint32_t op2, uint32_t op3) 2064 | { 2065 | uint32_t result; 2066 | 2067 | __ASM volatile ("smlsdx %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); 2068 | return(result); 2069 | } 2070 | 2071 | __STATIC_FORCEINLINE uint64_t __SMLSLD (uint32_t op1, uint32_t op2, uint64_t acc) 2072 | { 2073 | union llreg_u{ 2074 | uint32_t w32[2]; 2075 | uint64_t w64; 2076 | } llr; 2077 | llr.w64 = acc; 2078 | 2079 | #ifndef __ARMEB__ /* Little endian */ 2080 | __ASM volatile ("smlsld %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) ); 2081 | #else /* Big endian */ 2082 | __ASM volatile ("smlsld %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) ); 2083 | #endif 2084 | 2085 | return(llr.w64); 2086 | } 2087 | 2088 | __STATIC_FORCEINLINE uint64_t __SMLSLDX (uint32_t op1, uint32_t op2, uint64_t acc) 2089 | { 2090 | union llreg_u{ 2091 | uint32_t w32[2]; 2092 | uint64_t w64; 2093 | } llr; 2094 | llr.w64 = acc; 2095 | 2096 | #ifndef __ARMEB__ /* Little endian */ 2097 | __ASM volatile ("smlsldx %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) ); 2098 | #else /* Big endian */ 2099 | __ASM volatile ("smlsldx %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) ); 2100 | #endif 2101 | 2102 | return(llr.w64); 2103 | } 2104 | 2105 | __STATIC_FORCEINLINE uint32_t __SEL (uint32_t op1, uint32_t op2) 2106 | { 2107 | uint32_t result; 2108 | 2109 | __ASM volatile ("sel %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 2110 | return(result); 2111 | } 2112 | 2113 | __STATIC_FORCEINLINE int32_t __QADD( int32_t op1, int32_t op2) 2114 | { 2115 | int32_t result; 2116 | 2117 | __ASM volatile ("qadd %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 2118 | return(result); 2119 | } 2120 | 2121 | __STATIC_FORCEINLINE int32_t __QSUB( int32_t op1, int32_t op2) 2122 | { 2123 | int32_t result; 2124 | 2125 | __ASM volatile ("qsub %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 2126 | return(result); 2127 | } 2128 | 2129 | #if 0 2130 | #define __PKHBT(ARG1,ARG2,ARG3) \ 2131 | ({ \ 2132 | uint32_t __RES, __ARG1 = (ARG1), __ARG2 = (ARG2); \ 2133 | __ASM ("pkhbt %0, %1, %2, lsl %3" : "=r" (__RES) : "r" (__ARG1), "r" (__ARG2), "I" (ARG3) ); \ 2134 | __RES; \ 2135 | }) 2136 | 2137 | #define __PKHTB(ARG1,ARG2,ARG3) \ 2138 | ({ \ 2139 | uint32_t __RES, __ARG1 = (ARG1), __ARG2 = (ARG2); \ 2140 | if (ARG3 == 0) \ 2141 | __ASM ("pkhtb %0, %1, %2" : "=r" (__RES) : "r" (__ARG1), "r" (__ARG2) ); \ 2142 | else \ 2143 | __ASM ("pkhtb %0, %1, %2, asr %3" : "=r" (__RES) : "r" (__ARG1), "r" (__ARG2), "I" (ARG3) ); \ 2144 | __RES; \ 2145 | }) 2146 | #endif 2147 | 2148 | #define __PKHBT(ARG1,ARG2,ARG3) ( ((((uint32_t)(ARG1)) ) & 0x0000FFFFUL) | \ 2149 | ((((uint32_t)(ARG2)) << (ARG3)) & 0xFFFF0000UL) ) 2150 | 2151 | #define __PKHTB(ARG1,ARG2,ARG3) ( ((((uint32_t)(ARG1)) ) & 0xFFFF0000UL) | \ 2152 | ((((uint32_t)(ARG2)) >> (ARG3)) & 0x0000FFFFUL) ) 2153 | 2154 | __STATIC_FORCEINLINE int32_t __SMMLA (int32_t op1, int32_t op2, int32_t op3) 2155 | { 2156 | int32_t result; 2157 | 2158 | __ASM volatile ("smmla %0, %1, %2, %3" : "=r" (result): "r" (op1), "r" (op2), "r" (op3) ); 2159 | return(result); 2160 | } 2161 | 2162 | #endif /* (__ARM_FEATURE_DSP == 1) */ 2163 | /*@} end of group CMSIS_SIMD_intrinsics */ 2164 | 2165 | 2166 | #pragma GCC diagnostic pop 2167 | 2168 | #endif /* __CMSIS_GCC_H */ 2169 | -------------------------------------------------------------------------------- /cmsis/cmsis_version.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************//** 2 | * @file cmsis_version.h 3 | * @brief CMSIS Core(M) Version definitions 4 | * @version V5.0.3 5 | * @date 24. June 2019 6 | ******************************************************************************/ 7 | /* 8 | * Copyright (c) 2009-2019 ARM Limited. All rights reserved. 9 | * 10 | * SPDX-License-Identifier: Apache-2.0 11 | * 12 | * Licensed under the Apache License, Version 2.0 (the License); you may 13 | * not use this file except in compliance with the License. 14 | * You may obtain a copy of the License at 15 | * 16 | * www.apache.org/licenses/LICENSE-2.0 17 | * 18 | * Unless required by applicable law or agreed to in writing, software 19 | * distributed under the License is distributed on an AS IS BASIS, WITHOUT 20 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 21 | * See the License for the specific language governing permissions and 22 | * limitations under the License. 23 | */ 24 | 25 | #if defined ( __ICCARM__ ) 26 | #pragma system_include /* treat file as system include file for MISRA check */ 27 | #elif defined (__clang__) 28 | #pragma clang system_header /* treat file as system include file */ 29 | #endif 30 | 31 | #ifndef __CMSIS_VERSION_H 32 | #define __CMSIS_VERSION_H 33 | 34 | /* CMSIS Version definitions */ 35 | #define __CM_CMSIS_VERSION_MAIN ( 5U) /*!< [31:16] CMSIS Core(M) main version */ 36 | #define __CM_CMSIS_VERSION_SUB ( 3U) /*!< [15:0] CMSIS Core(M) sub version */ 37 | #define __CM_CMSIS_VERSION ((__CM_CMSIS_VERSION_MAIN << 16U) | \ 38 | __CM_CMSIS_VERSION_SUB ) /*!< CMSIS Core(M) version number */ 39 | #endif 40 | -------------------------------------------------------------------------------- /cmsis/dummy: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /cmsis/stm32f1xx.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anonymou8/stm32_usb_audio/110ba8d568523484cbda09356bfe9b17b28c0c8f/cmsis/stm32f1xx.h -------------------------------------------------------------------------------- /cmsis/system_stm32f1xx.h: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * @file system_stm32f10x.h 4 | * @author MCD Application Team 5 | * @brief CMSIS Cortex-M3 Device Peripheral Access Layer System Header File. 6 | ****************************************************************************** 7 | * @attention 8 | * 9 | *

© Copyright (c) 2017 STMicroelectronics. 10 | * All rights reserved.

11 | * 12 | * This software component is licensed by ST under BSD 3-Clause license, 13 | * the "License"; You may not use this file except in compliance with the 14 | * License. You may obtain a copy of the License at: 15 | * opensource.org/licenses/BSD-3-Clause 16 | * 17 | ****************************************************************************** 18 | */ 19 | 20 | /** @addtogroup CMSIS 21 | * @{ 22 | */ 23 | 24 | /** @addtogroup stm32f10x_system 25 | * @{ 26 | */ 27 | 28 | /** 29 | * @brief Define to prevent recursive inclusion 30 | */ 31 | #ifndef __SYSTEM_STM32F10X_H 32 | #define __SYSTEM_STM32F10X_H 33 | 34 | #ifdef __cplusplus 35 | extern "C" { 36 | #endif 37 | 38 | /** @addtogroup STM32F10x_System_Includes 39 | * @{ 40 | */ 41 | 42 | /** 43 | * @} 44 | */ 45 | 46 | 47 | /** @addtogroup STM32F10x_System_Exported_types 48 | * @{ 49 | */ 50 | 51 | extern uint32_t SystemCoreClock; /*!< System Clock Frequency (Core Clock) */ 52 | extern const uint8_t AHBPrescTable[16U]; /*!< AHB prescalers table values */ 53 | extern const uint8_t APBPrescTable[8U]; /*!< APB prescalers table values */ 54 | 55 | /** 56 | * @} 57 | */ 58 | 59 | /** @addtogroup STM32F10x_System_Exported_Constants 60 | * @{ 61 | */ 62 | 63 | /** 64 | * @} 65 | */ 66 | 67 | /** @addtogroup STM32F10x_System_Exported_Macros 68 | * @{ 69 | */ 70 | 71 | /** 72 | * @} 73 | */ 74 | 75 | /** @addtogroup STM32F10x_System_Exported_Functions 76 | * @{ 77 | */ 78 | 79 | extern void SystemInit(void); 80 | extern void SystemCoreClockUpdate(void); 81 | /** 82 | * @} 83 | */ 84 | 85 | #ifdef __cplusplus 86 | } 87 | #endif 88 | 89 | #endif /*__SYSTEM_STM32F10X_H */ 90 | 91 | /** 92 | * @} 93 | */ 94 | 95 | /** 96 | * @} 97 | */ 98 | /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ 99 | -------------------------------------------------------------------------------- /descriptors_audio.s: -------------------------------------------------------------------------------- 1 | .pushsection .rodata.descriptors 2 | 3 | /*************************************************************************************/ 4 | /* Symbols */ 5 | 6 | FREQ = 192000 7 | 8 | EP0_BUF_SZ = 8 /* Must cohere to C definition */ 9 | EP1_BUF_SZ = 512 /* Max */ 10 | 11 | VID = 0xf055 /* Unofficial FOSS VID */ 12 | PID = 0xf055 13 | 14 | DESC_TYPE_DEVICE = 1 15 | DESC_TYPE_CONFIG = 2 16 | DESC_TYPE_STRING = 3 17 | DESC_TYPE_INTERFACE = 4 18 | DESC_TYPE_ENDPOINT = 5 19 | 20 | 21 | /*************************************************************************************/ 22 | /* Device descriptor */ 23 | 24 | .align 1 25 | 26 | device_descriptor: 27 | .byte DD_SZ @; bLength 28 | .byte DESC_TYPE_DEVICE @; bDescriptorType 29 | .2byte 0x0200 @; bcdUSB = USB 2.0 30 | .byte 0x00 @; bDeviceClass = Interface defined 31 | .byte 0x00 @; bDeviceSubClass 32 | .byte 0x00 @; bDeviceProtocol 33 | .byte EP0_BUF_SZ @; bMaxPacketSize0 : 8, 16, 32, 64 34 | .2byte VID @; idVendor 35 | .2byte PID @; idProduct 36 | .2byte 0 @; bcdDevice 37 | .byte 1 @; iManufacturer : String index 38 | .byte 2 @; iProduct : String index 39 | .byte 0 @; iSerialNumber : String index = nothing 40 | .byte 1 @; bNumConfigurations 41 | DD_SZ = . - device_descriptor 42 | 43 | 44 | /*************************************************************************************/ 45 | /* Config descriptor */ 46 | 47 | .align 1 48 | 49 | config_descriptor: /* Configuration Descriptor */ 50 | .byte CD_SZ @; bLength 51 | .byte DESC_TYPE_CONFIG @; bDescriptorType 52 | .2byte CD_TOTAL_SZ @; wTotalLength 53 | .byte 2 @; bNumInterfaces 54 | .byte 1 @; bConfigurationValue 55 | .byte 0 @; iConfiguration : String index 56 | .byte 0x80 @; bmAttributes = Bus powered 57 | .byte 100/2 @; bMaxPower : In 2 mA units 58 | CD_SZ = . - config_descriptor 59 | 60 | /* First interface (Audio Class, no endpoints) */ 61 | interface_descriptor_ac: /* Standard AC Interface Descriptor */ 62 | .byte IDAC_SZ @; bLength 63 | .byte DESC_TYPE_INTERFACE @; bDescriptorType 64 | .byte 0 @; bInterfaceNumber : Zero based 65 | .byte 0 @; bAlternateSetting 66 | .byte 0 @; bNumEndpoints 67 | .byte 0x01 @; bInterfaceClass = AUDIO 68 | .byte 0x01 @; bInterfaceSubClass = AUDIO_CONTROL 69 | .byte 0 @; bInterfaceProtocol = No protocol 70 | .byte 0 @; iInterface 71 | IDAC_SZ = . - interface_descriptor_ac 72 | 73 | csi_descriptor_ac_hdr: /* AC Interface Header Descriptor */ 74 | .byte CSH_SZ @; bLength 75 | .byte 0x24 @; bDescriptorType = CS_INTERFACE 76 | .byte 0x01 @; bDescriptorSubtype = HEADER 77 | .2byte 0x0100 @; bcdADC: revision of class specification 1.00 78 | .2byte CS_TOTAL_SZ @; wTotalLength 79 | .byte 1 @; bInCollection = One streaming interface: 80 | .byte 1 @; baInterfaceNr = [1] 81 | CSH_SZ = . - csi_descriptor_ac_hdr 82 | 83 | csi_descriptor_ac_it: /* Input Terminal Descriptor */ 84 | .byte CSIT_SZ @; bLength 85 | .byte 0x24 @; bDescriptorType = CS_INTERFACE 86 | .byte 0x02 @; bDescriptorSubtype = INPUT_TERMINAL 87 | .byte (1) @; bTerminalID 88 | .2byte 0x0201 @; wTerminalType : Mic = 0x0201, undefined = 0x0200 89 | .byte 0 @; bAssocTerminal 90 | .byte 1 @; bNrChannels 91 | .2byte 0x00 @; wChannelConfig 92 | .byte 0 @; iChannelNames 93 | .byte 0 @; iTerminal 94 | CSIT_SZ = . - csi_descriptor_ac_it 95 | 96 | @; csi_descriptor_ac_fu: 97 | @; .byte CSFU_SZ @; bLength 98 | @; .byte 0x24 @; bDescriptorType = CS_INTERFACE 99 | @; .byte 0x06 @; bDescriptorSubtype = FEATURE_UNIT 100 | @; .byte (2) @; bUnitID 101 | @; .byte (1) @; bSourceID 102 | @; .byte 1 @; bControlSize = 1 byte (size of a bmaControls[] element) 103 | @; .byte 0x01 @; bmaControls[0] = Mute (Master) 104 | @; .byte 0x00 @; bmaControls[1] = None (Channel 1) 105 | @; .byte 0 @; iFeature 106 | @; CSFU_SZ = . - csi_descriptor_ac_fu 107 | 108 | csi_descriptor_ac_ot: /* Output Terminal Descriptor */ 109 | .byte CSOT_SZ @; bLength 110 | .byte 0x24 @; bDescriptorType = CS_INTERFACE 111 | .byte 0x03 @; bDescriptorSubtype = OUTPUT_TERMINAL 112 | .byte (3) @; bTerminalID 113 | .2byte 0x0101 @; wTerminalType = USB streaming 114 | .byte 0 @; bAssocTerminal 115 | .byte (1) @; bSourceID 116 | .byte 0 @; iTerminal 117 | CSOT_SZ = . - csi_descriptor_ac_ot 118 | 119 | CS_TOTAL_SZ = . - csi_descriptor_ac_hdr 120 | 121 | /* Second interface (Audio Streaming, 1 endpoint) */ 122 | interface_descriptor_as_alt: /* Standard AS interface descriptor (Alt. Set. 0) */ 123 | .byte IDAS_ALT_SZ @; bLength 124 | .byte DESC_TYPE_INTERFACE @; bDescriptorType 125 | .byte 1 @; bInterfaceNumber : Zero based 126 | .byte 0 @; bAlternateSetting 127 | .byte 0 @; bNumEndpoints = No endpoints interface altsetting 128 | .byte 0x01 @; bInterfaceClass = AUDIO 129 | .byte 0x02 @; bInterfaceSubClass = AUDIO_STREAMING 130 | .byte 0 @; bInterfaceProtocol : Not used, must be set to 0 131 | .byte 0 @; iInterface 132 | IDAS_ALT_SZ = . - interface_descriptor_as_alt 133 | 134 | interface_descriptor_as: /* Standard AS Interface Descriptor */ 135 | .byte IDAS_SZ @; bLength 136 | .byte DESC_TYPE_INTERFACE @; bDescriptorType 137 | .byte 1 @; bInterfaceNumber : Zero based 138 | .byte 1 @; bAlternateSetting 139 | .byte 1 @; bNumEndpoints 140 | .byte 0x01 @; bInterfaceClass = AUDIO 141 | .byte 0x02 @; bInterfaceSubClass = AUDIO_STREAMING 142 | .byte 0 @; bInterfaceProtocol : Not used, must be set to 0 143 | .byte 0 @; iInterface 144 | IDAS_SZ = . - interface_descriptor_as 145 | 146 | csi_descriptor_as: /* Class-specific AS General Interface Descriptor */ 147 | .byte CSAS_SZ @; bLength 148 | .byte 0x24 @; bDescriptorType = CS_INTERFACE 149 | .byte 0x01 @; bDescriptorSubtype = GENERAL 150 | .byte (3) @; bTerminalLink 151 | .byte 1 @; bDelay : In frames 152 | .2byte 0x0001 @; wFormatTag = PCM 153 | CSAS_SZ = . - csi_descriptor_as 154 | 155 | csi_descriptor_as_fmt: /* Type I Format Type Descriptor */ 156 | .byte CSASF_SZ @; bLength 157 | .byte 0x24 @; bDescriptorType = CS_INTERFACE 158 | .byte 0x02 @; bDescriptorSubtype = FORMAT_TYPE 159 | .byte 0x01 @; bFormatType = FORMAT_TYPE_I 160 | .byte 1 @; bNrChannels 161 | .byte 2 @; bSubFrameSize : Bytes 162 | .byte 16 @; bBitResolution : MSBs 163 | .byte 1 @; bSamFreqType = One supported frequency 164 | .byte (FREQ) & 0xff @; 165 | .byte (FREQ>>8) & 0xff @; 166 | .byte (FREQ>>16) & 0xff @; tSamFreq 167 | CSASF_SZ = . - csi_descriptor_as_fmt 168 | 169 | endpoint_descriptor: /* Standard AS Isochronous Audio Data Endpoint Descriptor */ 170 | .byte EPD_SZ @; bLength 171 | .byte DESC_TYPE_ENDPOINT @; bDescriptorType 172 | .byte 1 | 0x80 @; bEndpointAddress = IN 1 173 | .byte 0x01 @; bmAttributes = Isochronous, no sync 174 | .2byte EP1_BUF_SZ @; wMaxPacketSize 175 | .byte 1 @; bInterval : 2^(bInterval - 1) frames 176 | .byte 0 @; bRefresh : Not used 177 | .byte 0 @; bSynchAddress : Not used 178 | EPD_SZ = . - endpoint_descriptor 179 | 180 | cse_descriptor: /* Class-Specific AS Isochronous Audio Data Endpoint Descriptor */ 181 | .byte CSED_SZ @; bLength 182 | .byte 0x25 @; bDescriptorType = CS_ENDPOINT 183 | .byte 0x01 @; bDescriptorSubtype = GENERAL 184 | .byte 0x00 @; bmAttributes = None 185 | .byte 0x00 @; bLockDelayUnits : Not used 186 | .2byte 0x0000 @; wLockDelay : Not used 187 | CSED_SZ = . - cse_descriptor 188 | 189 | CD_TOTAL_SZ = . - config_descriptor 190 | 191 | 192 | /*************************************************************************************/ 193 | /* USB-string macro */ 194 | 195 | .macro StrDesc label, data, is_lang=0 196 | \label : 197 | .byte "\label\()_SZ" 198 | .byte DESC_TYPE_STRING 199 | 200 | .if \is_lang 201 | .2byte "\data" 202 | .set "\label\()_SZ", ( . - \label) 203 | .else 204 | .string16 "\data" 205 | .set "\label\()_SZ", ( . - \label - 2) 206 | .endif 207 | .endm 208 | 209 | 210 | /*************************************************************************************/ 211 | /* String descriptors */ 212 | 213 | .align 1 214 | 215 | string_descriptor: 216 | .word sd0_Lang 217 | .word sd1_Manu 218 | .word sd2_Prod 219 | 220 | LANG_EN_US = 0x0409 221 | 222 | StrDesc sd0_Lang, LANG_EN_US, is_lang=1 223 | StrDesc sd1_Manu, "WTF" 224 | StrDesc sd2_Prod, "Prod" 225 | 226 | 227 | /*************************************************************************************/ 228 | 229 | .align 1 230 | .popsection 231 | -------------------------------------------------------------------------------- /ldscripts/blue_pill.ld: -------------------------------------------------------------------------------- 1 | 2 | RAM_START = 0x20000000; 3 | RAM_END = 0x20005000; 4 | 5 | _estack = RAM_END; 6 | 7 | /* ENTRY(main) */ 8 | 9 | 10 | SECTIONS 11 | { 12 | /* This is for ability to change link address with `-Ttext=` ld option */ 13 | .text : {} 14 | 15 | /* Align interrupts vectors table to 512-byte boundary */ 16 | . = ALIGN(512); 17 | 18 | /* C generated vectors sections of name `.isr_vector.__vec_*` */ 19 | INCLUDE vectors.ld 20 | 21 | /* ASM/C generated vectors */ 22 | .isr_vector : { KEEP(*(.isr_vector*)) KEEP(*(.iv)) KEEP(*(.vt)) } 23 | 24 | /* Code and read-only data; can be aligned to (2) */ 25 | .text ALIGN(4) : { *(.text*) *(.rodata*) } 26 | 27 | /* Data alignment is not stricly required */ 28 | 29 | /* Save .text end address; .data init values retain here */ 30 | _sidata = ALIGN(4); 31 | 32 | /* Move .data and .bss to ram if . isn't already there */ 33 | . = . < RAM_START ? RAM_START : . ; 34 | 35 | /* Link .data always to RAM */ 36 | .data ALIGN(4) : AT (_sidata) { _sdata = . ; *(.data*) _edata = . ; } 37 | 38 | /* Link .bss always to RAM after the .data */ 39 | .bss ALIGN(4) : { _sbss = . ; *(.bss*) *(COMMON) _ebss = . ; } 40 | 41 | /* Remove sections that are not required */ 42 | /DISCARD/ : { *(.ARM.attributes) *(.comment*) *(.note*) } 43 | } 44 | -------------------------------------------------------------------------------- /ldscripts/dummy: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /ldscripts/vectors.ld: -------------------------------------------------------------------------------- 1 | /* 2 | STM32F103C interrupts vectors table 3 | 4 | Every `.isr_vector.__vec*` input section, if defined, 5 | goes to a specific offset from start of a vector table. 6 | This saves space if some of interrupts are not used. 7 | 8 | Size of an input section must be equal to 4 bytes. 9 | Input section names are unique. 10 | 11 | Use GCC's __attribute__ to put a vector into a section. 12 | */ 13 | 14 | /* Stack pointer value */ 15 | .isr_vector.sp (. + 0x00) : { 16 | _sivt = . ; /* _sivt */ 17 | KEEP(*(.isr_vector.__sp_val)) 18 | } 19 | 20 | /* Reset vector */ 21 | .isr_vector.reset (_sivt + 0x04) : { 22 | KEEP(*(.isr_vector.__vec_IRQ_Reset)) 23 | } 24 | 25 | /* System exceptions */ 26 | .isr_vector.sysex : { 27 | . = DEFINED(__vec_IRQ_NMI ) ? (_sivt + 0x08) : . ; KEEP(*(.isr_vector.__vec_IRQ_NMI )) 28 | . = DEFINED(__vec_IRQ_HardFault ) ? (_sivt + 0x0c) : . ; KEEP(*(.isr_vector.__vec_IRQ_HardFault )) 29 | . = DEFINED(__vec_IRQ_MemManage ) ? (_sivt + 0x10) : . ; KEEP(*(.isr_vector.__vec_IRQ_MemManage )) 30 | . = DEFINED(__vec_IRQ_BusFault ) ? (_sivt + 0x14) : . ; KEEP(*(.isr_vector.__vec_IRQ_BusFault )) 31 | . = DEFINED(__vec_IRQ_UsageFault ) ? (_sivt + 0x18) : . ; KEEP(*(.isr_vector.__vec_IRQ_UsageFault )) 32 | . = DEFINED(__vec_IRQ_SVCall ) ? (_sivt + 0x2c) : . ; KEEP(*(.isr_vector.__vec_IRQ_SVCall )) 33 | . = DEFINED(__vec_IRQ_DebugMonitor) ? (_sivt + 0x30) : . ; KEEP(*(.isr_vector.__vec_IRQ_DebugMonitor)) 34 | . = DEFINED(__vec_IRQ_PendSV ) ? (_sivt + 0x38) : . ; KEEP(*(.isr_vector.__vec_IRQ_PendSV )) 35 | . = DEFINED(__vec_IRQ_SysTick ) ? (_sivt + 0x3c) : . ; KEEP(*(.isr_vector.__vec_IRQ_SysTick )) 36 | } 37 | 38 | /* Interrupts */ 39 | .isr_vector.irqs : { 40 | . = DEFINED(__vec_0 ) ? (_sivt + 0x40) : . ; KEEP(*(.isr_vector.__vec_0 )) 41 | . = DEFINED(__vec_1 ) ? (_sivt + 0x44) : . ; KEEP(*(.isr_vector.__vec_1 )) 42 | . = DEFINED(__vec_2 ) ? (_sivt + 0x48) : . ; KEEP(*(.isr_vector.__vec_2 )) 43 | . = DEFINED(__vec_3 ) ? (_sivt + 0x4c) : . ; KEEP(*(.isr_vector.__vec_3 )) 44 | . = DEFINED(__vec_4 ) ? (_sivt + 0x50) : . ; KEEP(*(.isr_vector.__vec_4 )) 45 | . = DEFINED(__vec_5 ) ? (_sivt + 0x54) : . ; KEEP(*(.isr_vector.__vec_5 )) 46 | . = DEFINED(__vec_6 ) ? (_sivt + 0x58) : . ; KEEP(*(.isr_vector.__vec_6 )) 47 | . = DEFINED(__vec_7 ) ? (_sivt + 0x5c) : . ; KEEP(*(.isr_vector.__vec_7 )) 48 | . = DEFINED(__vec_8 ) ? (_sivt + 0x60) : . ; KEEP(*(.isr_vector.__vec_8 )) 49 | . = DEFINED(__vec_9 ) ? (_sivt + 0x64) : . ; KEEP(*(.isr_vector.__vec_9 )) 50 | . = DEFINED(__vec_10) ? (_sivt + 0x68) : . ; KEEP(*(.isr_vector.__vec_10)) 51 | . = DEFINED(__vec_11) ? (_sivt + 0x6c) : . ; KEEP(*(.isr_vector.__vec_11)) 52 | . = DEFINED(__vec_12) ? (_sivt + 0x70) : . ; KEEP(*(.isr_vector.__vec_12)) 53 | . = DEFINED(__vec_13) ? (_sivt + 0x74) : . ; KEEP(*(.isr_vector.__vec_13)) 54 | . = DEFINED(__vec_14) ? (_sivt + 0x78) : . ; KEEP(*(.isr_vector.__vec_14)) 55 | . = DEFINED(__vec_15) ? (_sivt + 0x7c) : . ; KEEP(*(.isr_vector.__vec_15)) 56 | . = DEFINED(__vec_16) ? (_sivt + 0x80) : . ; KEEP(*(.isr_vector.__vec_16)) 57 | . = DEFINED(__vec_17) ? (_sivt + 0x84) : . ; KEEP(*(.isr_vector.__vec_17)) 58 | . = DEFINED(__vec_18) ? (_sivt + 0x88) : . ; KEEP(*(.isr_vector.__vec_18)) 59 | . = DEFINED(__vec_19) ? (_sivt + 0x8c) : . ; KEEP(*(.isr_vector.__vec_19)) 60 | . = DEFINED(__vec_20) ? (_sivt + 0x90) : . ; KEEP(*(.isr_vector.__vec_20)) 61 | . = DEFINED(__vec_21) ? (_sivt + 0x94) : . ; KEEP(*(.isr_vector.__vec_21)) 62 | . = DEFINED(__vec_22) ? (_sivt + 0x98) : . ; KEEP(*(.isr_vector.__vec_22)) 63 | . = DEFINED(__vec_23) ? (_sivt + 0x9c) : . ; KEEP(*(.isr_vector.__vec_23)) 64 | . = DEFINED(__vec_24) ? (_sivt + 0xa0) : . ; KEEP(*(.isr_vector.__vec_24)) 65 | . = DEFINED(__vec_25) ? (_sivt + 0xa4) : . ; KEEP(*(.isr_vector.__vec_25)) 66 | . = DEFINED(__vec_26) ? (_sivt + 0xa8) : . ; KEEP(*(.isr_vector.__vec_26)) 67 | . = DEFINED(__vec_27) ? (_sivt + 0xac) : . ; KEEP(*(.isr_vector.__vec_27)) 68 | . = DEFINED(__vec_28) ? (_sivt + 0xb0) : . ; KEEP(*(.isr_vector.__vec_28)) 69 | . = DEFINED(__vec_29) ? (_sivt + 0xb4) : . ; KEEP(*(.isr_vector.__vec_29)) 70 | . = DEFINED(__vec_30) ? (_sivt + 0xb8) : . ; KEEP(*(.isr_vector.__vec_30)) 71 | . = DEFINED(__vec_31) ? (_sivt + 0xbc) : . ; KEEP(*(.isr_vector.__vec_31)) 72 | . = DEFINED(__vec_32) ? (_sivt + 0xc0) : . ; KEEP(*(.isr_vector.__vec_32)) 73 | . = DEFINED(__vec_33) ? (_sivt + 0xc4) : . ; KEEP(*(.isr_vector.__vec_33)) 74 | . = DEFINED(__vec_34) ? (_sivt + 0xc8) : . ; KEEP(*(.isr_vector.__vec_34)) 75 | . = DEFINED(__vec_35) ? (_sivt + 0xcc) : . ; KEEP(*(.isr_vector.__vec_35)) 76 | . = DEFINED(__vec_36) ? (_sivt + 0xd0) : . ; KEEP(*(.isr_vector.__vec_36)) 77 | . = DEFINED(__vec_37) ? (_sivt + 0xd4) : . ; KEEP(*(.isr_vector.__vec_37)) 78 | . = DEFINED(__vec_38) ? (_sivt + 0xd8) : . ; KEEP(*(.isr_vector.__vec_38)) 79 | . = DEFINED(__vec_39) ? (_sivt + 0xdc) : . ; KEEP(*(.isr_vector.__vec_39)) 80 | . = DEFINED(__vec_40) ? (_sivt + 0xe0) : . ; KEEP(*(.isr_vector.__vec_40)) 81 | . = DEFINED(__vec_41) ? (_sivt + 0xe4) : . ; KEEP(*(.isr_vector.__vec_41)) 82 | . = DEFINED(__vec_42) ? (_sivt + 0xe8) : . ; KEEP(*(.isr_vector.__vec_42)) 83 | } 84 | 85 | .isr_vector.soft : { 86 | . = DEFINED(__vec_IRQ_Soft_0) ? (_sivt + 0xec) : . ; KEEP(*(SORT_BY_NAME(.isr_vector.__vec_IRQ_Soft*))) 87 | } 88 | 89 | /* end. */ 90 | -------------------------------------------------------------------------------- /readme.txt: -------------------------------------------------------------------------------- 1 | 192 kHz, 1 channel 16 (15) bit Microphone (Capture device) 2 | for STM32F103 (Blue Pill) microcontroller. 3 | 4 | See `usb_audio.c` for more info. 5 | 6 | To make binary run 7 | chmod +x build.sh 8 | ./build.sh 9 | 10 | `usb_audio_flash.bin` was compiled for 0x08000000 address. -------------------------------------------------------------------------------- /screenshots/dummy: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /screenshots/middle point.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anonymou8/stm32_usb_audio/110ba8d568523484cbda09356bfe9b17b28c0c8f/screenshots/middle point.png -------------------------------------------------------------------------------- /screenshots/mp norm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anonymou8/stm32_usb_audio/110ba8d568523484cbda09356bfe9b17b28c0c8f/screenshots/mp norm.png -------------------------------------------------------------------------------- /screenshots/test signal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anonymou8/stm32_usb_audio/110ba8d568523484cbda09356bfe9b17b28c0c8f/screenshots/test signal.png -------------------------------------------------------------------------------- /usb.h: -------------------------------------------------------------------------------- 1 | /*****************************************************************************/ 2 | /* Types and macros */ 3 | 4 | #define EPnR ((volatile uint32_t*)USB_BASE) 5 | 6 | /* `rw` in the defines below is (ep_type | pa_addr); 7 | an example user definition to e.g. clear CTR bits is: 8 | 9 | #define EP0R_CLEAR_CTR(x) EPnR_CLEAR_CTR_RW(EP0, x, (EP_TYPE_CONTROL | EP0)) 10 | 11 | which is used like: 12 | 13 | EP0R_CLEAR_CTR(CTR_RX); 14 | EP0R_CLEAR_CTR(CTR_TX); 15 | */ 16 | 17 | #define __CTR (CTR_RX | CTR_TX) 18 | 19 | #define EPnR_TOGGLE_RW(ep, x, rw) EPnR[ep] = ((rw) | __CTR) | (x) 20 | #define EPnR_CLEAR_CTR_RW(ep, x, rw) EPnR[ep] = ((rw) | __CTR) ^ (x) 21 | 22 | #define EPnR_SET_STAT_RX_RW(ep, x, rw) EPnR[ep] = ((rw) | __CTR) | ((EPnR[ep] & STAT_RX) ^ ((x)<<12)) 23 | #define EPnR_SET_STAT_TX_RW(ep, x, rw) EPnR[ep] = ((rw) | __CTR) | ((EPnR[ep] & STAT_TX) ^ ((x)<<4)) 24 | 25 | enum _endpoint_numbers { 26 | EP0, EP1, EP2, EP3, EP4, EP5, EP6, EP7 27 | }; 28 | 29 | typedef struct { 30 | uint32_t addr; 31 | uint32_t count; 32 | } _pma_bdt_record[2]; 33 | 34 | #define BDT ((volatile _pma_bdt_record*) 0x40006000) 35 | #define BDT_END_PMA ((2*4)*8) /*64; 448 of 512 bytes left */ 36 | 37 | enum _alloc_pma_buf_types { 38 | TX = 0, RX = 1, 39 | TX0 = 0, TX1 = 1, 40 | RX0 = 0, RX1 = 1 41 | }; 42 | 43 | #define BL_SIZE_2(x) ((x)/2 << 10) 44 | #define BL_SIZE_32(x) (((x)/32 | 0x20) << 10) 45 | 46 | /* alloc_pma(): PMA buffer allocation macro */ 47 | #define alloc_pma(ep, buf_type, org, cnt) (uint32_t*) ( \ 48 | BDT[ep][buf_type].addr = (org), \ 49 | BDT[ep][buf_type].count = (cnt) < 64 ? BL_SIZE_2(cnt) : BL_SIZE_32(cnt), \ 50 | /* return */ ((uint8_t*)BDT + (org)*2) \ 51 | ) 52 | 53 | #define DESCRIPTOR_SIZE(desc) ((uint8_t*)desc)[0] 54 | #define CONFIG_DESCRIPTOR_SIZE(desc) ((uint16_t*)desc)[1] 55 | 56 | 57 | /*****************************************************************************/ 58 | /* Bits and values defines */ 59 | 60 | /* USB_EPnR */ 61 | #define CTR_RX (1<<15) 62 | #define DTOG_RX (1<<14) 63 | #define SW_BUF_TX (1<<14) 64 | #define STAT_RX (3<<12) 65 | #define SETUP (1<<11) 66 | #define CTR_TX (1<<7) 67 | #define DTOG_TX (1<<6) 68 | #define SW_BUF_RX (1<<6) 69 | #define STAT_TX (3<<4) 70 | 71 | /* Statuses */ 72 | #define DISABLED 0b00 73 | #define STALL 0b01 74 | #define NAK 0b10 75 | #define VALID 0b11 76 | 77 | /* Endpoint types */ 78 | #define EP_TYPE_BULK (0b00<<9) 79 | #define EP_TYPE_CONTROL (0b01<<9) 80 | #define EP_TYPE_ISOCHRONOUS (0b10<<9) 81 | #define EP_TYPE_INTERRUPT (0b11<<9) 82 | 83 | /* Standard USB requests */ 84 | #define GET_STATUS 0 85 | #define SET_ADDRESS 5 86 | #define GET_DESCRIPTOR 6 87 | #define GET_CONFIGURATION 8 88 | #define SET_CONFIGURATION 9 89 | #define GET_INTERFACE 10 90 | #define SET_INTERFACE 11 91 | 92 | /* USB descriptor types */ 93 | #define DESC_TYPE_DEVICE 1 94 | #define DESC_TYPE_CONFIG 2 95 | #define DESC_TYPE_STRING 3 96 | #define DESC_TYPE_INTERFACE 4 97 | #define DESC_TYPE_ENDPOINT 5 98 | 99 | 100 | /*****************************************************************************/ 101 | /* Functions */ 102 | 103 | /* PMA copy routines 104 | (`cnt` must be divisible by 2, if not - extra 105 | byte next to last one will be copied anyway) */ 106 | 107 | __attribute__((naked)) 108 | uint16_t* copy_to_pma(uint16_t* from, uint32_t* to, uint32_t cnt) { 109 | asm(" cmp r2, #0 "); 110 | asm(" beq 2f "); 111 | asm(" 1: "); 112 | asm(" ldrh r3, [r0], #2 "); 113 | asm(" strh r3, [r1], #4 "); 114 | asm(" subs r2, #2 "); 115 | asm(" bgt 1b "); 116 | asm(" 2: "); 117 | asm(" bx lr "); 118 | } 119 | 120 | __attribute__((naked)) 121 | uint16_t* copy_from_pma(uint32_t* from, uint16_t* to, uint32_t cnt) { 122 | asm(" cmp r2, #0 "); 123 | asm(" beq 2f "); 124 | asm(" 1: "); 125 | asm(" ldrh r3, [r0], #4 "); 126 | asm(" strh r3, [r1], #2 "); 127 | asm(" subs r2, #2 "); 128 | asm(" bgt 1b "); 129 | asm(" 2: "); 130 | asm(" mov r0, r1 "); 131 | asm(" bx lr "); 132 | } 133 | 134 | 135 | /* USB enabling routine 136 | (system clock must alredy be properly configured; 137 | IRQ and EF are not set!) */ 138 | #define ENABLE_USB_PERIPHERAL(interrupts_mask) do { \ 139 | RCC->APB1ENR |= RCC_APB1ENR_USBEN; \ 140 | /* After reset USB->CNTR == (PDWN | FRES) */ \ 141 | USB->CNTR = (0<CNTR = (0<ISTR = 0; \ 145 | } while (0) 146 | 147 | 148 | /*****************************************************************************/ 149 | /* Redefine CMSIS' `USB` for 32-bit access */ 150 | 151 | /* This redefine eliminates usage of `ldrh` and corresponding 152 | halfword conversions. New definition leads to smaller and 153 | faster executable. 154 | 155 | A cite from the Reference Manual: 156 | > 23.5 USB REGISTERS 157 | > ... 158 | > Due to the common limitation of APB1 bridges on word 159 | > addressability, all register addresses are aligned 160 | > to 32-bit word boundaries although they are 16-bit wide. 161 | > ... 162 | > The peripheral registers can be accessed by half-words 163 | > (16-bit) or words (32-bit). */ 164 | 165 | typedef struct { 166 | __IO uint32_t EP0R; 167 | __IO uint32_t EP1R; 168 | __IO uint32_t EP2R; 169 | __IO uint32_t EP3R; 170 | __IO uint32_t EP4R; 171 | __IO uint32_t EP5R; 172 | __IO uint32_t EP6R; 173 | __IO uint32_t EP7R; 174 | __IO uint32_t RESERVED[8]; 175 | __IO uint32_t CNTR; 176 | __IO uint32_t ISTR; 177 | __IO uint32_t FNR; 178 | __IO uint32_t DADDR; 179 | __IO uint32_t BTABLE; 180 | } My_USB_TypeDef; 181 | 182 | #undef USB 183 | #define USB ((My_USB_TypeDef*)USB_BASE) 184 | 185 | /*****************************************************************************/ 186 | -------------------------------------------------------------------------------- /usb_audio.c: -------------------------------------------------------------------------------- 1 | /*****************************************************************************/ 2 | /* Description */ 3 | 4 | /* 5 | USB Audio Class capture device for STM32F103. 6 | 7 | - 1 channel¹ 8 | - 192'000 samples per second 9 | - true 15 bits per sample 10 | 11 | 12 | Pins used: 13 | - PA1 - analog input 14 | - PC13² - onboard green LED, indicates USB address assignment 15 | - PC14² - external LED, indicates active state (recording) 16 | - PB15 - test signal, push-pull output if enabled 17 | 18 | 19 | Input range and output format: 20 | Input is the regular ADC one. No scaling or shifting is done. 21 | 12-bit ADC measures from Vref+ to Vref- (in case of Blue Pill 22 | they are internally connected to Vdda and Vssa: +3.3 V and 23 | GND respectively). 24 | 25 | For output, 8 12-bit samples are added together, then the sum 26 | is multiplied by 2 to compose 16-bit values. A value of 32768 27 | is subtracted to make samples signed. Endianness is "little". 28 | 29 | 30 | Test signal: 31 | If enabled, it will produce 192000 toggles per second (96 kHz 32 | square wave) between Vdd and Vss. Even if it's not directly 33 | connected to the input it will generate a bit of noise. 34 | 35 | When test signal is connected to ADC input a waveform should 36 | be like alternating samples of a close to maximum amplitude. 37 | 38 | 39 | USB device has only one configuration, one interface altsetting, 40 | no audio controls such as mute or volume. 41 | 42 | 43 | ¹ - If someone wants to make 2-channel version, then he must write 44 | additional proper oversamples summation function, set ADC second 45 | channel and change channels number and sampling rate in the USB 46 | configuration descriptor. If done, then one would have 96 ksps 47 | and only 14 bits per sample. 48 | 49 | ² - Pins PC13-PC15 should only sink or source no more than 3 mA. 50 | 51 | */ 52 | 53 | /*****************************************************************************/ 54 | /* Includes */ 55 | 56 | #include "blue_pill.h" 57 | #include "usb.h" 58 | 59 | asm(".include \"descriptors_audio.s\""); 60 | 61 | 62 | /*****************************************************************************/ 63 | /* Common defines and vars */ 64 | 65 | #define F_CPU_MHz 72 66 | 67 | /* Pin will be configured as push-pull output if 1 */ 68 | #define ENABLE_TEST_SIGNAL_ON_PB15 0 69 | 70 | /* Decreases CPU usage even more - to ~6% when running from flash */ 71 | #define USE_FAST_ASM_COPY_FUNCTIOIN 1 72 | 73 | /* LED on PC14 pin indicates active state - recording */ 74 | #define BB_RED_OUT BITBAND(GPIOC->ODR, 14) 75 | #define RED BB_RED_OUT 76 | #define RED_ON() BB_RED_OUT = 0 77 | #define RED_OFF() BB_RED_OUT = 1 78 | #define RED_TOGGLE() BB_RED_OUT ^= 1 79 | 80 | /* Count of 16-bit samples * (8) oversamples - determines buffer size */ 81 | #define ADC_RAW_BUF_CNT ((8)*(192+52)) /* 3904 bytes */ 82 | uint16_t 83 | adc_raw_buffer[ADC_RAW_BUF_CNT] __attribute__((aligned(4))); 84 | 85 | 86 | /*****************************************************************************/ 87 | /* USB related functions, vars and defs */ 88 | 89 | #define N_EPs 2 /* Total number of endpoints used */ 90 | 91 | #define EP0_BUF_SZ 8 /* See `descriptors_audio.s` file */ 92 | #define EP1_BUF_SZ 0 /* Not used in this program */ 93 | 94 | const uint32_t 95 | ep_typ_adr[N_EPs] = { (EP_TYPE_CONTROL | EP0), (EP_TYPE_ISOCHRONOUS | EP1) }, 96 | bufs_sizes[N_EPs] = { EP0_BUF_SZ, EP1_BUF_SZ }; 97 | 98 | #define EPnR_CLEAR_CTR(ep, x) EPnR_CLEAR_CTR_RW(ep, x, ep_typ_adr[ep]) 99 | #define EPnR_SET_STAT_RX(ep, x) EPnR_SET_STAT_RX_RW(ep, x, ep_typ_adr[ep]) 100 | #define EPnR_SET_STAT_TX(ep, x) EPnR_SET_STAT_TX_RW(ep, x, ep_typ_adr[ep]) 101 | 102 | int32_t 103 | device_address, 104 | current_configuration, /* Currently not used */ 105 | interface_1_altsetting; 106 | 107 | extern uint16_t 108 | device_descriptor[], 109 | config_descriptor[], 110 | *string_descriptor[]; 111 | 112 | /* Setup packet */ 113 | struct { 114 | uint32_t bmRequestType; 115 | uint32_t bRequest; 116 | uint32_t wValue; 117 | uint32_t wIndex; 118 | uint32_t wLength; 119 | } SP; 120 | 121 | /* PMA buffers addresses in normal address space; 122 | 2 pointers (for tx/tx0/rx0 and rx/tx1/rx1 buffers) 123 | for each of N_EPs endpoints */ 124 | uint32_t 125 | *pma_bufs[N_EPs][2]; 126 | 127 | /* Buffers origins in PMA space (0..511) */ 128 | #define PMA_BUF0_ORG (N_EPs * 8) /* EP0; same for tx and rx */ 129 | #define PMA_BUF1_ORG (PMA_BUF0_ORG + EP0_BUF_SZ) /* EP1; same for tx0 and tx1 */ 130 | 131 | 132 | void init_ep0() { 133 | /* PMA buffers are arrays of `uint32_t` 134 | which can carry only 16-bit values */ 135 | pma_bufs[EP0][TX] = alloc_pma(EP0, TX, PMA_BUF0_ORG, 0); 136 | pma_bufs[EP0][RX] = alloc_pma(EP0, RX, PMA_BUF0_ORG, EP0_BUF_SZ); 137 | 138 | /* After reset USB->EPnR == 0; set 139 | STAT_RX = VALID; STAT_TX = STALL; */ 140 | EPnR[EP0] = ep_typ_adr[EP0] | (VALID<<12) | (STALL<<4); 141 | } 142 | 143 | void set_ep1_counters(uint32_t cnt) { 144 | BDT[EP1][TX0].count = cnt; 145 | BDT[EP1][TX1].count = cnt; 146 | } 147 | 148 | void init_ep1() { 149 | /* Single buffer: both pointers point to the same location */ 150 | pma_bufs[EP1][TX0] = alloc_pma(EP1, TX0, PMA_BUF1_ORG, 0); 151 | pma_bufs[EP1][TX1] = alloc_pma(EP1, TX1, PMA_BUF1_ORG, 0); 152 | 153 | set_ep1_counters(0); 154 | 155 | /* STAT_TX = VALID; */ 156 | EPnR[EP1] = ep_typ_adr[EP1] | (VALID<<4); 157 | } 158 | 159 | void init_endpoints() { 160 | init_ep0(); 161 | init_ep1(); 162 | } 163 | 164 | 165 | uint32_t reset_dma_counter() { 166 | /* 167 | Returns current couter value. 168 | 169 | CNDTR holds number of transfers, not bytes. 170 | */ 171 | 172 | uint32_t 173 | cndtr; 174 | 175 | cndtr = DMA1_Channel1->CNDTR; 176 | 177 | #define DMA_TRANSFER_SIZE_32 (0b1010 << 8) 178 | 179 | /* To reset counter DMA must be disabled first */ 180 | DMA1_Channel1->CCR = 0; 181 | DMA1_Channel1->CNDTR = ADC_RAW_BUF_CNT/2; 182 | asm("@ no push, please"); 183 | DMA1_Channel1->CCR = 1 | DMA_TRANSFER_SIZE_32 | DMA_CCR_MINC; 184 | 185 | return cndtr; 186 | } 187 | 188 | void copy_to_pma_x8_oversampled(uint16_t *from, uint32_t* to, uint32_t cnt) { 189 | /* 190 | Function execution time is ~78 (~120) μs 191 | when running from flash (RAM) at 72 MHz 192 | CPU clock. `cnt` is the number of samples 193 | to be written. 194 | */ 195 | 196 | uint32_t 197 | sample, i; 198 | 199 | for (i=0; i < cnt; i++) { 200 | sample = from[i*8 + 0] + 201 | from[i*8 + 1] + 202 | from[i*8 + 2] + 203 | from[i*8 + 3] + 204 | from[i*8 + 4] + 205 | from[i*8 + 5] + 206 | from[i*8 + 6] + 207 | from[i*8 + 7]; 208 | 209 | /* Only lower 2 bytes will be copied */ 210 | to[i] = sample * 2 - 0x8000; 211 | } 212 | 213 | /* Test expression: will zero first sample in every USB frame */ 214 | //~ to[0] = 0; 215 | } 216 | 217 | #if USE_FAST_ASM_COPY_FUNCTIOIN == 1 218 | __attribute__((naked)) 219 | void copy_to_pma_x8_oversampled_fast(uint16_t *from, uint32_t* to, int32_t cnt) { 220 | /* 221 | Function execution time is ~52 (~78) μs 222 | when running from flash (RAM) at 72 MHz 223 | CPU clock. 224 | 225 | `from` - 12-bit data as uint16_t*; 226 | `to` - PMA buffer, uint16_t* as uint32_t*; 227 | `cnt` - number of samples to be written. 228 | */ 229 | 230 | asm(" push {r4,r5,r6} "); 231 | asm(" b 2f "); 232 | asm(" "); 233 | asm(" 1: "); 234 | asm(" ldmia r0!, {r3,r4,r5,r6} "); 235 | asm(" "); 236 | asm(" add r3, r4 "); 237 | asm(" add r3, r5 "); 238 | asm(" add r3, r6 "); 239 | asm(" add r3, r3, r3, lsr #16 "); 240 | asm(" "); 241 | asm(" lsls r3, #1 "); 242 | asm(" sub r3, #0x8000 "); 243 | asm(" "); 244 | asm(" str r3, [r1], #4 "); 245 | asm(" 2: "); 246 | asm(" subs r2, #1 "); 247 | asm(" bpl 1b "); 248 | asm(" "); 249 | asm(" pop {r4,r5,r6} "); 250 | asm(" bx lr "); 251 | } 252 | #endif 253 | 254 | #if 0 255 | void start_systick_ms(uint32_t ms) { 256 | /* 257 | Maximum overflow time is 1.864 s. 258 | */ 259 | 260 | if (ms) { 261 | SysTick->LOAD = ms * 1000 * F_CPU_MHz / 8; 262 | SysTick->CTRL = 3; 263 | } else { 264 | SysTick->CTRL = 0; 265 | SysTick->VAL = 0; 266 | } 267 | } 268 | #endif 269 | 270 | 271 | /*****************************************************************************/ 272 | /* General USB functions */ 273 | 274 | void ep0_set_stat_tx(uint32_t status) { 275 | /* Compiles to 7 instructions */ 276 | EPnR_SET_STAT_TX(EP0, status); 277 | } 278 | 279 | /* Used as arg in `epn_tx()` calls 280 | in place of `cnt` value when `data` == NULL */ 281 | #define NEXT 0 282 | 283 | void epn_tx(uint32_t ep, uint16_t *data, int32_t cnt) { 284 | /* 285 | -1 (any negative) for `bytes_remain` means 286 | send nothing; if it's 0 - zero-length packet 287 | will be sent. 288 | */ 289 | 290 | static int32_t 291 | bytes_remain[N_EPs]; 292 | static uint16_t 293 | *s_data[N_EPs]; 294 | 295 | if (data != NULL) { 296 | /* Initializatioin */ 297 | s_data[ep] = data; 298 | bytes_remain[ep] = cnt; 299 | } else { 300 | /* On `NEXT` iterations */ 301 | cnt = bytes_remain[ep]; 302 | } 303 | 304 | if (cnt >= 0) { 305 | 306 | if (cnt >= bufs_sizes[ep]) { 307 | cnt = bufs_sizes[ep]; 308 | bytes_remain[ep] -= cnt; 309 | } else { 310 | /* Last packet */ 311 | bytes_remain[ep] = -1; 312 | } 313 | 314 | /* Will copy even number of bytes (never less); 315 | `cnt` may be odd only at a final chunk */ 316 | s_data[ep] = copy_to_pma(s_data[ep], pma_bufs[ep][TX], cnt); 317 | BDT[ep][TX].count = cnt; 318 | 319 | /* Enable transfer */ 320 | ep0_set_stat_tx(VALID); 321 | } 322 | 323 | } 324 | 325 | void get_descriptor(uint32_t wValue, uint32_t wLength) { 326 | uint32_t 327 | desc_type = wValue >> 8, 328 | desc_index = wValue & 0xff; 329 | uint16_t 330 | *data, 331 | cnt; 332 | 333 | switch (desc_type) { 334 | case DESC_TYPE_DEVICE: 335 | data = device_descriptor; 336 | cnt = DESCRIPTOR_SIZE(data); 337 | break; 338 | case DESC_TYPE_CONFIG: 339 | data = config_descriptor; 340 | cnt = CONFIG_DESCRIPTOR_SIZE(data); 341 | break; 342 | case DESC_TYPE_STRING: 343 | data = string_descriptor[desc_index]; 344 | cnt = DESCRIPTOR_SIZE(data); 345 | break; 346 | default: 347 | ep0_set_stat_tx(STALL); 348 | return; 349 | } 350 | 351 | if (cnt > wLength) { 352 | cnt = wLength; 353 | } 354 | 355 | /* Send descriptor */ 356 | epn_tx(EP0, data, cnt); 357 | } 358 | 359 | #if 0 360 | void class_request_handler(uint32_t rx_cnt) { 361 | uint16_t 362 | data = 0, 363 | cnt = 0; 364 | 365 | switch (SP.bRequest) { 366 | case 0x01: /* SET_CUR */ 367 | MUTED = pma_bufs[EP0][RX][0] & 0xff; 368 | break; 369 | case 0x81: /* GET_CUR */ 370 | data = MUTED; 371 | cnt = 1; 372 | break; 373 | 374 | default: 375 | ep0_set_stat_tx(STALL); 376 | return; 377 | } 378 | 379 | /* Send short data or zero-length packet (status) */ 380 | epn_tx(EP0, &data, cnt); 381 | } 382 | #endif 383 | 384 | void setup_handler() { 385 | /* Setup Packet is always 8 bytes */ 386 | SP.bmRequestType = pma_bufs[EP0][RX][0] & 0x60, /* Type only */ 387 | SP.bRequest = pma_bufs[EP0][RX][0] >> 8, 388 | SP.wValue = pma_bufs[EP0][RX][1], 389 | SP.wIndex = pma_bufs[EP0][RX][2], 390 | SP.wLength = pma_bufs[EP0][RX][3]; 391 | 392 | uint16_t 393 | data = 0, 394 | cnt = 0; 395 | 396 | if (SP.bmRequestType == 0 /* Standard */) { 397 | switch (SP.bRequest) { 398 | case GET_STATUS: 399 | cnt = 2; 400 | break; 401 | case SET_ADDRESS: 402 | device_address = SP.wValue; 403 | break; 404 | case GET_DESCRIPTOR: 405 | /* `wIndex` is Lang ID or zero */ 406 | get_descriptor(SP.wValue, SP.wLength); 407 | return; 408 | case SET_CONFIGURATION: 409 | /* current_configuration = SP.wValue; */ 410 | break; 411 | case GET_CONFIGURATION: 412 | /* data = current_configuration; */ 413 | data = 1; /* There's only one config #1 */ 414 | cnt = 1; 415 | break; 416 | case SET_INTERFACE: 417 | if (SP.wIndex == 1) { 418 | interface_1_altsetting = SP.wValue; 419 | } 420 | break; 421 | case GET_INTERFACE: 422 | if (SP.wIndex == 1) { 423 | data = interface_1_altsetting; 424 | } 425 | cnt = 1; 426 | break; 427 | default: 428 | ep0_set_stat_tx(STALL); 429 | return; 430 | } 431 | } else { 432 | #if 0 433 | if (SP.bRequest & 0x80) { 434 | /* Handle Class IN request */ 435 | class_request_handler(0); 436 | return; 437 | } else { 438 | /* Wait for Class OUT data; see `ISR_usb()` */ 439 | } 440 | #else 441 | ep0_set_stat_tx(STALL); 442 | return; 443 | #endif 444 | } 445 | 446 | /* Send short data or zero-length packet (Status) */ 447 | epn_tx(EP0, &data, cnt); 448 | } 449 | 450 | 451 | void ISR_usb() { 452 | /* 453 | Main USB interrupt routine. 454 | */ 455 | 456 | /* Bits SOF and SOFM have same position */ 457 | uint32_t 458 | istr = USB->ISTR, 459 | ep = istr & 0x0f, 460 | epnr = EPnR[ep], 461 | reset = istr & USB_ISTR_RESET, 462 | sof_int = (USB->CNTR & USB_CNTR_SOFM) & (istr & USB_ISTR_SOF), 463 | setup = epnr & SETUP, 464 | rx = epnr & CTR_RX, 465 | tx = epnr & CTR_TX; 466 | 467 | static uint32_t 468 | ep1_tx_ok = 0; 469 | 470 | void stop_tim1() { 471 | TIM1->CR1 = 0; 472 | TIM1->CNT = 0; 473 | } 474 | 475 | 476 | if (reset) { 477 | /* 478 | Host must send reset requset to a device 479 | right after it's been attached. 480 | */ 481 | 482 | init_endpoints(); 483 | USB->ISTR = 0; 484 | USB->DADDR = USB_DADDR_EF; 485 | stop_tim1(); 486 | ep1_tx_ok = 0; 487 | return; 488 | } 489 | 490 | 491 | if (sof_int) { 492 | /* 493 | SOF interrupts are enabled after an EP1 tx. 494 | 495 | If data haven't been transmitted in previous 496 | frame, turn red led off and stop conversions 497 | and disable SOF interrupts; on Isochronous EPs 498 | exactly one transaction occurs every frame. 499 | */ 500 | 501 | if (!ep1_tx_ok) { 502 | RED_OFF(); 503 | 504 | /* Timer 1 triggers ADCs; as group conversion 505 | is used, they remain converting and requesting 506 | DMA till group end */ 507 | stop_tim1(); 508 | 509 | set_ep1_counters(0); 510 | 511 | /* Turn off SOF interrupts */ 512 | USB->CNTR &= ~USB_CNTR_SOFM; 513 | } 514 | 515 | ep1_tx_ok = 0; 516 | 517 | /* Clear SOF flag */ 518 | USB->ISTR = ~USB_ISTR_SOF; 519 | } 520 | 521 | 522 | if (rx) { 523 | /* 524 | On receiving a Control data packet 525 | MC sets both STATs to NAK. 526 | */ 527 | 528 | if (setup) { 529 | setup_handler(); 530 | } else { 531 | #if 0 532 | /* Staus or Data phase */ 533 | uint32_t 534 | rx_cnt = BDT[ep][RX].count & 0x3ff; 535 | 536 | if (rx_cnt) { 537 | if (ep == EP0 && SP.bmRequestType != 0) { 538 | /* Handle Class OUT request data */ 539 | class_request_handler(rx_cnt); 540 | } 541 | } 542 | #endif 543 | } 544 | 545 | /* Also clears EPnR_SETUP bit */ 546 | EPnR_CLEAR_CTR(ep, CTR_RX); 547 | EPnR_SET_STAT_RX(ep, VALID); 548 | } 549 | 550 | 551 | if (tx) { 552 | EPnR_CLEAR_CTR(ep, CTR_TX); 553 | 554 | if (ep == EP0) { 555 | 556 | if (device_address && device_address > 0) { 557 | USB->DADDR = USB_DADDR_EF | device_address; 558 | device_address = -1; 559 | 560 | /* Indicate successful address assignment */ 561 | LED_ON(); 562 | } 563 | 564 | /* Transmit next if there's data; 565 | first tx started elsewhere */ 566 | epn_tx(ep, NULL, NEXT); 567 | 568 | } else if (ep == EP1) { 569 | 570 | ep1_tx_ok = 1; 571 | 572 | if (TIM1->CR1 == 0 /* stopped */) { 573 | RED_ON(); 574 | 575 | /* Clear excess conversions from previous session */ 576 | reset_dma_counter(); 577 | 578 | /* Turn on SOF interrupts */ 579 | USB->ISTR = ~USB_ISTR_SOF; 580 | USB->CNTR |= USB_CNTR_SOFM; 581 | } 582 | 583 | /* Start/continue Timer 1; enable Timer1 CC3 interrupt; 584 | at the worst case the interrupt will happen in 5.2 μs */ 585 | TIM1->SR = 0; 586 | TIM1->DIER = TIM_DIER_CC3IE; 587 | TIM1->CR1 = 1; 588 | } 589 | } 590 | 591 | } /* ISR_usb() */ 592 | 593 | 594 | void ISR_tim1() { 595 | /* 596 | Timer1 CC3 interrupt. 597 | 598 | It is generated a little before CC1 event, 599 | at this moment previous DMA transactions 600 | for all 8 oversamples of an audio sample 601 | should already be over. 602 | 603 | Timer1 CC1 triggers ADC1 group conversion 604 | while every conversion of a group triggers DMA. 605 | Thus we have about 14 ADC cycles or 84 CPU 606 | cycles to reset DMA counter and copy first 607 | 2 samples. 608 | 609 | Interrupt entry/exit costs 12 CPU cycles. 610 | */ 611 | 612 | uint32_t 613 | samples_done, 614 | bytes_done, 615 | cndtr; 616 | 617 | cndtr = reset_dma_counter(); 618 | 619 | /* DMA copies 2 samples at a time; there are 8 oversamples */ 620 | samples_done = ADC_RAW_BUF_CNT/8 - cndtr/4; 621 | bytes_done = samples_done * 2; 622 | 623 | #if USE_FAST_ASM_COPY_FUNCTIOIN == 1 624 | copy_to_pma_x8_oversampled_fast(adc_raw_buffer, pma_bufs[EP1][TX], samples_done); 625 | #else 626 | copy_to_pma_x8_oversampled(adc_raw_buffer, pma_bufs[EP1][TX], samples_done); 627 | #endif 628 | 629 | set_ep1_counters(bytes_done); 630 | 631 | /* You must use DSB if an interrupt/flag 632 | is cleared at the handler return */ 633 | TIM1->DIER = 0; 634 | __DSB(); 635 | } 636 | 637 | 638 | /*****************************************************************************/ 639 | /* Program entry */ 640 | 641 | int main() { 642 | 643 | { /* Configure clocks */ 644 | CONFIGURE_PLL(HSE, F_CPU_MHz); 645 | RCC->CFGR |= RCC_CFGR_ADCPRE_DIV6; 646 | } 647 | 648 | { /* Enable peripherals used (except USB) */ 649 | RCC->AHBENR |= RCC_AHBENR_DMA1EN; 650 | RCC->APB2ENR = 651 | RCC_APB2ENR_IOPAEN | RCC_APB2ENR_IOPBEN | RCC_APB2ENR_IOPCEN | 652 | RCC_APB2ENR_ADC1EN | RCC_APB2ENR_ADC2EN | 653 | RCC_APB2ENR_TIM1EN; 654 | } 655 | 656 | { /* LEDs */ 657 | /* LED_OFF(); 658 | RED_OFF(); 659 | CONFIGURE_PIN(GPIOC, 13, O_OPEN_DRAIN); 660 | CONFIGURE_PIN(GPIOC, 14, O_OPEN_DRAIN); 661 | ~= */ 662 | GPIOC->ODR = (1<<13) | (1<<14); 663 | GPIOC->CRH = (O_OPEN_DRAIN << 13%8*4) | (O_OPEN_DRAIN << 14%8*4); 664 | } 665 | 666 | { /* ADCs */ 667 | /** 668 | ADC1 + ADC2 run @ 12 MHz performing 4 group conversions 669 | each. ADCs are triggered by Timer 1 CC1 & CC2 events. 670 | The result is then copyed by DMA1 channel 1 requested 671 | by ADC1. ADC2 starts 7 cycles before ADC1. 672 | 673 | At 12 MHz clock one ADC can make no more than 4 674 | conversions per 192k audio sample: 675 | - one conversion lasts 14 ADC clock cycles; 676 | - 12e6 / 192e3 / 14 ~= 4.46. 677 | 678 | Maximum externel trigger conversion start delay is: 679 | 2/12 + 1/72 = 0.180 μs (from datasheet) 680 | **/ 681 | 682 | /* CONFIGURE_PIN(GPIOA, 0, I_ANALOG); */ 683 | CONFIGURE_PIN(GPIOA, 1, I_ANALOG); 684 | 685 | #define A1CH 1 686 | #define A2CH 1 687 | #define TRG_T1CC1 (0b000 << ADC_CR2_EXTSEL_Pos) 688 | #define TRG_T1CC2 (0b001 << ADC_CR2_EXTSEL_Pos) 689 | 690 | ADC1->CR1 = ADC_CR1_SCAN; 691 | ADC2->CR1 = ADC_CR1_SCAN; 692 | ADC1->SQR1 = (4-1) << ADC_SQR1_L_Pos; 693 | ADC2->SQR1 = (4-1) << ADC_SQR1_L_Pos; 694 | ADC1->SQR3 = (A1CH<<(0*5)) | (A1CH<<(1*5)) | (A1CH<<(2*5)) | (A1CH<<(3*5)); 695 | ADC2->SQR3 = (A2CH<<(0*5)) | (A2CH<<(1*5)) | (A2CH<<(2*5)) | (A2CH<<(3*5)); 696 | ADC1->CR2 = 1 | ADC_CR2_EXTTRIG | TRG_T1CC1 | ADC_CR2_DMA; 697 | ADC2->CR2 = 1 | ADC_CR2_EXTTRIG | TRG_T1CC2; 698 | 699 | /* Calibrate ADCs */ 700 | wait_μs(6, F_CPU_MHz); 701 | ADC1->CR2 |= ADC_CR2_CAL; 702 | ADC2->CR2 |= ADC_CR2_CAL; 703 | while ((ADC1->CR2 | ADC2->CR2) & ADC_CR2_CAL); 704 | } 705 | 706 | { /* Timer 1 as ADC sync */ 707 | /** 708 | TIM1_ARR - a period of ADCs triggering. 709 | 710 | CC3 event has an important role of updating DMA 711 | counter at the exact momment of time. It also 712 | used as the test signal generator. 713 | 714 | To make CCx an ADC trigger CCxE and MOE must be enabled. 715 | **/ 716 | 717 | #if ENABLE_TEST_SIGNAL_ON_PB15 == 1 718 | /* Test PWM signal, 192k Toggles per second */ 719 | CONFIGURE_PIN(GPIOB, 15, O_ALT_PUSH_PULL); 720 | #endif 721 | 722 | #define CC_PWM2 0b111 /* |_--| */ 723 | #define CC_TOGGLE 0b011 724 | 725 | TIM1->ARR = F_CPU_MHz * 1000 / 192 - 1; 726 | TIM1->CCR1 = 32 + 7*6; 727 | TIM1->CCR2 = 32; 728 | TIM1->CCR3 = 32; 729 | TIM1->CCMR1 = (CC_PWM2 << 4) | (CC_PWM2 << 12); 730 | TIM1->CCMR2 = (CC_TOGGLE << 4); 731 | TIM1->CCER = TIM_CCER_CC1E | TIM_CCER_CC2E | TIM_CCER_CC3NE; 732 | TIM1->BDTR = TIM_BDTR_MOE; 733 | 734 | INTERRUPT_ENABLE(IRQ_TIM1_CC); 735 | } 736 | 737 | { /* DMA */ 738 | DMA1_Channel1->CPAR = (uint32_t)&ADC1->DR; 739 | DMA1_Channel1->CMAR = (uint32_t)adc_raw_buffer; 740 | } 741 | 742 | 743 | { /* USB */ 744 | ENABLE_USB_PERIPHERAL(USB_CNTR_RESETM | USB_CNTR_CTRM); 745 | /** Make USB interrupt preemptible **/ 746 | INTERRUPT_PRIORITY(IRQ_USB_LP_CAN_RX0, 1); 747 | INTERRUPT_ENABLE(IRQ_USB_LP_CAN_RX0); 748 | } 749 | 750 | 751 | while (PWR /* :) */) { 752 | /* 753 | Infinite loop. 754 | 755 | Current CPU load is no more than 10% spent 756 | on summation of oversamples. 757 | */ 758 | 759 | __WFI(); 760 | } 761 | } 762 | 763 | 764 | /*****************************************************************************/ 765 | /* Interrupt vectors */ 766 | 767 | #if 0 768 | void ISR_systick() { 769 | RED_TOGGLE(); 770 | } 771 | 772 | VECTOR(IRQ_SysTick, ISR_systick); 773 | #endif 774 | 775 | VECTOR(IRQ_TIM1_CC, ISR_tim1); 776 | VECTOR(IRQ_USB_LP_CAN_RX0, ISR_usb); 777 | 778 | 779 | /*****************************************************************************/ 780 | -------------------------------------------------------------------------------- /usb_audio_flash.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anonymou8/stm32_usb_audio/110ba8d568523484cbda09356bfe9b17b28c0c8f/usb_audio_flash.bin --------------------------------------------------------------------------------