├── .gitignore ├── .gitmodules ├── LICENSE.txt ├── README.md ├── example └── blue_pill │ ├── Makefile.template │ ├── speed_demo │ ├── Makefile │ ├── config.mk │ ├── convert_image.py │ ├── image.png │ ├── lib │ ├── linker.ld │ ├── main.c │ ├── run.gdb │ ├── semihosting_helper.py │ ├── startup.s │ ├── utils │ └── vendor │ │ └── cmsis │ └── ugui │ ├── Makefile │ ├── config.mk │ ├── lib │ ├── linker.ld │ ├── main.c │ ├── run.gdb │ ├── startup.s │ ├── utils │ └── vendor │ ├── cmsis │ └── uGUI │ ├── system.h │ ├── ugui.c │ ├── ugui.h │ └── ugui_config.h ├── lib ├── st7789.c └── st7789.h ├── utils ├── svc.c └── svc.h └── vendor └── cmsis ├── cmsis_compiler.h ├── cmsis_gcc.h ├── cmsis_version.h ├── core_cm3.h ├── stm32f10x.h └── system_stm32f10x.h /.gitignore: -------------------------------------------------------------------------------- 1 | build/ 2 | example/blue_pill/speed_demo/image.png.dat 3 | .gdb_history 4 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "vendor/uGUI"] 2 | path = vendor/uGUI 3 | url = https://github.com/achimdoebler/UGUI.git 4 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2019 Miroslav Bendík 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | SOFTWARE. 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # st7789-stm32-driver 2 | ST7789 display driver for STM32F103C8 (blue pill) 3 | 4 | Demo: 5 | 6 | [![Video](https://img.youtube.com/vi/8S1BXnx-vLE/0.jpg)](https://www.youtube.com/watch?v=8S1BXnx-vLE) 7 | -------------------------------------------------------------------------------- /example/blue_pill/Makefile.template: -------------------------------------------------------------------------------- 1 | .PHONY: clean 2 | 3 | -include config.mk 4 | 5 | BUILD_DIR ?= build/ 6 | SOURCE_DIR ?= . 7 | 8 | ECHO = echo 9 | FIND = find 10 | MKDIR = mkdir -p 11 | RM = rm -rf 12 | 13 | ARCH = arm-none-eabi 14 | AS = $(ARCH)-as 15 | CC = $(ARCH)-gcc 16 | CXX = $(ARCH)-g++ 17 | GDB = $(ARCH)-gdb 18 | OBJCOPY = $(ARCH)-objcopy 19 | OBJDUMP = $(ARCH)-objdump 20 | SIZE = $(ARCH)-size 21 | LD = $(ARCH)-g++ 22 | 23 | DEBUG_CLFAGS = -g3 -ggdb 24 | COMMON_CFLAGS = -Wall -Wextra -ffreestanding -ffunction-sections -fdata-sections -O3 25 | ARCH_CFLAGS = -mlittle-endian -mcpu=cortex-m3 -march=armv7-m -mthumb -mfloat-abi=soft 26 | CFLAGS ?= -nostdlib -nostartfiles -specs=nosys.specs -specs=nano.specs -std=gnu99 27 | CXXFLAGS ?= -nostdlib -nostartfiles -specs=nosys.specs 28 | 29 | 30 | CFLAGS := ${COMMON_CFLAGS} ${DEBUG_CLFAGS} ${ARCH_CFLAGS} ${CFLAGS} 31 | CXXFLAGS := ${COMMON_CFLAGS} ${DEBUG_CLFAGS} ${ARCH_CFLAGS} ${CXXFLAGS} 32 | AFLAGS := --warn --fatal-warnings ${AFLAGS} 33 | LDFLAGS := ${CFLAGS} -Wl,--gc-sections ${LDFLAGS} 34 | 35 | 36 | TARGET = $(BUILD_DIR)$(PROJECT_NAME) 37 | VPATH = ${SOURCE_DIR} 38 | 39 | 40 | SOURCES = $(shell $(FIND) -L ${SOURCE_DIR} -iregex ".*\.\\(c\\|s\\|cpp\\)" -printf "%P\n") 41 | objects = $(patsubst %.cpp,%.o,$(patsubst %.c,%.o,$(patsubst %.s,%.o,$(SOURCES)))) 42 | OBJECTS = $(addprefix $(BUILD_DIR), $(objects)) 43 | LINKERS = $(shell $(FIND) ${SOURCE_DIR} -name '*.ld') 44 | 45 | 46 | $(TARGET).elf: $(OBJECTS) $(LINKERS) Makefile config.mk 47 | $(LD) $(addprefix -T ,$(LINKERS)) -Wl,-Map,$(@:.elf=.map) -o $@ $(OBJECTS) $(LDFLAGS) 48 | @$(OBJCOPY) -O binary $@ $(@:.elf=.bin) 49 | @$(OBJCOPY) -O ihex $@ $(@:.elf=.hex) 50 | @$(ECHO) 51 | @$(SIZE) $@ | tail -1 - | awk '{print "Size: "$$1+$$2" B"}' 52 | 53 | 54 | $(BUILD_DIR)%.o: %.c Makefile config.mk 55 | @$(MKDIR) `dirname $@` 56 | $(CC) -c -MMD -MP $(CFLAGS) -o $@ $< 57 | 58 | 59 | $(BUILD_DIR)%.o: %.cpp Makefile config.mk 60 | @$(MKDIR) `dirname $@` 61 | $(CXX) -c -MMD -MP $(CXXFLAGS) -o $@ $< 62 | 63 | 64 | $(BUILD_DIR)%.o: %.s Makefile config.mk 65 | @$(MKDIR) `dirname $@` 66 | $(AS) $(AFLAGS) -o $@ $< 67 | 68 | 69 | -include $(OBJECTS:.o=.d) 70 | 71 | 72 | clean: 73 | $(RM) $(BUILD_DIR)* 74 | -------------------------------------------------------------------------------- /example/blue_pill/speed_demo/Makefile: -------------------------------------------------------------------------------- 1 | -include ../Makefile.template 2 | 3 | 4 | run: $(TARGET).elf image.png.dat 5 | $(GDB) --command=run.gdb -nh -q --batch $(TARGET).elf 6 | 7 | 8 | image.png.dat: image.png 9 | python convert_image.py image.png 10 | -------------------------------------------------------------------------------- /example/blue_pill/speed_demo/config.mk: -------------------------------------------------------------------------------- 1 | PROJECT_NAME = demo 2 | 3 | CFLAGS = -specs=nosys.specs -nostartfiles -Ivendor/cmsis -Ilib -Iutils -DSTM32F10X_MD -I. 4 | -------------------------------------------------------------------------------- /example/blue_pill/speed_demo/convert_image.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | import sys 3 | import struct 4 | from PIL import Image, ImagePalette 5 | import numpy as np 6 | 7 | 8 | OUTPUT_SIZE = (240, 240) 9 | 10 | 11 | def dither_565(im): 12 | bands = im.split() 13 | 14 | r_palette = np.array([[(c << 3) + 3 for c in range(32)]]) 15 | g_palette = np.array([[(c << 2) + 1 for c in range(64)]]) 16 | b_palette = np.array([[(c << 3) + 3 for c in range(32)]]) 17 | r_palette = Image.fromarray(r_palette, mode='L').convert('RGB').convert('P', palette=Image.ADAPTIVE, colors=32) 18 | g_palette = Image.fromarray(g_palette, mode='L').convert('RGB').convert('P', palette=Image.ADAPTIVE, colors=64) 19 | b_palette = Image.fromarray(b_palette, mode='L').convert('RGB').convert('P', palette=Image.ADAPTIVE, colors=32) 20 | print(r_palette.palette.colors) 21 | 22 | bands = [bands[0].convert('RGB').convert('P', palette=r_palette.palette), bands[1].convert('RGB').convert('P', palette=r_palette.palette), bands[2].convert('RGB').convert('P', palette=r_palette.palette)] 23 | bands = [bands[0].convert('L'), bands[1].convert('L'), bands[2].convert('L')] 24 | 25 | return Image.merge('RGB', bands) 26 | 27 | 28 | def main(): 29 | with open(sys.argv[1], 'rb') as image_fp: 30 | im = Image.open(image_fp) 31 | im = im.convert('RGB') 32 | 33 | im.thumbnail(OUTPUT_SIZE, Image.ANTIALIAS) 34 | 35 | with open(sys.argv[1] + '.dat', 'wb') as image_fp: 36 | packed_pixel = struct.Struct("> 3 41 | g = g >> 2 42 | b = b >> 3 43 | pixel = (r << 11) + (g << 5) + (b) 44 | image_fp.write(packed_pixel.pack(pixel)) 45 | 46 | 47 | 48 | if __name__ == "__main__": 49 | main() 50 | -------------------------------------------------------------------------------- /example/blue_pill/speed_demo/image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mireq/st7789-stm32-driver/fa3d3470366c30afd2262db462fe894e3d56aa51/example/blue_pill/speed_demo/image.png -------------------------------------------------------------------------------- /example/blue_pill/speed_demo/lib: -------------------------------------------------------------------------------- 1 | ../../../lib -------------------------------------------------------------------------------- /example/blue_pill/speed_demo/linker.ld: -------------------------------------------------------------------------------- 1 | ENTRY(start_) 2 | 3 | MEMORY 4 | { 5 | ram : ORIGIN = 0x20000000, LENGTH = 20k 6 | } 7 | 8 | SECTIONS 9 | { 10 | /* 11 | * Program 12 | */ 13 | .text : { 14 | *(.text.startup_) /* start code */ 15 | *(.text) /* .text sections */ 16 | *(.text*) /* .text* sections */ 17 | *(.glue_7) /* Glue ARM to thumb */ 18 | *(.glue_7t) /* Glue thumb to ARM */ 19 | *(.eh_frame) /* Exceptions, stack unwinding */ 20 | 21 | KEEP (*(.init)) 22 | KEEP (*(.fini)) 23 | } > ram 24 | 25 | /* ARM section unwinding */ 26 | .ARM.extab : { 27 | *(.ARM.extab* .gnu.linkonce.armextab.*) 28 | } > ram 29 | 30 | .ARM.exidx : { 31 | *(.ARM.exidx* .gnu.linkonce.armexidx.*) 32 | } > ram 33 | 34 | /* Stack unwinding for C++ */ 35 | .eh_frame_hdr : { 36 | *(.eh_frame_hdr) 37 | } > ram 38 | .eh_frame : ONLY_IF_RO { 39 | *(.eh_frame) 40 | } > ram 41 | 42 | /* Constants */ 43 | .rodata : ALIGN(4) { 44 | . = ALIGN(4); 45 | __rodata_start__ = .; 46 | *(.rodata) 47 | *(.rodata.*) 48 | . = ALIGN(4); 49 | __rodata_end__ = .; 50 | } > ram 51 | 52 | _etext = .; 53 | 54 | .data : ALIGN(4) 55 | { 56 | . = ALIGN(4); 57 | *(.data) 58 | *(.data.*) 59 | *(.ramtext) 60 | . = ALIGN(4); 61 | } > ram 62 | 63 | .bss (NOLOAD) : ALIGN(4) 64 | { 65 | . = ALIGN(4); 66 | _bss_start = .; 67 | *(.bss) 68 | *(.bss.*) 69 | *(COMMON) 70 | . = ALIGN(4); 71 | _bss_end = .; 72 | } > ram 73 | 74 | .noinit (NOLOAD) : ALIGN(4) 75 | { 76 | __noinit_start__ = .; 77 | *(.noinit .noinit.*) 78 | . = ALIGN(4) ; 79 | __noinit_end__ = .; 80 | } > ram 81 | 82 | end = .; 83 | 84 | 85 | /* 86 | .heap (NOLOAD) : 87 | { 88 | . = ALIGN(4); 89 | __heap_start__ = .; 90 | __heap_base__ = .; 91 | . = ORIGIN(HEAP_RAM) + LENGTH(HEAP_RAM); 92 | __heap_end__ = .; 93 | } > ram 94 | */ 95 | 96 | 97 | /* 98 | .rodata : { 99 | *(.rodata*); 100 | } > ram 101 | .bss : { 102 | *(.bss*); 103 | } > ram 104 | */ 105 | } 106 | 107 | -------------------------------------------------------------------------------- /example/blue_pill/speed_demo/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | 8 | typedef int64_t float_t; 9 | #define FLOAT_BITS 20 10 | #define FLOAT_FACT ((float_t)1 << FLOAT_BITS) 11 | #define MANDELBROT_MAXITER 1024 12 | 13 | typedef int float_fast_t; 14 | #define FLOAT_FAST_BITS 13 15 | #define FLOAT_FAST_FACT ((float_t)1 << FLOAT_FAST_BITS) 16 | #define MANDELBROT_MAXITER_FAST 64 17 | 18 | 19 | #define PIXEL_BUFFER_LINES 20 20 | #define PIXEL_BUFFER_SIZE (ST7789_LCD_WIDTH * PIXEL_BUFFER_LINES) 21 | 22 | 23 | void setupPrescaler(int pllmul) { 24 | // enable high speed external oscillator 25 | RCC->CR = (RCC->CR & ~RCC_CR_HSEBYP) | RCC_CR_HSEON; 26 | while (!(RCC->CR & RCC_CR_HSERDY)) { 27 | ; 28 | } 29 | 30 | RCC->CFGR = (pllmul-2) << 18 | RCC_CFGR_PLLSRC | RCC_CFGR_PPRE1_DIV2; 31 | RCC->CR |= RCC_CR_PLLON; 32 | 33 | while (!(RCC->CR & RCC_CR_PLLRDY)) { 34 | ; 35 | } 36 | 37 | if (RCC->APB2ENR & RCC_APB2ENR_USART1EN) { 38 | // if usart1 is clocked wait to drain possible debugging infos. 39 | while ((USART1->SR & (USART_SR_TXE | USART_SR_TC)) != (USART_SR_TXE | USART_SR_TC)) { 40 | ; 41 | } 42 | } 43 | 44 | // switch sysclock to pll 45 | RCC->CFGR |= RCC_CFGR_SW_PLL; 46 | 47 | // wait for ack 48 | while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_PLL) { 49 | ; 50 | } 51 | } 52 | 53 | 54 | void setupTimer(void) { 55 | RCC->APB2ENR |= RCC_APB2ENR_TIM1EN; 56 | TIM1->PSC = 0x3200 - 1; 57 | // TIM1->CR1 |= TIM_CR1_ARPE; 58 | TIM1->CR1 |= TIM_CR1_CEN; 59 | } 60 | 61 | 62 | void svcLogTime() { 63 | static char buf[12]; 64 | itoa(TIM1->CNT / 10, buf, 10); 65 | char *bufPtr = buf; 66 | while (*bufPtr != 0) { 67 | bufPtr++; 68 | } 69 | *bufPtr = '\n'; 70 | bufPtr++; 71 | *bufPtr = '\0'; 72 | svcWrite0(buf); 73 | } 74 | 75 | 76 | void svcLogTimeReset() { 77 | TIM1->CNT = 0; 78 | } 79 | 80 | 81 | void svcWriteNumber(int number) { 82 | static char buf[12]; 83 | itoa(number, buf, 10); 84 | char *bufPtr = buf; 85 | while (*bufPtr != 0) { 86 | bufPtr++; 87 | } 88 | *bufPtr = '\n'; 89 | bufPtr++; 90 | *bufPtr = '\0'; 91 | svcWrite0(buf); 92 | } 93 | 94 | 95 | void st7789_GPIOInit(void) { 96 | // Enable GPIOA and SPI1 clock 97 | RCC->APB2ENR |= RCC_APB2ENR_IOPAEN | RCC_APB2ENR_SPI1EN; 98 | // Enable DMA1 channel 99 | RCC->AHBENR |= RCC_AHBENR_DMA1EN; 100 | 101 | // Enable SPI 102 | ST7789_SPI->SR = 0; 103 | // Reverse polarity? 104 | ST7789_SPI->CR1 = \ 105 | SPI_CR1_SSM | \ 106 | SPI_CR1_SSI | \ 107 | SPI_CR1_MSTR | \ 108 | SPI_CR1_CPOL | \ 109 | SPI_CR1_BIDIMODE | \ 110 | SPI_CR1_BIDIOE; 111 | ST7789_SPI->CR1 |= SPI_CR1_SPE; 112 | 113 | // DC and RST signals 114 | // Maximum output speed 115 | ST7789_DC_PORT->CRH |= GPIO_CRH_MODE8; 116 | ST7789_RST_PORT->CRH |= GPIO_CRH_MODE9; 117 | // Output push pull 118 | ST7789_DC_PORT->CRH &= ~(GPIO_CRH_CNF8); 119 | ST7789_RST_PORT->CRH &= ~(GPIO_CRH_CNF9); 120 | 121 | // SPI pins 122 | // Maximum output speed on PA5/PA7 123 | GPIOA->CRL |= GPIO_CRL_MODE5; 124 | GPIOA->CRL |= GPIO_CRL_MODE7; 125 | // Alternate mode on PA5/PA7 126 | GPIOA->CRL = (GPIOA->CRL & ~(GPIO_CRL_CNF5)) | (GPIO_CRL_CNF5_1); 127 | GPIOA->CRL = (GPIOA->CRL & ~(GPIO_CRL_CNF7)) | (GPIO_CRL_CNF7_1); 128 | } 129 | 130 | 131 | void demoCycleColors(void) { 132 | for (uint8_t color = 0; color < 248; color += 8) { 133 | st7789_Clear(st7789_RGBToColor(color, color, color)); 134 | } 135 | for (uint8_t color = 248; color > 0; color -= 8) { 136 | st7789_Clear(st7789_RGBToColor(255, color, color)); 137 | } 138 | for (uint8_t color = 0; color < 248; color += 8) { 139 | st7789_Clear(st7789_RGBToColor(255, color, 0)); 140 | } 141 | for (uint8_t color = 248; color > 0; color -= 8) { 142 | st7789_Clear(st7789_RGBToColor(color, 255, 0)); 143 | } 144 | for (uint8_t color = 0; color < 248; color += 8) { 145 | st7789_Clear(st7789_RGBToColor(0, 255, color)); 146 | } 147 | for (uint8_t color = 248; color > 0; color -= 8) { 148 | st7789_Clear(st7789_RGBToColor(0, color, 255)); 149 | } 150 | for (uint8_t color = 248; color > 0; color -= 8) { 151 | st7789_Clear(st7789_RGBToColor(0, 0, color)); 152 | } 153 | } 154 | 155 | 156 | void demoCheckboardDisplay(uint16_t checkboardSize, uint16_t startX, uint16_t startY) { 157 | st7789_StartMemoryWrite(); 158 | bool xPolarity = (startX / checkboardSize) & 1; 159 | bool yPolarity = (startY / checkboardSize) & 1; 160 | bool initialXPolarity = (startX / checkboardSize) & 1; 161 | startX = startX % checkboardSize; 162 | startY = startY % checkboardSize; 163 | uint16_t lineBuffer[ST7789_LCD_WIDTH * 2]; 164 | uint16_t *buf = (uint16_t *)(&lineBuffer); 165 | uint16_t xCounter = startX; 166 | uint16_t yCounter = startY; 167 | 168 | for (uint16_t line = 0; line < ST7789_LCD_HEIGHT + 1; ++line) { 169 | uint16_t *frontBuffer = ((line & 1 )== 0) ? (buf + ST7789_LCD_WIDTH) : buf; 170 | uint16_t *backBuffer = ((line & 1) == 0) ? buf : (buf + ST7789_LCD_WIDTH); 171 | xPolarity = initialXPolarity; 172 | if (line > 0) { 173 | st7789_WriteDMA(frontBuffer, ST7789_LCD_WIDTH * 2); 174 | } 175 | if (line < ST7789_LCD_HEIGHT) { 176 | xCounter = startX; 177 | for (uint16_t column = 0; column < ST7789_LCD_WIDTH; ++column) { 178 | backBuffer[column] = (xPolarity ^ yPolarity) ? 0xffff : st7789_RGBToColor(line, column, 255 - line); 179 | xCounter++; 180 | if (xCounter == checkboardSize) { 181 | xPolarity = !xPolarity; 182 | xCounter = 0; 183 | } 184 | } 185 | } 186 | if (line > 0) { 187 | st7789_WaitForDMA(); 188 | } 189 | yCounter++; 190 | if (yCounter == checkboardSize) { 191 | yPolarity = !yPolarity; 192 | yCounter = 0; 193 | } 194 | } 195 | } 196 | 197 | 198 | void demoCheckboard(void) { 199 | uint16_t size = 1; 200 | uint16_t posX = 0; 201 | uint16_t posY = 0; 202 | for (size_t i = 0; i < 50; ++i) { 203 | size++; 204 | demoCheckboardDisplay(size, posX, posY); 205 | } 206 | for (size_t i = 0; i < 50; ++i) { 207 | posX += 3; 208 | demoCheckboardDisplay(size, posX, posY); 209 | } 210 | for (size_t i = 0; i < 50; ++i) { 211 | posX += 3; 212 | posY += i / 10; 213 | demoCheckboardDisplay(size, posX, posY); 214 | } 215 | for (size_t i = 0; i < 100; ++i) { 216 | posX += 3 + i / 25; 217 | posY += 5 + i / 10; 218 | demoCheckboardDisplay(size, posX, posY); 219 | } 220 | for (size_t i = 0; i < 20; ++i) { 221 | posX += 7; 222 | posY += 15; 223 | demoCheckboardDisplay(size, posX, posY); 224 | } 225 | for (size_t i = 0; i < 100; ++i) { 226 | posX += 7 * (100 - i) / 100; 227 | posY += 15 * (100 - i) / 100; 228 | demoCheckboardDisplay(size, posX, posY); 229 | } 230 | } 231 | 232 | 233 | uint16_t demoMandelbrotCalculateFast(float_fast_t realInit, float_fast_t imagInit, uint16_t maxiter) { 234 | float_fast_t realq, imagq, real, imag; 235 | uint16_t iter; 236 | 237 | real = realInit; 238 | imag = imagInit; 239 | for (iter = 0; iter < maxiter; ++iter) { 240 | realq = (real * real) >> FLOAT_FAST_BITS; 241 | imagq = (imag * imag) >> FLOAT_FAST_BITS; 242 | if ((realq + imagq) > (float_fast_t) 4 * FLOAT_FAST_FACT) { 243 | break; 244 | } 245 | imag = ((real * imag) >> (FLOAT_FAST_BITS - 1)) + imagInit; 246 | real = realq - imagq + realInit; 247 | } 248 | return iter; 249 | } 250 | 251 | 252 | void demoMandelbrotDisplayFast(float_fast_t realmin, float_fast_t imagmin, float_fast_t realmax, float_fast_t imagmax, uint16_t maxiter) { 253 | st7789_StartMemoryWrite(); 254 | uint16_t lineBuffer[ST7789_LCD_WIDTH * 2]; 255 | uint16_t *buf = (uint16_t *)(&lineBuffer); 256 | uint16_t colormap[MANDELBROT_MAXITER_FAST]; 257 | for (size_t i = 0; i < maxiter; ++i) { 258 | colormap[i] = st7789_RGBToColor( 259 | (maxiter - i - 1) * 256 / maxiter, 260 | i * 256 / maxiter, 261 | 0 262 | ); 263 | } 264 | 265 | float_fast_t stepReal, stepImag, real, imag; 266 | uint8_t column, line; 267 | 268 | stepReal = (realmax - realmin) / ST7789_LCD_WIDTH; 269 | stepImag = (imagmax - imagmin) / ST7789_LCD_HEIGHT; 270 | 271 | imag = imagmax; 272 | for (line = 0; line < ST7789_LCD_HEIGHT; ++line) { 273 | uint16_t *frontBuffer = ((line & 1 )== 0) ? (buf + ST7789_LCD_WIDTH) : buf; 274 | uint16_t *backBuffer = ((line & 1) == 0) ? buf : (buf + ST7789_LCD_WIDTH); 275 | if (line > 0) { 276 | st7789_WriteDMA(frontBuffer, ST7789_LCD_WIDTH * 2); 277 | } 278 | 279 | real = realmin; 280 | for (column = 0; column < ST7789_LCD_WIDTH; ++column) { 281 | uint16_t color = demoMandelbrotCalculateFast(real, imag, maxiter); 282 | if (color == maxiter) { 283 | color = 0; 284 | } 285 | else { 286 | color = colormap[color]; 287 | } 288 | backBuffer[column] = color; 289 | real += stepReal; 290 | } 291 | imag -= stepImag; 292 | 293 | if (line > 0) { 294 | st7789_WaitForDMA(); 295 | } 296 | if (line == ST7789_LCD_HEIGHT - 1) { 297 | st7789_WriteDMA(backBuffer, ST7789_LCD_WIDTH * 2); 298 | st7789_WaitForDMA(); 299 | } 300 | } 301 | } 302 | 303 | 304 | uint16_t demoMandelbrotCalculate(float_t realInit, float_t imagInit) { 305 | float_t realq, imagq, real, imag; 306 | uint16_t iter; 307 | 308 | real = realInit; 309 | imag = imagInit; 310 | for (iter = 0; iter < MANDELBROT_MAXITER; ++iter) { 311 | realq = (real * real) >> FLOAT_BITS; 312 | imagq = (imag * imag) >> FLOAT_BITS; 313 | if ((realq + imagq) > (float_t) 4 * FLOAT_FACT) { 314 | break; 315 | } 316 | imag = ((real * imag) >> (FLOAT_BITS - 1)) + imagInit; 317 | real = realq - imagq + realInit; 318 | } 319 | return iter; 320 | } 321 | 322 | 323 | void demoMandelbrotDisplay(float_t realmin, float_t imagmin, float_t realmax, float_t imagmax) { 324 | st7789_StartMemoryWrite(); 325 | uint16_t lineBuffer[ST7789_LCD_WIDTH * 2]; 326 | uint16_t *buf = (uint16_t *)(&lineBuffer); 327 | uint16_t colormap[MANDELBROT_MAXITER]; 328 | for (int i = 0; i < MANDELBROT_MAXITER; ++i) { 329 | colormap[i] = st7789_RGBToColor( 330 | i < 64 ? (MANDELBROT_MAXITER - i - 1) * 256 / MANDELBROT_MAXITER : 0, 331 | i < 64 ? (i * 16) * 256 / MANDELBROT_MAXITER : (i < 319 ? 319 - i : 0), 332 | (i * 4) * 256 / MANDELBROT_MAXITER 333 | ); 334 | } 335 | 336 | float_t stepReal, stepImag, real, imag; 337 | uint8_t column, line; 338 | 339 | stepReal = (realmax - realmin) / ST7789_LCD_WIDTH; 340 | stepImag = (imagmax - imagmin) / ST7789_LCD_HEIGHT; 341 | 342 | imag = imagmax; 343 | for (line = 0; line < ST7789_LCD_HEIGHT; ++line) { 344 | uint16_t *frontBuffer = ((line & 1 )== 0) ? (buf + ST7789_LCD_WIDTH) : buf; 345 | uint16_t *backBuffer = ((line & 1) == 0) ? buf : (buf + ST7789_LCD_WIDTH); 346 | if (line > 0) { 347 | st7789_WriteDMA(frontBuffer, ST7789_LCD_WIDTH * 2); 348 | } 349 | 350 | real = realmin; 351 | for (column = 0; column < ST7789_LCD_WIDTH; ++column) { 352 | uint16_t color = demoMandelbrotCalculate(real, imag); 353 | if (color == MANDELBROT_MAXITER) { 354 | color = 0; 355 | } 356 | else { 357 | color = colormap[color]; 358 | } 359 | backBuffer[column] = color; 360 | real += stepReal; 361 | } 362 | imag -= stepImag; 363 | 364 | if (line > 0) { 365 | st7789_WaitForDMA(); 366 | } 367 | if (line == ST7789_LCD_HEIGHT - 1) { 368 | st7789_WriteDMA(backBuffer, ST7789_LCD_WIDTH * 2); 369 | st7789_WaitForDMA(); 370 | } 371 | } 372 | } 373 | 374 | 375 | void demoMandelbrot() { 376 | float realMin = -2.0; 377 | float imagMin = -1.35; 378 | float realMax = 0.7; 379 | float imagMax = 1.35; 380 | const float realFinalMin = -0.749; 381 | const float imagFinalMin = 0.125; 382 | const float realFinalMax = -0.739; 383 | const float imagFinalMax = 0.135; 384 | 385 | for (size_t i = 8; i < 16; ++i) { 386 | demoMandelbrotDisplayFast(realMin * FLOAT_FAST_FACT, imagMin * FLOAT_FAST_FACT, realMax * FLOAT_FAST_FACT, imagMax * FLOAT_FAST_FACT, i); 387 | st7789_WaitNanosecs(20000); 388 | } 389 | for (size_t i = 0; i < 24; ++i) { 390 | realMin = (realMin * 9 + realFinalMin) / 10; 391 | realMax = (realMax * 9 + realFinalMax) / 10; 392 | imagMin = (imagMin * 9 + imagFinalMin) / 10; 393 | imagMax = (imagMax * 9 + imagFinalMax) / 10; 394 | demoMandelbrotDisplayFast(realMin * FLOAT_FAST_FACT, imagMin * FLOAT_FAST_FACT, realMax * FLOAT_FAST_FACT, imagMax * FLOAT_FAST_FACT, 16 + i); 395 | } 396 | 397 | demoMandelbrotDisplay(realFinalMin * FLOAT_FACT, imagFinalMin * FLOAT_FACT, realFinalMax * FLOAT_FACT, imagFinalMax * FLOAT_FACT); 398 | st7789_WaitNanosecs(4000000); 399 | } 400 | 401 | 402 | void demoPixmap() { 403 | uint16_t line = 0; 404 | uint16_t batch = 0; 405 | uint16_t pixels[PIXEL_BUFFER_SIZE]; 406 | 407 | st7789_Clear(0x0000); 408 | st7789_StartMemoryWrite(); 409 | while (line < ST7789_LCD_HEIGHT) { 410 | pixels[0] = batch; 411 | pixels[1] = PIXEL_BUFFER_SIZE; 412 | svcCall(0xff, &pixels); 413 | st7789_WriteDMA(&pixels, PIXEL_BUFFER_SIZE * 2); 414 | st7789_WaitForDMA(); 415 | line = line + PIXEL_BUFFER_LINES; 416 | batch += 1; 417 | } 418 | st7789_WaitNanosecs(2000000); 419 | } 420 | 421 | 422 | int main(void) { 423 | setupPrescaler(16); 424 | setupTimer(); 425 | 426 | st7789_GPIOInit(); 427 | st7789_Reset(); 428 | st7789_Init_1_3_LCD(); 429 | 430 | for(;;) { 431 | demoCycleColors(); 432 | demoCheckboard(); 433 | demoMandelbrot(); 434 | demoPixmap(); 435 | } 436 | return 0; 437 | } 438 | -------------------------------------------------------------------------------- /example/blue_pill/speed_demo/run.gdb: -------------------------------------------------------------------------------- 1 | target remote localhost:3333 2 | monitor arm semihosting disable 3 | monitor reset halt 4 | 5 | 6 | #handle SIGTRAP noprint nostop 7 | 8 | source semihosting_helper.py 9 | catch signal SIGTRAP 10 | commands 11 | pi on_trap() 12 | end 13 | 14 | 15 | load 16 | continue 17 | -------------------------------------------------------------------------------- /example/blue_pill/speed_demo/semihosting_helper.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | import gdb 3 | import struct 4 | 5 | 6 | def on_trap(): 7 | frame = gdb.selected_frame() 8 | arch = frame.architecture() 9 | pc = frame.read_register("pc") 10 | instruction = arch.disassemble(int(pc))[0]['asm'].split() 11 | if instruction[0] != 'bkpt': 12 | return 13 | svc_command = int(instruction[1], 16) 14 | if svc_command != 0xAB: 15 | return 16 | command = int(frame.read_register("r0")) 17 | message = frame.read_register("r1") 18 | try: 19 | command_handler = SVC_COMMANDS[command] 20 | except KeyError: 21 | print("Unknown command 0x%04x" % command) 22 | else: 23 | command_handler(message) 24 | 25 | 26 | def write0(message): 27 | char_pointer_type = gdb.lookup_type('char').pointer() 28 | message_pointer = message.cast(char_pointer_type) 29 | gdb.write(message_pointer.string()) 30 | gdb.flush() 31 | gdb.execute('continue') 32 | 33 | 34 | def writePixels(message): 35 | inferior = gdb.inferiors()[0] 36 | batch, size = struct.unpack(' ram 24 | 25 | /* ARM section unwinding */ 26 | .ARM.extab : { 27 | *(.ARM.extab* .gnu.linkonce.armextab.*) 28 | } > ram 29 | 30 | .ARM.exidx : { 31 | *(.ARM.exidx* .gnu.linkonce.armexidx.*) 32 | } > ram 33 | 34 | /* Stack unwinding for C++ */ 35 | .eh_frame_hdr : { 36 | *(.eh_frame_hdr) 37 | } > ram 38 | .eh_frame : ONLY_IF_RO { 39 | *(.eh_frame) 40 | } > ram 41 | 42 | /* Constants */ 43 | .rodata : ALIGN(4) { 44 | . = ALIGN(4); 45 | __rodata_start__ = .; 46 | *(.rodata) 47 | *(.rodata.*) 48 | . = ALIGN(4); 49 | __rodata_end__ = .; 50 | } > ram 51 | 52 | _etext = .; 53 | 54 | .data : ALIGN(4) 55 | { 56 | . = ALIGN(4); 57 | *(.data) 58 | *(.data.*) 59 | *(.ramtext) 60 | . = ALIGN(4); 61 | } > ram 62 | 63 | .bss (NOLOAD) : ALIGN(4) 64 | { 65 | . = ALIGN(4); 66 | _bss_start = .; 67 | *(.bss) 68 | *(.bss.*) 69 | *(COMMON) 70 | . = ALIGN(4); 71 | _bss_end = .; 72 | } > ram 73 | 74 | .noinit (NOLOAD) : ALIGN(4) 75 | { 76 | __noinit_start__ = .; 77 | *(.noinit .noinit.*) 78 | . = ALIGN(4) ; 79 | __noinit_end__ = .; 80 | } > ram 81 | 82 | end = .; 83 | 84 | 85 | /* 86 | .heap (NOLOAD) : 87 | { 88 | . = ALIGN(4); 89 | __heap_start__ = .; 90 | __heap_base__ = .; 91 | . = ORIGIN(HEAP_RAM) + LENGTH(HEAP_RAM); 92 | __heap_end__ = .; 93 | } > ram 94 | */ 95 | 96 | 97 | /* 98 | .rodata : { 99 | *(.rodata*); 100 | } > ram 101 | .bss : { 102 | *(.bss*); 103 | } > ram 104 | */ 105 | } 106 | 107 | -------------------------------------------------------------------------------- /example/blue_pill/ugui/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | 10 | void setupPrescaler(int pllmul) { 11 | // enable high speed external oscillator 12 | RCC->CR = (RCC->CR & ~RCC_CR_HSEBYP) | RCC_CR_HSEON; 13 | while (!(RCC->CR & RCC_CR_HSERDY)) { 14 | ; 15 | } 16 | 17 | RCC->CFGR = (pllmul-2) << 18 | RCC_CFGR_PLLSRC | RCC_CFGR_PPRE1_DIV2; 18 | RCC->CR |= RCC_CR_PLLON; 19 | 20 | while (!(RCC->CR & RCC_CR_PLLRDY)) { 21 | ; 22 | } 23 | 24 | if (RCC->APB2ENR & RCC_APB2ENR_USART1EN) { 25 | // if usart1 is clocked wait to drain possible debugging infos. 26 | while ((USART1->SR & (USART_SR_TXE | USART_SR_TC)) != (USART_SR_TXE | USART_SR_TC)) { 27 | ; 28 | } 29 | } 30 | 31 | // switch sysclock to pll 32 | RCC->CFGR |= RCC_CFGR_SW_PLL; 33 | 34 | // wait for ack 35 | while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_PLL) { 36 | ; 37 | } 38 | } 39 | 40 | 41 | void st7789_GPIOInit(void) { 42 | // Enable GPIOA and SPI1 clock 43 | RCC->APB2ENR |= RCC_APB2ENR_IOPAEN | RCC_APB2ENR_SPI1EN; 44 | // Enable DMA1 channel 45 | RCC->AHBENR |= RCC_AHBENR_DMA1EN; 46 | 47 | // Enable SPI 48 | ST7789_SPI->SR = 0; 49 | // Reverse polarity? 50 | ST7789_SPI->CR1 = \ 51 | SPI_CR1_SSM | \ 52 | SPI_CR1_SSI | \ 53 | SPI_CR1_MSTR | \ 54 | SPI_CR1_CPOL | \ 55 | SPI_CR1_BIDIMODE | \ 56 | SPI_CR1_BIDIOE; 57 | ST7789_SPI->CR1 |= SPI_CR1_SPE; 58 | 59 | // DC and RST signals 60 | // Maximum output speed 61 | ST7789_DC_PORT->CRH |= GPIO_CRH_MODE8; 62 | ST7789_RST_PORT->CRH |= GPIO_CRH_MODE9; 63 | // Output push pull 64 | ST7789_DC_PORT->CRH &= ~(GPIO_CRH_CNF8); 65 | ST7789_RST_PORT->CRH &= ~(GPIO_CRH_CNF9); 66 | 67 | // SPI pins 68 | // Maximum output speed on PA5/PA7 69 | GPIOA->CRL |= GPIO_CRL_MODE5; 70 | GPIOA->CRL |= GPIO_CRL_MODE7; 71 | // Alternate mode on PA5/PA7 72 | GPIOA->CRL = (GPIOA->CRL & ~(GPIO_CRL_CNF5)) | (GPIO_CRL_CNF5_1); 73 | GPIOA->CRL = (GPIOA->CRL & ~(GPIO_CRL_CNF7)) | (GPIO_CRL_CNF7_1); 74 | } 75 | 76 | 77 | void UG_Driver_PushPixel(UG_COLOR color) { 78 | st7789_WriteDMA(&color, 2); 79 | st7789_WaitForDMA(); 80 | } 81 | 82 | 83 | void UG_Driver_SetPixel(UG_S16 x, UG_S16 y, UG_COLOR color) { 84 | st7789_SetWindow(x, y, x, y); 85 | st7789_WriteDMA(&color, 2); 86 | st7789_WaitForDMA(); 87 | st7789_SetWindow(0, 0, ST7789_LCD_WIDTH, ST7789_LCD_HEIGHT); 88 | } 89 | 90 | 91 | UG_RESULT UG_Driver_FillFrame(UG_S16 x1, UG_S16 y1, UG_S16 x2, UG_S16 y2, UG_COLOR color) { 92 | st7789_FillArea(color, x1, y1, x2, y2); 93 | return UG_RESULT_OK; 94 | } 95 | 96 | 97 | void(*UG_Driver_FillArea(UG_S16 x1, UG_S16 y1, UG_S16 x2, UG_S16 y2))(UG_COLOR) { 98 | st7789_SetWindow(x1, y1, x2, y2); 99 | return UG_Driver_PushPixel; 100 | } 101 | 102 | 103 | int main(void) { 104 | setupPrescaler(16); 105 | 106 | st7789_GPIOInit(); 107 | st7789_Reset(); 108 | st7789_Init_1_3_LCD(); 109 | 110 | UG_GUI gui; 111 | UG_Init(&gui, UG_Driver_SetPixel, ST7789_LCD_WIDTH, ST7789_LCD_HEIGHT); 112 | UG_SelectGUI(&gui); 113 | 114 | //UG_DriverRegister(DRIVER_DRAW_LINE, (void *) UG_Driver_DrawLine); 115 | UG_DriverRegister(DRIVER_FILL_FRAME, (void *) UG_Driver_FillFrame); 116 | UG_DriverRegister(DRIVER_FILL_AREA, (void *) UG_Driver_FillArea); 117 | //UG_DriverEnable(DRIVER_DRAW_LINE); 118 | UG_DriverEnable(DRIVER_FILL_FRAME); 119 | UG_DriverEnable(DRIVER_FILL_AREA); 120 | 121 | UG_FillFrame(0, 0, ST7789_LCD_WIDTH, ST7789_LCD_HEIGHT, C_BLACK); 122 | /* Draw text with uGUI */ 123 | UG_FontSelect(&FONT_8X14); 124 | UG_ConsoleSetArea(0, 0, ST7789_LCD_WIDTH, ST7789_LCD_HEIGHT); 125 | UG_ConsoleSetBackcolor(C_BLACK); 126 | UG_ConsoleSetForecolor(C_RED); 127 | UG_ConsolePutString("Beginning System Initialization...\n"); 128 | UG_ConsoleSetForecolor(C_GREEN); 129 | UG_ConsolePutString("System Initialization Complete\n"); 130 | 131 | for(;;) { 132 | } 133 | return 0; 134 | } 135 | -------------------------------------------------------------------------------- /example/blue_pill/ugui/run.gdb: -------------------------------------------------------------------------------- 1 | target remote localhost:3333 2 | monitor arm semihosting enable 3 | monitor reset halt 4 | 5 | load 6 | continue 7 | -------------------------------------------------------------------------------- /example/blue_pill/ugui/startup.s: -------------------------------------------------------------------------------- 1 | .syntax unified 2 | .cpu cortex-m3 3 | .fpu softvfp 4 | .thumb 5 | 6 | .section .text.startup_ 7 | 8 | 9 | .thumb_func 10 | .global start_ 11 | start_: 12 | ldr r0, stacktop 13 | mov sp, r0 14 | ldr r2, =_bss_start 15 | b loop_zero_bss 16 | zero_bss: 17 | movs r3, #0x00 18 | str r3, [r2], #0x04 19 | loop_zero_bss: 20 | ldr r3, = _bss_end 21 | cmp r2, r3 22 | bcc zero_bss 23 | bl main 24 | b hang 25 | 26 | .thumb_func 27 | hang: 28 | b . 29 | 30 | .align 31 | stacktop: .word 0x20005000 32 | 33 | .end 34 | -------------------------------------------------------------------------------- /example/blue_pill/ugui/utils: -------------------------------------------------------------------------------- 1 | ../../../utils -------------------------------------------------------------------------------- /example/blue_pill/ugui/vendor/cmsis: -------------------------------------------------------------------------------- 1 | ../../../../vendor/cmsis -------------------------------------------------------------------------------- /example/blue_pill/ugui/vendor/uGUI/system.h: -------------------------------------------------------------------------------- 1 | #include 2 | -------------------------------------------------------------------------------- /example/blue_pill/ugui/vendor/uGUI/ugui.c: -------------------------------------------------------------------------------- 1 | ../../../../../vendor/uGUI/ugui.c -------------------------------------------------------------------------------- /example/blue_pill/ugui/vendor/uGUI/ugui.h: -------------------------------------------------------------------------------- 1 | ../../../../../vendor/uGUI/ugui.h -------------------------------------------------------------------------------- /example/blue_pill/ugui/vendor/uGUI/ugui_config.h: -------------------------------------------------------------------------------- 1 | #ifndef __UGUI_CONFIG_H 2 | #define __UGUI_CONFIG_H 3 | 4 | /* -------------------------------------------------------------------------------- */ 5 | /* -- CONFIG SECTION -- */ 6 | /* -------------------------------------------------------------------------------- */ 7 | 8 | //#define USE_MULTITASKING 9 | 10 | /* Enable color mode */ 11 | //#define USE_COLOR_RGB888 // RGB = 0xFF,0xFF,0xFF 12 | #define USE_COLOR_RGB565 // RGB = 0bRRRRRGGGGGGBBBBB 13 | 14 | /* Enable needed fonts here */ 15 | //#define USE_FONT_4X6 16 | //#define USE_FONT_5X8 17 | //#define USE_FONT_5X12 18 | //#define USE_FONT_6X8 19 | //#define USE_FONT_6X10 20 | //#define USE_FONT_7X12 21 | //#define USE_FONT_8X8 22 | //#define USE_FONT_8X12_CYRILLIC 23 | //#define USE_FONT_8X12 24 | //#define USE_FONT_8X12 25 | #define USE_FONT_8X14 26 | //#define USE_FONT_10X16 27 | //#define USE_FONT_12X16 28 | //#define USE_FONT_12X20 29 | //#define USE_FONT_16X26 30 | //#define USE_FONT_22X36 31 | //#define USE_FONT_24X40 32 | //#define USE_FONT_32X53 33 | 34 | /* Specify platform-dependent integer types here */ 35 | 36 | #define __UG_FONT_DATA const 37 | typedef uint8_t UG_U8; 38 | typedef int8_t UG_S8; 39 | typedef uint16_t UG_U16; 40 | typedef int16_t UG_S16; 41 | typedef uint32_t UG_U32; 42 | typedef int32_t UG_S32; 43 | 44 | 45 | /* Example for dsPIC33 46 | typedef unsigned char UG_U8; 47 | typedef signed char UG_S8; 48 | typedef unsigned int UG_U16; 49 | typedef signed int UG_S16; 50 | typedef unsigned long int UG_U32; 51 | typedef signed long int UG_S32; 52 | */ 53 | 54 | /* -------------------------------------------------------------------------------- */ 55 | /* -------------------------------------------------------------------------------- */ 56 | 57 | 58 | /* Feature enablers */ 59 | #define USE_PRERENDER_EVENT 60 | #define USE_POSTRENDER_EVENT 61 | 62 | 63 | #endif 64 | -------------------------------------------------------------------------------- /lib/st7789.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "st7789.h" 6 | 7 | 8 | #define LCD_FILL_BUFFER_SIZE 64 9 | 10 | 11 | // Weak attribute to allow override 12 | void __attribute__((weak)) st7789_WaitNanosecs(uint32_t ns) { 13 | int ctr = ((ST7789_PRESCALER * ST7789_OSC_MHZ) * ns / 6); 14 | while (ctr) { 15 | __asm__ volatile ("nop"); 16 | --ctr; 17 | } 18 | } 19 | 20 | 21 | void st7789_Reset(void) { 22 | ST7789_RST_PORT->ODR &= ~ST7789_RST_PIN; 23 | st7789_WaitNanosecs(10000); // Reset pulse time 24 | ST7789_RST_PORT->ODR |= ST7789_RST_PIN; 25 | st7789_WaitNanosecs(120000); // Maximum time of blanking sequence 26 | } 27 | 28 | 29 | void st7789_StartCommand(void) { 30 | //st7789_WaitNanosecs(10); // D/CX setup time 31 | ST7789_DC_PORT->ODR &= ~ST7789_DC_PIN; 32 | } 33 | 34 | 35 | void st7789_StartData(void) { 36 | //st7789_WaitNanosecs(10); // D/CX setup time 37 | ST7789_DC_PORT->ODR |= ST7789_DC_PIN; 38 | } 39 | 40 | 41 | void st7789_WriteSpi(uint8_t data) { 42 | for (int32_t i = 0; i<10000; i++) { 43 | if (ST7789_SPI->SR & SPI_SR_TXE) break; 44 | } 45 | ST7789_SPI->DR = data; 46 | while (ST7789_SPI->SR & SPI_SR_BSY); 47 | } 48 | 49 | 50 | void st7789_ReadSpi(uint8_t *data, size_t length) { 51 | // Disable SPI output 52 | ST7789_SPI->CR1 &= ~(SPI_CR1_BIDIOE); 53 | uint8_t dummy = 0; 54 | 55 | /* 56 | clockPulse(); // ??? 57 | GPIOA->CRL = (GPIOA->CRL & ~(GPIO_CRL_CNF5)); 58 | for (size_t i = 0; i < 1; ++i) { 59 | st7789_WaitNanosecs(10); 60 | GPIOA->ODR |= GPIO_ODR_ODR5; 61 | st7789_WaitNanosecs(10); 62 | } 63 | GPIOA->CRL = (GPIOA->CRL & ~(GPIO_CRL_CNF5)) | (GPIO_CRL_CNF5_1); 64 | */ 65 | 66 | while (length--) { 67 | while (!(ST7789_SPI->SR & SPI_SR_TXE)); 68 | ST7789_SPI->DR = dummy; 69 | while (!(ST7789_SPI->SR & SPI_SR_RXNE)); 70 | *data++ = ST7789_SPI->DR; 71 | } 72 | while (ST7789_SPI->SR & SPI_SR_BSY); 73 | 74 | // Enable SPI output 75 | ST7789_SPI->CR1 |= SPI_CR1_BIDIOE; 76 | } 77 | 78 | 79 | void __attribute__((weak)) st7789_WriteDMA(void *data, uint16_t length) { 80 | ST7789_DMA->CCR = (DMA_CCR1_MINC | DMA_CCR1_DIR); // Memory increment, direction to peripherial 81 | ST7789_DMA->CMAR = (uint32_t)data; // Source address 82 | ST7789_DMA->CPAR = (uint32_t)&ST7789_SPI->DR; // Destination address 83 | ST7789_DMA->CNDTR = length; 84 | ST7789_SPI->CR1 &= ~(SPI_CR1_SPE); // Disable SPI 85 | ST7789_SPI->CR2 |= SPI_CR2_TXDMAEN; // Enable DMA transfer 86 | ST7789_SPI->CR1 |= SPI_CR1_SPE; // Enable SPI 87 | ST7789_DMA->CCR |= DMA_CCR1_EN; // Start DMA transfer 88 | } 89 | 90 | 91 | void st7789_WaitForDMA(void) { 92 | while(ST7789_DMA->CNDTR); 93 | } 94 | 95 | void st7789_ReadCommand(uint8_t command, void *data, size_t length) { 96 | st7789_StartCommand(); 97 | st7789_WriteSpi(command); 98 | st7789_StartData(); 99 | st7789_ReadSpi((void *)data, length); 100 | } 101 | 102 | 103 | void st7789_WriteCommand(uint8_t command, const void *data, size_t length) { 104 | st7789_StartCommand(); 105 | st7789_WriteSpi(command); 106 | st7789_StartData(); 107 | for (size_t i = 0; i < length; ++i) { 108 | st7789_WriteSpi(((const uint8_t *)data)[i]); 109 | } 110 | } 111 | 112 | 113 | void st7789_RunCommand(const st7789_Command *command) { 114 | st7789_StartCommand(); 115 | st7789_WriteSpi(command->command); 116 | if (command->dataSize > 0) { 117 | st7789_StartData(); 118 | for (uint8_t i = 0; i < command->dataSize; ++i) { 119 | st7789_WriteSpi(command->data[i]); 120 | } 121 | } 122 | if (command->waitMs > 0) { 123 | st7789_WaitNanosecs(command->waitMs * 1000); 124 | } 125 | } 126 | 127 | 128 | void st7789_RunCommands(const st7789_Command *sequence) { 129 | while (sequence->command != ST7789_CMDLIST_END) { 130 | st7789_RunCommand(sequence); 131 | sequence++; 132 | } 133 | } 134 | 135 | 136 | void st7789_Init_1_3_LCD(void) { 137 | // Resolution 138 | const uint8_t caset[4] = { 139 | 0x00, 140 | 0x00, 141 | (ST7789_LCD_WIDTH - 1) >> 8, 142 | (ST7789_LCD_WIDTH - 1) & 0xff 143 | }; 144 | const uint8_t raset[4] = { 145 | 0x00, 146 | 0x00, 147 | (ST7789_LCD_HEIGHT - 1) >> 8, 148 | (ST7789_LCD_HEIGHT - 1) & 0xff 149 | }; 150 | const st7789_Command initSequence[] = { 151 | // Sleep 152 | {ST7789_CMD_SLPIN, 10, 0, NULL}, // Sleep 153 | {ST7789_CMD_SWRESET, 200, 0, NULL}, // Reset 154 | {ST7789_CMD_SLPOUT, 120, 0, NULL}, // Sleep out 155 | {ST7789_CMD_MADCTL, 0, 1, (const uint8_t *)"\x00"}, // Page / column address order 156 | {ST7789_CMD_COLMOD, 0, 1, (const uint8_t *)"\x55"}, // 16 bit RGB 157 | {ST7789_CMD_INVON, 0, 0, NULL}, // Inversion on 158 | {ST7789_CMD_CASET, 0, 4, (const uint8_t *)&caset}, // Set width 159 | {ST7789_CMD_RASET, 0, 4, (const uint8_t *)&raset}, // Set height 160 | // Porch setting 161 | {ST7789_CMD_PORCTRL, 0, 5, (const uint8_t *)"\x0c\x0c\x00\x33\x33"}, 162 | // Set VGH to 13.26V and VGL to -10.43V 163 | {ST7789_CMD_GCTRL, 0, 1, (const uint8_t *)"\x35"}, 164 | // Set VCOM to 1.675V 165 | {ST7789_CMD_VCOMS, 0, 1, (const uint8_t *)"\x1f"}, 166 | // LCM control 167 | {ST7789_CMD_LCMCTRL, 0, 1, (const uint8_t *)"\x2c"}, 168 | // VDV/VRH command enable 169 | {ST7789_CMD_VDVVRHEN, 0, 2, (const uint8_t *)"\x01\xc3"}, 170 | // VDV set to default value 171 | {ST7789_CMD_VDVSET, 0, 1, (const uint8_t *)"\x20"}, 172 | // Set frame rate to 60Hz 173 | {ST7789_CMD_FRCTR2, 0, 1, (const uint8_t *)"\x0f"}, 174 | // Set VDS to 2.3V, AVCL to -4.8V and AVDD to 6.8V 175 | {ST7789_CMD_PWCTRL1, 0, 2, (const uint8_t *)"\xa4\xa1"}, 176 | // Gamma corection 177 | //{ST7789_CMD_PVGAMCTRL, 0, 14, (const uint8_t *)"\xd0\x08\x11\x08\x0c\x15\x39\x33\x50\x36\x13\x14\x29\x2d"}, 178 | //{ST7789_CMD_NVGAMCTRL, 0, 14, (const uint8_t *)"\xd0\x08\x10\x08\x06\x06\x39\x44\x51\x0b\x16\x14\x2f\x31"}, 179 | // Little endian 180 | {ST7789_CMD_RAMCTRL, 0, 2, (const uint8_t *)"\x00\x08"}, 181 | {ST7789_CMDLIST_END, 0, 0, NULL}, // End of commands 182 | }; 183 | st7789_RunCommands(initSequence); 184 | st7789_Clear(0x0000); 185 | const st7789_Command initSequence2[] = { 186 | {ST7789_CMD_DISPON, 100, 0, NULL}, // Display on 187 | {ST7789_CMD_SLPOUT, 100, 0, NULL}, // Sleep out 188 | {ST7789_CMD_TEON, 0, 0, NULL}, // Tearing line effect on 189 | {ST7789_CMDLIST_END, 0, 0, NULL}, // End of commands 190 | }; 191 | st7789_RunCommands(initSequence2); 192 | } 193 | 194 | 195 | void st7789_StartMemoryWrite(void) { 196 | st7789_StartCommand(); 197 | st7789_WriteSpi(ST7789_CMD_RAMWR); 198 | st7789_StartData(); 199 | } 200 | 201 | 202 | void st7789_SetWindow(uint16_t xStart, uint16_t yStart, uint16_t xEnd, uint16_t yEnd) { 203 | uint8_t caset[4]; 204 | uint8_t raset[4]; 205 | caset[0] = (uint8_t)(xStart >> 8); 206 | caset[1] = (uint8_t)(xStart & 0xff); 207 | caset[2] = (uint8_t)(xEnd >> 8); 208 | caset[3] = (uint8_t)(xEnd & 0xff); 209 | raset[0] = (uint8_t)(yStart >> 8); 210 | raset[1] = (uint8_t)(yStart & 0xff); 211 | raset[2] = (uint8_t)(yEnd >> 8); 212 | raset[3] = (uint8_t)(yEnd & 0xff); 213 | st7789_Command sequence[] = { 214 | {ST7789_CMD_CASET, 0, 4, caset}, 215 | {ST7789_CMD_RASET, 0, 4, raset}, 216 | {ST7789_CMD_RAMWR, 0, 0, NULL}, 217 | {ST7789_CMDLIST_END, 0, 0, NULL}, 218 | }; 219 | st7789_StartCommand(); 220 | st7789_RunCommands(sequence); 221 | st7789_StartData(); 222 | } 223 | 224 | 225 | void st7789_FillArea(uint16_t color, uint16_t startX, uint16_t startY, uint16_t width, uint16_t height) { 226 | uint16_t buf[LCD_FILL_BUFFER_SIZE]; 227 | for (size_t i = 0; i < LCD_FILL_BUFFER_SIZE; i++) { 228 | buf[i] = color; 229 | } 230 | st7789_SetWindow(startX, startY, startX + width - 1, startY + height - 1); 231 | size_t bytestToWrite = width * height * 2; 232 | uint16_t transferSize = (uint16_t)LCD_FILL_BUFFER_SIZE * 2; 233 | while (bytestToWrite > 0) { 234 | if (bytestToWrite < transferSize) { 235 | transferSize = bytestToWrite; 236 | } 237 | bytestToWrite -= transferSize; 238 | st7789_WriteDMA(&buf, transferSize); 239 | st7789_WaitForDMA(); 240 | } 241 | } 242 | 243 | 244 | void st7789_Clear(uint16_t color) { 245 | st7789_FillArea(color, 0, 0, ST7789_LCD_WIDTH, ST7789_LCD_HEIGHT); 246 | } 247 | 248 | 249 | uint16_t st7789_RGBToColor(uint8_t r, uint8_t g, uint8_t b) { 250 | return (((uint16_t)r >> 3) << 11) | (((uint16_t)g >> 2) << 5) | ((uint16_t)b >> 3); 251 | } 252 | -------------------------------------------------------------------------------- /lib/st7789.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | 5 | #define ST7789_RST_PORT GPIOA 6 | #define ST7789_RST_PIN GPIO_ODR_ODR9 7 | #define ST7789_DC_PORT GPIOA 8 | #define ST7789_DC_PIN GPIO_ODR_ODR8 9 | #define ST7789_SPI SPI1 10 | #define ST7789_DMA DMA1_Channel3 11 | 12 | #define ST7789_PRESCALER 16 13 | #define ST7789_OSC_MHZ 8 14 | 15 | #define ST7789_LCD_WIDTH 240 16 | #define ST7789_LCD_HEIGHT 240 17 | 18 | // System Function Command Table 1 19 | #define ST7789_CMD_NOP 0x00 // No operation 20 | #define ST7789_CMD_SWRESET 0x01 // Software reset 21 | #define ST7789_CMD_RDDID 0x04 // Read display ID 22 | #define ST7789_CMD_RDDST 0x09 // Read display status 23 | #define ST7789_CMD_RDDPM 0x0a // Read display power 24 | #define ST7789_CMD_RDDMADCTL 0x0b // Read display 25 | #define ST7789_CMD_RDDCOLMOD 0x0c // Read display pixel 26 | #define ST7789_CMD_RDDIM 0x0d // Read display image 27 | #define ST7789_CMD_RDDSM 0x0e // Read display signal 28 | #define ST7789_CMD_RDDSDR 0x0f // Read display self-diagnostic result 29 | #define ST7789_CMD_SLPIN 0x10 // Sleep in 30 | #define ST7789_CMD_SLPOUT 0x11 // Sleep out 31 | #define ST7789_CMD_PTLON 0x12 // Partial mode on 32 | #define ST7789_CMD_NORON 0x13 // Partial off (Normal) 33 | #define ST7789_CMD_INVOFF 0x20 // Display inversion off 34 | #define ST7789_CMD_INVON 0x21 // Display inversion on 35 | #define ST7789_CMD_GAMSET 0x26 // Gamma set 36 | #define ST7789_CMD_DISPOFF 0x28 // Display off 37 | #define ST7789_CMD_DISPON 0x29 // Display on 38 | #define ST7789_CMD_CASET 0x2a // Column address set 39 | #define ST7789_CMD_RASET 0x2b // Row address set 40 | #define ST7789_CMD_RAMWR 0x2c // Memory write 41 | #define ST7789_CMD_RAMRD 0x2e // Memory read 42 | #define ST7789_CMD_PTLAR 0x30 // Partial start/end address set 43 | #define ST7789_CMD_VSCRDEF 0x33 // Vertical scrolling definition 44 | #define ST7789_CMD_TEOFF 0x34 // Tearing line effect off 45 | #define ST7789_CMD_TEON 0x35 // Tearing line effect on 46 | #define ST7789_CMD_MADCTL 0x36 // Memory data access control 47 | #define ST7789_CMD_VSCRSADD 0x37 // Vertical address scrolling 48 | #define ST7789_CMD_IDMOFF 0x38 // Idle mode off 49 | #define ST7789_CMD_IDMON 0x39 // Idle mode on 50 | #define ST7789_CMD_COLMOD 0x3a // Interface pixel format 51 | #define ST7789_CMD_RAMWRC 0x3c // Memory write continue 52 | #define ST7789_CMD_RAMRDC 0x3e // Memory read continue 53 | #define ST7789_CMD_TESCAN 0x44 // Set tear scanline 54 | #define ST7789_CMD_RDTESCAN 0x45 // Get scanline 55 | #define ST7789_CMD_WRDISBV 0x51 // Write display brightness 56 | #define ST7789_CMD_RDDISBV 0x52 // Read display brightness value 57 | #define ST7789_CMD_WRCTRLD 0x53 // Write CTRL display 58 | #define ST7789_CMD_RDCTRLD 0x54 // Read CTRL value display 59 | #define ST7789_CMD_WRCACE 0x55 // Write content adaptive brightness control and Color enhancemnet 60 | #define ST7789_CMD_RDCABC 0x56 // Read content adaptive brightness control 61 | #define ST7789_CMD_WRCABCMB 0x5e // Write CABC minimum brightness 62 | #define ST7789_CMD_RDCABCMB 0x5f // Read CABC minimum brightness 63 | #define ST7789_CMD_RDABCSDR 0x68 // Read Automatic Brightness Control Self-Diagnostic Result 64 | #define ST7789_CMD_RDID1 0xda // Read ID1 65 | #define ST7789_CMD_RDID2 0xdb // Read ID2 66 | #define ST7789_CMD_RDID3 0xdc // Read ID3 67 | 68 | // System Function Command Table 2 69 | #define ST7789_CMD_RAMCTRL 0xb0 // RAM Control 70 | #define ST7789_CMD_RGBCTRL 0xb1 // RGB Control 71 | #define ST7789_CMD_PORCTRL 0xb2 // Porch control 72 | #define ST7789_CMD_FRCTRL1 0xb3 // Frame Rate Control 1 73 | #define ST7789_CMD_GCTRL 0xb7 // Gate control 74 | #define ST7789_CMD_DGMEN 0xba // Digital Gamma Enable 75 | #define ST7789_CMD_VCOMS 0xbb // VCOM Setting 76 | #define ST7789_CMD_LCMCTRL 0xc0 // LCM Control 77 | #define ST7789_CMD_IDSET 0xc1 // ID Setting 78 | #define ST7789_CMD_VDVVRHEN 0xc2 // VDV and VRH Command enable 79 | #define ST7789_CMD_VRHS 0xc3 // VRH Set 80 | #define ST7789_CMD_VDVSET 0xc4 // VDV Setting 81 | #define ST7789_CMD_VCMOFSET 0xc5 // VCOM Offset Set 82 | #define ST7789_CMD_FRCTR2 0xc6 // FR Control 2 83 | #define ST7789_CMD_CABCCTRL 0xc7 // CABC Control 84 | #define ST7789_CMD_REGSEL1 0xc8 // Register value selection 1 85 | #define ST7789_CMD_REGSEL2 0xca // Register value selection 2 86 | #define ST7789_CMD_PWMFRSEL 0xcc // PWM Frequency Selection 87 | #define ST7789_CMD_PWCTRL1 0xd0 // Power Control 1 88 | #define ST7789_CMD_VAPVANEN 0xd2 // Enable VAP/VAN signal output 89 | #define ST7789_CMD_CMD2EN 0xdf // Command 2 Enable 90 | #define ST7789_CMD_PVGAMCTRL 0xe0 // Positive Voltage Gamma Control 91 | #define ST7789_CMD_NVGAMCTRL 0xe1 // Negative voltage Gamma Control 92 | #define ST7789_CMD_DGMLUTR 0xe2 // Digital Gamma Look-up Table for Red 93 | #define ST7789_CMD_DGMLUTB 0xe3 // Digital Gamma Look-up Table for Blue 94 | #define ST7789_CMD_GATECTRL 0xe4 // Gate control 95 | #define ST7789_CMD_PWCTRL2 0xe8 // Power Control 2 96 | #define ST7789_CMD_EQCTRL 0xe9 // Equalize Time Control 97 | #define ST7789_CMD_PROMCTRL 0xec // Program Control 98 | #define ST7789_CMD_PROMEN 0xfa // Program Mode Enable 99 | #define ST7789_CMD_NVMSET 0xfc // NVM Setting 100 | #define ST7789_CMD_PROMACT 0xfe // Program Action 101 | 102 | #define ST7789_CMDLIST_END 0xff // End command (used for command list) 103 | 104 | 105 | typedef struct st7789_Command { 106 | uint8_t command; 107 | uint8_t waitMs; 108 | uint8_t dataSize; 109 | const uint8_t *data; 110 | } st7789_Command; 111 | 112 | void st7789_WaitNanosecs(uint32_t nanosecs); 113 | void st7789_Reset(void); 114 | void st7789_StartCommand(void); 115 | void st7789_StartData(void); 116 | void st7789_WriteSpi(uint8_t data); 117 | void st7789_ReadSpi(uint8_t *data, size_t length); 118 | void st7789_WriteDMA(void *data, uint16_t length); 119 | void st7789_WaitForDMA(void); 120 | void st7789_ReadCommand(uint8_t command, void *data, size_t length); 121 | void st7789_WriteCommand(uint8_t command, const void *data, size_t length); 122 | void st7789_RunCommand(const st7789_Command *command); 123 | void st7789_RunCommands(const st7789_Command *sequence); 124 | void st7789_Init_1_3_LCD(void); 125 | void st7789_StartMemoryWrite(void); 126 | void st7789_SetWindow(uint16_t xStart, uint16_t yStart, uint16_t xEnd, uint16_t yEnd); 127 | void st7789_FillArea(uint16_t color, uint16_t startX, uint16_t startY, uint16_t width, uint16_t height); 128 | void st7789_Clear(uint16_t color); 129 | uint16_t st7789_RGBToColor(uint8_t r, uint8_t g, uint8_t b); 130 | -------------------------------------------------------------------------------- /utils/svc.c: -------------------------------------------------------------------------------- 1 | #include "svc.h" 2 | 3 | void *svcCall(int command, const void *message) { 4 | void *output; 5 | __asm volatile 6 | ( 7 | "mov r0, %[com] \n" 8 | "mov r1, %[msg] \n" 9 | "bkpt #0xAB \n" 10 | "mov %[out], r0" 11 | : [out] "=r" (output) 12 | : [com] "r" (command), [msg] "r" (message) 13 | : "r0", "r1" 14 | ); 15 | return output; 16 | } 17 | 18 | 19 | void svcWrite0(const char *message) { 20 | svcCall(0x04, message); 21 | } 22 | -------------------------------------------------------------------------------- /utils/svc.h: -------------------------------------------------------------------------------- 1 | void *svcCall(int command, const void *message); 2 | void svcWrite0(const char *message); 3 | -------------------------------------------------------------------------------- /vendor/cmsis/cmsis_compiler.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************//** 2 | * @file cmsis_compiler.h 3 | * @brief CMSIS compiler generic header file 4 | * @version V5.0.4 5 | * @date 10. January 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 (armclang) 39 | */ 40 | #elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) 41 | #include "cmsis_armclang.h" 42 | 43 | 44 | /* 45 | * GNU Compiler 46 | */ 47 | #elif defined ( __GNUC__ ) 48 | #include "cmsis_gcc.h" 49 | 50 | 51 | /* 52 | * IAR Compiler 53 | */ 54 | #elif defined ( __ICCARM__ ) 55 | #include 56 | 57 | 58 | /* 59 | * TI Arm Compiler 60 | */ 61 | #elif defined ( __TI_ARM__ ) 62 | #include 63 | 64 | #ifndef __ASM 65 | #define __ASM __asm 66 | #endif 67 | #ifndef __INLINE 68 | #define __INLINE inline 69 | #endif 70 | #ifndef __STATIC_INLINE 71 | #define __STATIC_INLINE static inline 72 | #endif 73 | #ifndef __STATIC_FORCEINLINE 74 | #define __STATIC_FORCEINLINE __STATIC_INLINE 75 | #endif 76 | #ifndef __NO_RETURN 77 | #define __NO_RETURN __attribute__((noreturn)) 78 | #endif 79 | #ifndef __USED 80 | #define __USED __attribute__((used)) 81 | #endif 82 | #ifndef __WEAK 83 | #define __WEAK __attribute__((weak)) 84 | #endif 85 | #ifndef __PACKED 86 | #define __PACKED __attribute__((packed)) 87 | #endif 88 | #ifndef __PACKED_STRUCT 89 | #define __PACKED_STRUCT struct __attribute__((packed)) 90 | #endif 91 | #ifndef __PACKED_UNION 92 | #define __PACKED_UNION union __attribute__((packed)) 93 | #endif 94 | #ifndef __UNALIGNED_UINT32 /* deprecated */ 95 | struct __attribute__((packed)) T_UINT32 { uint32_t v; }; 96 | #define __UNALIGNED_UINT32(x) (((struct T_UINT32 *)(x))->v) 97 | #endif 98 | #ifndef __UNALIGNED_UINT16_WRITE 99 | __PACKED_STRUCT T_UINT16_WRITE { uint16_t v; }; 100 | #define __UNALIGNED_UINT16_WRITE(addr, val) (void)((((struct T_UINT16_WRITE *)(void*)(addr))->v) = (val)) 101 | #endif 102 | #ifndef __UNALIGNED_UINT16_READ 103 | __PACKED_STRUCT T_UINT16_READ { uint16_t v; }; 104 | #define __UNALIGNED_UINT16_READ(addr) (((const struct T_UINT16_READ *)(const void *)(addr))->v) 105 | #endif 106 | #ifndef __UNALIGNED_UINT32_WRITE 107 | __PACKED_STRUCT T_UINT32_WRITE { uint32_t v; }; 108 | #define __UNALIGNED_UINT32_WRITE(addr, val) (void)((((struct T_UINT32_WRITE *)(void *)(addr))->v) = (val)) 109 | #endif 110 | #ifndef __UNALIGNED_UINT32_READ 111 | __PACKED_STRUCT T_UINT32_READ { uint32_t v; }; 112 | #define __UNALIGNED_UINT32_READ(addr) (((const struct T_UINT32_READ *)(const void *)(addr))->v) 113 | #endif 114 | #ifndef __ALIGNED 115 | #define __ALIGNED(x) __attribute__((aligned(x))) 116 | #endif 117 | #ifndef __RESTRICT 118 | #warning No compiler specific solution for __RESTRICT. __RESTRICT is ignored. 119 | #define __RESTRICT 120 | #endif 121 | 122 | 123 | /* 124 | * TASKING Compiler 125 | */ 126 | #elif defined ( __TASKING__ ) 127 | /* 128 | * The CMSIS functions have been implemented as intrinsics in the compiler. 129 | * Please use "carm -?i" to get an up to date list of all intrinsics, 130 | * Including the CMSIS ones. 131 | */ 132 | 133 | #ifndef __ASM 134 | #define __ASM __asm 135 | #endif 136 | #ifndef __INLINE 137 | #define __INLINE inline 138 | #endif 139 | #ifndef __STATIC_INLINE 140 | #define __STATIC_INLINE static inline 141 | #endif 142 | #ifndef __STATIC_FORCEINLINE 143 | #define __STATIC_FORCEINLINE __STATIC_INLINE 144 | #endif 145 | #ifndef __NO_RETURN 146 | #define __NO_RETURN __attribute__((noreturn)) 147 | #endif 148 | #ifndef __USED 149 | #define __USED __attribute__((used)) 150 | #endif 151 | #ifndef __WEAK 152 | #define __WEAK __attribute__((weak)) 153 | #endif 154 | #ifndef __PACKED 155 | #define __PACKED __packed__ 156 | #endif 157 | #ifndef __PACKED_STRUCT 158 | #define __PACKED_STRUCT struct __packed__ 159 | #endif 160 | #ifndef __PACKED_UNION 161 | #define __PACKED_UNION union __packed__ 162 | #endif 163 | #ifndef __UNALIGNED_UINT32 /* deprecated */ 164 | struct __packed__ T_UINT32 { uint32_t v; }; 165 | #define __UNALIGNED_UINT32(x) (((struct T_UINT32 *)(x))->v) 166 | #endif 167 | #ifndef __UNALIGNED_UINT16_WRITE 168 | __PACKED_STRUCT T_UINT16_WRITE { uint16_t v; }; 169 | #define __UNALIGNED_UINT16_WRITE(addr, val) (void)((((struct T_UINT16_WRITE *)(void *)(addr))->v) = (val)) 170 | #endif 171 | #ifndef __UNALIGNED_UINT16_READ 172 | __PACKED_STRUCT T_UINT16_READ { uint16_t v; }; 173 | #define __UNALIGNED_UINT16_READ(addr) (((const struct T_UINT16_READ *)(const void *)(addr))->v) 174 | #endif 175 | #ifndef __UNALIGNED_UINT32_WRITE 176 | __PACKED_STRUCT T_UINT32_WRITE { uint32_t v; }; 177 | #define __UNALIGNED_UINT32_WRITE(addr, val) (void)((((struct T_UINT32_WRITE *)(void *)(addr))->v) = (val)) 178 | #endif 179 | #ifndef __UNALIGNED_UINT32_READ 180 | __PACKED_STRUCT T_UINT32_READ { uint32_t v; }; 181 | #define __UNALIGNED_UINT32_READ(addr) (((const struct T_UINT32_READ *)(const void *)(addr))->v) 182 | #endif 183 | #ifndef __ALIGNED 184 | #define __ALIGNED(x) __align(x) 185 | #endif 186 | #ifndef __RESTRICT 187 | #warning No compiler specific solution for __RESTRICT. __RESTRICT is ignored. 188 | #define __RESTRICT 189 | #endif 190 | 191 | 192 | /* 193 | * COSMIC Compiler 194 | */ 195 | #elif defined ( __CSMC__ ) 196 | #include 197 | 198 | #ifndef __ASM 199 | #define __ASM _asm 200 | #endif 201 | #ifndef __INLINE 202 | #define __INLINE inline 203 | #endif 204 | #ifndef __STATIC_INLINE 205 | #define __STATIC_INLINE static inline 206 | #endif 207 | #ifndef __STATIC_FORCEINLINE 208 | #define __STATIC_FORCEINLINE __STATIC_INLINE 209 | #endif 210 | #ifndef __NO_RETURN 211 | // NO RETURN is automatically detected hence no warning here 212 | #define __NO_RETURN 213 | #endif 214 | #ifndef __USED 215 | #warning No compiler specific solution for __USED. __USED is ignored. 216 | #define __USED 217 | #endif 218 | #ifndef __WEAK 219 | #define __WEAK __weak 220 | #endif 221 | #ifndef __PACKED 222 | #define __PACKED @packed 223 | #endif 224 | #ifndef __PACKED_STRUCT 225 | #define __PACKED_STRUCT @packed struct 226 | #endif 227 | #ifndef __PACKED_UNION 228 | #define __PACKED_UNION @packed union 229 | #endif 230 | #ifndef __UNALIGNED_UINT32 /* deprecated */ 231 | @packed struct T_UINT32 { uint32_t v; }; 232 | #define __UNALIGNED_UINT32(x) (((struct T_UINT32 *)(x))->v) 233 | #endif 234 | #ifndef __UNALIGNED_UINT16_WRITE 235 | __PACKED_STRUCT T_UINT16_WRITE { uint16_t v; }; 236 | #define __UNALIGNED_UINT16_WRITE(addr, val) (void)((((struct T_UINT16_WRITE *)(void *)(addr))->v) = (val)) 237 | #endif 238 | #ifndef __UNALIGNED_UINT16_READ 239 | __PACKED_STRUCT T_UINT16_READ { uint16_t v; }; 240 | #define __UNALIGNED_UINT16_READ(addr) (((const struct T_UINT16_READ *)(const void *)(addr))->v) 241 | #endif 242 | #ifndef __UNALIGNED_UINT32_WRITE 243 | __PACKED_STRUCT T_UINT32_WRITE { uint32_t v; }; 244 | #define __UNALIGNED_UINT32_WRITE(addr, val) (void)((((struct T_UINT32_WRITE *)(void *)(addr))->v) = (val)) 245 | #endif 246 | #ifndef __UNALIGNED_UINT32_READ 247 | __PACKED_STRUCT T_UINT32_READ { uint32_t v; }; 248 | #define __UNALIGNED_UINT32_READ(addr) (((const struct T_UINT32_READ *)(const void *)(addr))->v) 249 | #endif 250 | #ifndef __ALIGNED 251 | #warning No compiler specific solution for __ALIGNED. __ALIGNED is ignored. 252 | #define __ALIGNED(x) 253 | #endif 254 | #ifndef __RESTRICT 255 | #warning No compiler specific solution for __RESTRICT. __RESTRICT is ignored. 256 | #define __RESTRICT 257 | #endif 258 | 259 | 260 | #else 261 | #error Unknown compiler. 262 | #endif 263 | 264 | 265 | #endif /* __CMSIS_COMPILER_H */ 266 | 267 | -------------------------------------------------------------------------------- /vendor/cmsis/cmsis_gcc.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************//** 2 | * @file cmsis_gcc.h 3 | * @brief CMSIS compiler GCC header file 4 | * @version V5.0.4 5 | * @date 09. April 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_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 | 117 | 118 | /* ########################### Core Function Access ########################### */ 119 | /** \ingroup CMSIS_Core_FunctionInterface 120 | \defgroup CMSIS_Core_RegAccFunctions CMSIS Core Register Access Functions 121 | @{ 122 | */ 123 | 124 | /** 125 | \brief Enable IRQ Interrupts 126 | \details Enables IRQ interrupts by clearing the I-bit in the CPSR. 127 | Can only be executed in Privileged modes. 128 | */ 129 | __STATIC_FORCEINLINE void __enable_irq(void) 130 | { 131 | __ASM volatile ("cpsie i" : : : "memory"); 132 | } 133 | 134 | 135 | /** 136 | \brief Disable IRQ Interrupts 137 | \details Disables IRQ interrupts by setting the I-bit in the CPSR. 138 | Can only be executed in Privileged modes. 139 | */ 140 | __STATIC_FORCEINLINE void __disable_irq(void) 141 | { 142 | __ASM volatile ("cpsid i" : : : "memory"); 143 | } 144 | 145 | 146 | /** 147 | \brief Get Control Register 148 | \details Returns the content of the Control Register. 149 | \return Control Register value 150 | */ 151 | __STATIC_FORCEINLINE uint32_t __get_CONTROL(void) 152 | { 153 | uint32_t result; 154 | 155 | __ASM volatile ("MRS %0, control" : "=r" (result) ); 156 | return(result); 157 | } 158 | 159 | 160 | #if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) 161 | /** 162 | \brief Get Control Register (non-secure) 163 | \details Returns the content of the non-secure Control Register when in secure mode. 164 | \return non-secure Control Register value 165 | */ 166 | __STATIC_FORCEINLINE uint32_t __TZ_get_CONTROL_NS(void) 167 | { 168 | uint32_t result; 169 | 170 | __ASM volatile ("MRS %0, control_ns" : "=r" (result) ); 171 | return(result); 172 | } 173 | #endif 174 | 175 | 176 | /** 177 | \brief Set Control Register 178 | \details Writes the given value to the Control Register. 179 | \param [in] control Control Register value to set 180 | */ 181 | __STATIC_FORCEINLINE void __set_CONTROL(uint32_t control) 182 | { 183 | __ASM volatile ("MSR control, %0" : : "r" (control) : "memory"); 184 | } 185 | 186 | 187 | #if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) 188 | /** 189 | \brief Set Control Register (non-secure) 190 | \details Writes the given value to the non-secure Control Register when in secure state. 191 | \param [in] control Control Register value to set 192 | */ 193 | __STATIC_FORCEINLINE void __TZ_set_CONTROL_NS(uint32_t control) 194 | { 195 | __ASM volatile ("MSR control_ns, %0" : : "r" (control) : "memory"); 196 | } 197 | #endif 198 | 199 | 200 | /** 201 | \brief Get IPSR Register 202 | \details Returns the content of the IPSR Register. 203 | \return IPSR Register value 204 | */ 205 | __STATIC_FORCEINLINE uint32_t __get_IPSR(void) 206 | { 207 | uint32_t result; 208 | 209 | __ASM volatile ("MRS %0, ipsr" : "=r" (result) ); 210 | return(result); 211 | } 212 | 213 | 214 | /** 215 | \brief Get APSR Register 216 | \details Returns the content of the APSR Register. 217 | \return APSR Register value 218 | */ 219 | __STATIC_FORCEINLINE uint32_t __get_APSR(void) 220 | { 221 | uint32_t result; 222 | 223 | __ASM volatile ("MRS %0, apsr" : "=r" (result) ); 224 | return(result); 225 | } 226 | 227 | 228 | /** 229 | \brief Get xPSR Register 230 | \details Returns the content of the xPSR Register. 231 | \return xPSR Register value 232 | */ 233 | __STATIC_FORCEINLINE uint32_t __get_xPSR(void) 234 | { 235 | uint32_t result; 236 | 237 | __ASM volatile ("MRS %0, xpsr" : "=r" (result) ); 238 | return(result); 239 | } 240 | 241 | 242 | /** 243 | \brief Get Process Stack Pointer 244 | \details Returns the current value of the Process Stack Pointer (PSP). 245 | \return PSP Register value 246 | */ 247 | __STATIC_FORCEINLINE uint32_t __get_PSP(void) 248 | { 249 | uint32_t result; 250 | 251 | __ASM volatile ("MRS %0, psp" : "=r" (result) ); 252 | return(result); 253 | } 254 | 255 | 256 | #if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) 257 | /** 258 | \brief Get Process Stack Pointer (non-secure) 259 | \details Returns the current value of the non-secure Process Stack Pointer (PSP) when in secure state. 260 | \return PSP Register value 261 | */ 262 | __STATIC_FORCEINLINE uint32_t __TZ_get_PSP_NS(void) 263 | { 264 | uint32_t result; 265 | 266 | __ASM volatile ("MRS %0, psp_ns" : "=r" (result) ); 267 | return(result); 268 | } 269 | #endif 270 | 271 | 272 | /** 273 | \brief Set Process Stack Pointer 274 | \details Assigns the given value to the Process Stack Pointer (PSP). 275 | \param [in] topOfProcStack Process Stack Pointer value to set 276 | */ 277 | __STATIC_FORCEINLINE void __set_PSP(uint32_t topOfProcStack) 278 | { 279 | __ASM volatile ("MSR psp, %0" : : "r" (topOfProcStack) : ); 280 | } 281 | 282 | 283 | #if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) 284 | /** 285 | \brief Set Process Stack Pointer (non-secure) 286 | \details Assigns the given value to the non-secure Process Stack Pointer (PSP) when in secure state. 287 | \param [in] topOfProcStack Process Stack Pointer value to set 288 | */ 289 | __STATIC_FORCEINLINE void __TZ_set_PSP_NS(uint32_t topOfProcStack) 290 | { 291 | __ASM volatile ("MSR psp_ns, %0" : : "r" (topOfProcStack) : ); 292 | } 293 | #endif 294 | 295 | 296 | /** 297 | \brief Get Main Stack Pointer 298 | \details Returns the current value of the Main Stack Pointer (MSP). 299 | \return MSP Register value 300 | */ 301 | __STATIC_FORCEINLINE uint32_t __get_MSP(void) 302 | { 303 | uint32_t result; 304 | 305 | __ASM volatile ("MRS %0, msp" : "=r" (result) ); 306 | return(result); 307 | } 308 | 309 | 310 | #if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) 311 | /** 312 | \brief Get Main Stack Pointer (non-secure) 313 | \details Returns the current value of the non-secure Main Stack Pointer (MSP) when in secure state. 314 | \return MSP Register value 315 | */ 316 | __STATIC_FORCEINLINE uint32_t __TZ_get_MSP_NS(void) 317 | { 318 | uint32_t result; 319 | 320 | __ASM volatile ("MRS %0, msp_ns" : "=r" (result) ); 321 | return(result); 322 | } 323 | #endif 324 | 325 | 326 | /** 327 | \brief Set Main Stack Pointer 328 | \details Assigns the given value to the Main Stack Pointer (MSP). 329 | \param [in] topOfMainStack Main Stack Pointer value to set 330 | */ 331 | __STATIC_FORCEINLINE void __set_MSP(uint32_t topOfMainStack) 332 | { 333 | __ASM volatile ("MSR msp, %0" : : "r" (topOfMainStack) : ); 334 | } 335 | 336 | 337 | #if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) 338 | /** 339 | \brief Set Main Stack Pointer (non-secure) 340 | \details Assigns the given value to the non-secure Main Stack Pointer (MSP) when in secure state. 341 | \param [in] topOfMainStack Main Stack Pointer value to set 342 | */ 343 | __STATIC_FORCEINLINE void __TZ_set_MSP_NS(uint32_t topOfMainStack) 344 | { 345 | __ASM volatile ("MSR msp_ns, %0" : : "r" (topOfMainStack) : ); 346 | } 347 | #endif 348 | 349 | 350 | #if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) 351 | /** 352 | \brief Get Stack Pointer (non-secure) 353 | \details Returns the current value of the non-secure Stack Pointer (SP) when in secure state. 354 | \return SP Register value 355 | */ 356 | __STATIC_FORCEINLINE uint32_t __TZ_get_SP_NS(void) 357 | { 358 | uint32_t result; 359 | 360 | __ASM volatile ("MRS %0, sp_ns" : "=r" (result) ); 361 | return(result); 362 | } 363 | 364 | 365 | /** 366 | \brief Set Stack Pointer (non-secure) 367 | \details Assigns the given value to the non-secure Stack Pointer (SP) when in secure state. 368 | \param [in] topOfStack Stack Pointer value to set 369 | */ 370 | __STATIC_FORCEINLINE void __TZ_set_SP_NS(uint32_t topOfStack) 371 | { 372 | __ASM volatile ("MSR sp_ns, %0" : : "r" (topOfStack) : ); 373 | } 374 | #endif 375 | 376 | 377 | /** 378 | \brief Get Priority Mask 379 | \details Returns the current state of the priority mask bit from the Priority Mask Register. 380 | \return Priority Mask value 381 | */ 382 | __STATIC_FORCEINLINE uint32_t __get_PRIMASK(void) 383 | { 384 | uint32_t result; 385 | 386 | __ASM volatile ("MRS %0, primask" : "=r" (result) :: "memory"); 387 | return(result); 388 | } 389 | 390 | 391 | #if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) 392 | /** 393 | \brief Get Priority Mask (non-secure) 394 | \details Returns the current state of the non-secure priority mask bit from the Priority Mask Register when in secure state. 395 | \return Priority Mask value 396 | */ 397 | __STATIC_FORCEINLINE uint32_t __TZ_get_PRIMASK_NS(void) 398 | { 399 | uint32_t result; 400 | 401 | __ASM volatile ("MRS %0, primask_ns" : "=r" (result) :: "memory"); 402 | return(result); 403 | } 404 | #endif 405 | 406 | 407 | /** 408 | \brief Set Priority Mask 409 | \details Assigns the given value to the Priority Mask Register. 410 | \param [in] priMask Priority Mask 411 | */ 412 | __STATIC_FORCEINLINE void __set_PRIMASK(uint32_t priMask) 413 | { 414 | __ASM volatile ("MSR primask, %0" : : "r" (priMask) : "memory"); 415 | } 416 | 417 | 418 | #if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) 419 | /** 420 | \brief Set Priority Mask (non-secure) 421 | \details Assigns the given value to the non-secure Priority Mask Register when in secure state. 422 | \param [in] priMask Priority Mask 423 | */ 424 | __STATIC_FORCEINLINE void __TZ_set_PRIMASK_NS(uint32_t priMask) 425 | { 426 | __ASM volatile ("MSR primask_ns, %0" : : "r" (priMask) : "memory"); 427 | } 428 | #endif 429 | 430 | 431 | #if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ 432 | (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ 433 | (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) ) 434 | /** 435 | \brief Enable FIQ 436 | \details Enables FIQ interrupts by clearing the F-bit in the CPSR. 437 | Can only be executed in Privileged modes. 438 | */ 439 | __STATIC_FORCEINLINE void __enable_fault_irq(void) 440 | { 441 | __ASM volatile ("cpsie f" : : : "memory"); 442 | } 443 | 444 | 445 | /** 446 | \brief Disable FIQ 447 | \details Disables FIQ interrupts by setting the F-bit in the CPSR. 448 | Can only be executed in Privileged modes. 449 | */ 450 | __STATIC_FORCEINLINE void __disable_fault_irq(void) 451 | { 452 | __ASM volatile ("cpsid f" : : : "memory"); 453 | } 454 | 455 | 456 | /** 457 | \brief Get Base Priority 458 | \details Returns the current value of the Base Priority register. 459 | \return Base Priority register value 460 | */ 461 | __STATIC_FORCEINLINE uint32_t __get_BASEPRI(void) 462 | { 463 | uint32_t result; 464 | 465 | __ASM volatile ("MRS %0, basepri" : "=r" (result) ); 466 | return(result); 467 | } 468 | 469 | 470 | #if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) 471 | /** 472 | \brief Get Base Priority (non-secure) 473 | \details Returns the current value of the non-secure Base Priority register when in secure state. 474 | \return Base Priority register value 475 | */ 476 | __STATIC_FORCEINLINE uint32_t __TZ_get_BASEPRI_NS(void) 477 | { 478 | uint32_t result; 479 | 480 | __ASM volatile ("MRS %0, basepri_ns" : "=r" (result) ); 481 | return(result); 482 | } 483 | #endif 484 | 485 | 486 | /** 487 | \brief Set Base Priority 488 | \details Assigns the given value to the Base Priority register. 489 | \param [in] basePri Base Priority value to set 490 | */ 491 | __STATIC_FORCEINLINE void __set_BASEPRI(uint32_t basePri) 492 | { 493 | __ASM volatile ("MSR basepri, %0" : : "r" (basePri) : "memory"); 494 | } 495 | 496 | 497 | #if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) 498 | /** 499 | \brief Set Base Priority (non-secure) 500 | \details Assigns the given value to the non-secure Base Priority register when in secure state. 501 | \param [in] basePri Base Priority value to set 502 | */ 503 | __STATIC_FORCEINLINE void __TZ_set_BASEPRI_NS(uint32_t basePri) 504 | { 505 | __ASM volatile ("MSR basepri_ns, %0" : : "r" (basePri) : "memory"); 506 | } 507 | #endif 508 | 509 | 510 | /** 511 | \brief Set Base Priority with condition 512 | \details Assigns the given value to the Base Priority register only if BASEPRI masking is disabled, 513 | or the new value increases the BASEPRI priority level. 514 | \param [in] basePri Base Priority value to set 515 | */ 516 | __STATIC_FORCEINLINE void __set_BASEPRI_MAX(uint32_t basePri) 517 | { 518 | __ASM volatile ("MSR basepri_max, %0" : : "r" (basePri) : "memory"); 519 | } 520 | 521 | 522 | /** 523 | \brief Get Fault Mask 524 | \details Returns the current value of the Fault Mask register. 525 | \return Fault Mask register value 526 | */ 527 | __STATIC_FORCEINLINE uint32_t __get_FAULTMASK(void) 528 | { 529 | uint32_t result; 530 | 531 | __ASM volatile ("MRS %0, faultmask" : "=r" (result) ); 532 | return(result); 533 | } 534 | 535 | 536 | #if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) 537 | /** 538 | \brief Get Fault Mask (non-secure) 539 | \details Returns the current value of the non-secure Fault Mask register when in secure state. 540 | \return Fault Mask register value 541 | */ 542 | __STATIC_FORCEINLINE uint32_t __TZ_get_FAULTMASK_NS(void) 543 | { 544 | uint32_t result; 545 | 546 | __ASM volatile ("MRS %0, faultmask_ns" : "=r" (result) ); 547 | return(result); 548 | } 549 | #endif 550 | 551 | 552 | /** 553 | \brief Set Fault Mask 554 | \details Assigns the given value to the Fault Mask register. 555 | \param [in] faultMask Fault Mask value to set 556 | */ 557 | __STATIC_FORCEINLINE void __set_FAULTMASK(uint32_t faultMask) 558 | { 559 | __ASM volatile ("MSR faultmask, %0" : : "r" (faultMask) : "memory"); 560 | } 561 | 562 | 563 | #if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) 564 | /** 565 | \brief Set Fault Mask (non-secure) 566 | \details Assigns the given value to the non-secure Fault Mask register when in secure state. 567 | \param [in] faultMask Fault Mask value to set 568 | */ 569 | __STATIC_FORCEINLINE void __TZ_set_FAULTMASK_NS(uint32_t faultMask) 570 | { 571 | __ASM volatile ("MSR faultmask_ns, %0" : : "r" (faultMask) : "memory"); 572 | } 573 | #endif 574 | 575 | #endif /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ 576 | (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ 577 | (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) ) */ 578 | 579 | 580 | #if ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ 581 | (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) 582 | 583 | /** 584 | \brief Get Process Stack Pointer Limit 585 | Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure 586 | Stack Pointer Limit register hence zero is returned always in non-secure 587 | mode. 588 | 589 | \details Returns the current value of the Process Stack Pointer Limit (PSPLIM). 590 | \return PSPLIM Register value 591 | */ 592 | __STATIC_FORCEINLINE uint32_t __get_PSPLIM(void) 593 | { 594 | #if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ 595 | (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) 596 | // without main extensions, the non-secure PSPLIM is RAZ/WI 597 | return 0U; 598 | #else 599 | uint32_t result; 600 | __ASM volatile ("MRS %0, psplim" : "=r" (result) ); 601 | return result; 602 | #endif 603 | } 604 | 605 | #if (defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3)) 606 | /** 607 | \brief Get Process Stack Pointer Limit (non-secure) 608 | Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure 609 | Stack Pointer Limit register hence zero is returned always. 610 | 611 | \details Returns the current value of the non-secure Process Stack Pointer Limit (PSPLIM) when in secure state. 612 | \return PSPLIM Register value 613 | */ 614 | __STATIC_FORCEINLINE uint32_t __TZ_get_PSPLIM_NS(void) 615 | { 616 | #if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1))) 617 | // without main extensions, the non-secure PSPLIM is RAZ/WI 618 | return 0U; 619 | #else 620 | uint32_t result; 621 | __ASM volatile ("MRS %0, psplim_ns" : "=r" (result) ); 622 | return result; 623 | #endif 624 | } 625 | #endif 626 | 627 | 628 | /** 629 | \brief Set Process Stack Pointer Limit 630 | Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure 631 | Stack Pointer Limit register hence the write is silently ignored in non-secure 632 | mode. 633 | 634 | \details Assigns the given value to the Process Stack Pointer Limit (PSPLIM). 635 | \param [in] ProcStackPtrLimit Process Stack Pointer Limit value to set 636 | */ 637 | __STATIC_FORCEINLINE void __set_PSPLIM(uint32_t ProcStackPtrLimit) 638 | { 639 | #if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ 640 | (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) 641 | // without main extensions, the non-secure PSPLIM is RAZ/WI 642 | (void)ProcStackPtrLimit; 643 | #else 644 | __ASM volatile ("MSR psplim, %0" : : "r" (ProcStackPtrLimit)); 645 | #endif 646 | } 647 | 648 | 649 | #if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) 650 | /** 651 | \brief Set Process Stack Pointer (non-secure) 652 | Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure 653 | Stack Pointer Limit register hence the write is silently ignored. 654 | 655 | \details Assigns the given value to the non-secure Process Stack Pointer Limit (PSPLIM) when in secure state. 656 | \param [in] ProcStackPtrLimit Process Stack Pointer Limit value to set 657 | */ 658 | __STATIC_FORCEINLINE void __TZ_set_PSPLIM_NS(uint32_t ProcStackPtrLimit) 659 | { 660 | #if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1))) 661 | // without main extensions, the non-secure PSPLIM is RAZ/WI 662 | (void)ProcStackPtrLimit; 663 | #else 664 | __ASM volatile ("MSR psplim_ns, %0\n" : : "r" (ProcStackPtrLimit)); 665 | #endif 666 | } 667 | #endif 668 | 669 | 670 | /** 671 | \brief Get Main Stack Pointer Limit 672 | Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure 673 | Stack Pointer Limit register hence zero is returned always in non-secure 674 | mode. 675 | 676 | \details Returns the current value of the Main Stack Pointer Limit (MSPLIM). 677 | \return MSPLIM Register value 678 | */ 679 | __STATIC_FORCEINLINE uint32_t __get_MSPLIM(void) 680 | { 681 | #if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ 682 | (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) 683 | // without main extensions, the non-secure MSPLIM is RAZ/WI 684 | return 0U; 685 | #else 686 | uint32_t result; 687 | __ASM volatile ("MRS %0, msplim" : "=r" (result) ); 688 | return result; 689 | #endif 690 | } 691 | 692 | 693 | #if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) 694 | /** 695 | \brief Get Main Stack Pointer Limit (non-secure) 696 | Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure 697 | Stack Pointer Limit register hence zero is returned always. 698 | 699 | \details Returns the current value of the non-secure Main Stack Pointer Limit(MSPLIM) when in secure state. 700 | \return MSPLIM Register value 701 | */ 702 | __STATIC_FORCEINLINE uint32_t __TZ_get_MSPLIM_NS(void) 703 | { 704 | #if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1))) 705 | // without main extensions, the non-secure MSPLIM is RAZ/WI 706 | return 0U; 707 | #else 708 | uint32_t result; 709 | __ASM volatile ("MRS %0, msplim_ns" : "=r" (result) ); 710 | return result; 711 | #endif 712 | } 713 | #endif 714 | 715 | 716 | /** 717 | \brief Set Main Stack Pointer Limit 718 | Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure 719 | Stack Pointer Limit register hence the write is silently ignored in non-secure 720 | mode. 721 | 722 | \details Assigns the given value to the Main Stack Pointer Limit (MSPLIM). 723 | \param [in] MainStackPtrLimit Main Stack Pointer Limit value to set 724 | */ 725 | __STATIC_FORCEINLINE void __set_MSPLIM(uint32_t MainStackPtrLimit) 726 | { 727 | #if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ 728 | (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) 729 | // without main extensions, the non-secure MSPLIM is RAZ/WI 730 | (void)MainStackPtrLimit; 731 | #else 732 | __ASM volatile ("MSR msplim, %0" : : "r" (MainStackPtrLimit)); 733 | #endif 734 | } 735 | 736 | 737 | #if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) 738 | /** 739 | \brief Set Main Stack Pointer Limit (non-secure) 740 | Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure 741 | Stack Pointer Limit register hence the write is silently ignored. 742 | 743 | \details Assigns the given value to the non-secure Main Stack Pointer Limit (MSPLIM) when in secure state. 744 | \param [in] MainStackPtrLimit Main Stack Pointer value to set 745 | */ 746 | __STATIC_FORCEINLINE void __TZ_set_MSPLIM_NS(uint32_t MainStackPtrLimit) 747 | { 748 | #if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1))) 749 | // without main extensions, the non-secure MSPLIM is RAZ/WI 750 | (void)MainStackPtrLimit; 751 | #else 752 | __ASM volatile ("MSR msplim_ns, %0" : : "r" (MainStackPtrLimit)); 753 | #endif 754 | } 755 | #endif 756 | 757 | #endif /* ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ 758 | (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) */ 759 | 760 | 761 | /** 762 | \brief Get FPSCR 763 | \details Returns the current value of the Floating Point Status/Control register. 764 | \return Floating Point Status/Control register value 765 | */ 766 | __STATIC_FORCEINLINE uint32_t __get_FPSCR(void) 767 | { 768 | #if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \ 769 | (defined (__FPU_USED ) && (__FPU_USED == 1U)) ) 770 | #if __has_builtin(__builtin_arm_get_fpscr) 771 | // Re-enable using built-in when GCC has been fixed 772 | // || (__GNUC__ > 7) || (__GNUC__ == 7 && __GNUC_MINOR__ >= 2) 773 | /* see https://gcc.gnu.org/ml/gcc-patches/2017-04/msg00443.html */ 774 | return __builtin_arm_get_fpscr(); 775 | #else 776 | uint32_t result; 777 | 778 | __ASM volatile ("VMRS %0, fpscr" : "=r" (result) ); 779 | return(result); 780 | #endif 781 | #else 782 | return(0U); 783 | #endif 784 | } 785 | 786 | 787 | /** 788 | \brief Set FPSCR 789 | \details Assigns the given value to the Floating Point Status/Control register. 790 | \param [in] fpscr Floating Point Status/Control value to set 791 | */ 792 | __STATIC_FORCEINLINE void __set_FPSCR(uint32_t fpscr) 793 | { 794 | #if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \ 795 | (defined (__FPU_USED ) && (__FPU_USED == 1U)) ) 796 | #if __has_builtin(__builtin_arm_set_fpscr) 797 | // Re-enable using built-in when GCC has been fixed 798 | // || (__GNUC__ > 7) || (__GNUC__ == 7 && __GNUC_MINOR__ >= 2) 799 | /* see https://gcc.gnu.org/ml/gcc-patches/2017-04/msg00443.html */ 800 | __builtin_arm_set_fpscr(fpscr); 801 | #else 802 | __ASM volatile ("VMSR fpscr, %0" : : "r" (fpscr) : "vfpcc", "memory"); 803 | #endif 804 | #else 805 | (void)fpscr; 806 | #endif 807 | } 808 | 809 | 810 | /*@} end of CMSIS_Core_RegAccFunctions */ 811 | 812 | 813 | /* ########################## Core Instruction Access ######################### */ 814 | /** \defgroup CMSIS_Core_InstructionInterface CMSIS Core Instruction Interface 815 | Access to dedicated instructions 816 | @{ 817 | */ 818 | 819 | /* Define macros for porting to both thumb1 and thumb2. 820 | * For thumb1, use low register (r0-r7), specified by constraint "l" 821 | * Otherwise, use general registers, specified by constraint "r" */ 822 | #if defined (__thumb__) && !defined (__thumb2__) 823 | #define __CMSIS_GCC_OUT_REG(r) "=l" (r) 824 | #define __CMSIS_GCC_RW_REG(r) "+l" (r) 825 | #define __CMSIS_GCC_USE_REG(r) "l" (r) 826 | #else 827 | #define __CMSIS_GCC_OUT_REG(r) "=r" (r) 828 | #define __CMSIS_GCC_RW_REG(r) "+r" (r) 829 | #define __CMSIS_GCC_USE_REG(r) "r" (r) 830 | #endif 831 | 832 | /** 833 | \brief No Operation 834 | \details No Operation does nothing. This instruction can be used for code alignment purposes. 835 | */ 836 | #define __NOP() __ASM volatile ("nop") 837 | 838 | /** 839 | \brief Wait For Interrupt 840 | \details Wait For Interrupt is a hint instruction that suspends execution until one of a number of events occurs. 841 | */ 842 | #define __WFI() __ASM volatile ("wfi") 843 | 844 | 845 | /** 846 | \brief Wait For Event 847 | \details Wait For Event is a hint instruction that permits the processor to enter 848 | a low-power state until one of a number of events occurs. 849 | */ 850 | #define __WFE() __ASM volatile ("wfe") 851 | 852 | 853 | /** 854 | \brief Send Event 855 | \details Send Event is a hint instruction. It causes an event to be signaled to the CPU. 856 | */ 857 | #define __SEV() __ASM volatile ("sev") 858 | 859 | 860 | /** 861 | \brief Instruction Synchronization Barrier 862 | \details Instruction Synchronization Barrier flushes the pipeline in the processor, 863 | so that all instructions following the ISB are fetched from cache or memory, 864 | after the instruction has been completed. 865 | */ 866 | __STATIC_FORCEINLINE void __ISB(void) 867 | { 868 | __ASM volatile ("isb 0xF":::"memory"); 869 | } 870 | 871 | 872 | /** 873 | \brief Data Synchronization Barrier 874 | \details Acts as a special kind of Data Memory Barrier. 875 | It completes when all explicit memory accesses before this instruction complete. 876 | */ 877 | __STATIC_FORCEINLINE void __DSB(void) 878 | { 879 | __ASM volatile ("dsb 0xF":::"memory"); 880 | } 881 | 882 | 883 | /** 884 | \brief Data Memory Barrier 885 | \details Ensures the apparent order of the explicit memory operations before 886 | and after the instruction, without ensuring their completion. 887 | */ 888 | __STATIC_FORCEINLINE void __DMB(void) 889 | { 890 | __ASM volatile ("dmb 0xF":::"memory"); 891 | } 892 | 893 | 894 | /** 895 | \brief Reverse byte order (32 bit) 896 | \details Reverses the byte order in unsigned integer value. For example, 0x12345678 becomes 0x78563412. 897 | \param [in] value Value to reverse 898 | \return Reversed value 899 | */ 900 | __STATIC_FORCEINLINE uint32_t __REV(uint32_t value) 901 | { 902 | #if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5) 903 | return __builtin_bswap32(value); 904 | #else 905 | uint32_t result; 906 | 907 | __ASM volatile ("rev %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) ); 908 | return result; 909 | #endif 910 | } 911 | 912 | 913 | /** 914 | \brief Reverse byte order (16 bit) 915 | \details Reverses the byte order within each halfword of a word. For example, 0x12345678 becomes 0x34127856. 916 | \param [in] value Value to reverse 917 | \return Reversed value 918 | */ 919 | __STATIC_FORCEINLINE uint32_t __REV16(uint32_t value) 920 | { 921 | uint32_t result; 922 | 923 | __ASM volatile ("rev16 %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) ); 924 | return result; 925 | } 926 | 927 | 928 | /** 929 | \brief Reverse byte order (16 bit) 930 | \details Reverses the byte order in a 16-bit value and returns the signed 16-bit result. For example, 0x0080 becomes 0x8000. 931 | \param [in] value Value to reverse 932 | \return Reversed value 933 | */ 934 | __STATIC_FORCEINLINE int16_t __REVSH(int16_t value) 935 | { 936 | #if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) 937 | return (int16_t)__builtin_bswap16(value); 938 | #else 939 | int16_t result; 940 | 941 | __ASM volatile ("revsh %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) ); 942 | return result; 943 | #endif 944 | } 945 | 946 | 947 | /** 948 | \brief Rotate Right in unsigned value (32 bit) 949 | \details Rotate Right (immediate) provides the value of the contents of a register rotated by a variable number of bits. 950 | \param [in] op1 Value to rotate 951 | \param [in] op2 Number of Bits to rotate 952 | \return Rotated value 953 | */ 954 | __STATIC_FORCEINLINE uint32_t __ROR(uint32_t op1, uint32_t op2) 955 | { 956 | op2 %= 32U; 957 | if (op2 == 0U) 958 | { 959 | return op1; 960 | } 961 | return (op1 >> op2) | (op1 << (32U - op2)); 962 | } 963 | 964 | 965 | /** 966 | \brief Breakpoint 967 | \details Causes the processor to enter Debug state. 968 | Debug tools can use this to investigate system state when the instruction at a particular address is reached. 969 | \param [in] value is ignored by the processor. 970 | If required, a debugger can use it to store additional information about the breakpoint. 971 | */ 972 | #define __BKPT(value) __ASM volatile ("bkpt "#value) 973 | 974 | 975 | /** 976 | \brief Reverse bit order of value 977 | \details Reverses the bit order of the given value. 978 | \param [in] value Value to reverse 979 | \return Reversed value 980 | */ 981 | __STATIC_FORCEINLINE uint32_t __RBIT(uint32_t value) 982 | { 983 | uint32_t result; 984 | 985 | #if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ 986 | (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ 987 | (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) ) 988 | __ASM volatile ("rbit %0, %1" : "=r" (result) : "r" (value) ); 989 | #else 990 | uint32_t s = (4U /*sizeof(v)*/ * 8U) - 1U; /* extra shift needed at end */ 991 | 992 | result = value; /* r will be reversed bits of v; first get LSB of v */ 993 | for (value >>= 1U; value != 0U; value >>= 1U) 994 | { 995 | result <<= 1U; 996 | result |= value & 1U; 997 | s--; 998 | } 999 | result <<= s; /* shift when v's highest bits are zero */ 1000 | #endif 1001 | return result; 1002 | } 1003 | 1004 | 1005 | /** 1006 | \brief Count leading zeros 1007 | \details Counts the number of leading zeros of a data value. 1008 | \param [in] value Value to count the leading zeros 1009 | \return number of leading zeros in value 1010 | */ 1011 | #define __CLZ (uint8_t)__builtin_clz 1012 | 1013 | 1014 | #if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ 1015 | (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ 1016 | (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ 1017 | (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) 1018 | /** 1019 | \brief LDR Exclusive (8 bit) 1020 | \details Executes a exclusive LDR instruction for 8 bit value. 1021 | \param [in] ptr Pointer to data 1022 | \return value of type uint8_t at (*ptr) 1023 | */ 1024 | __STATIC_FORCEINLINE uint8_t __LDREXB(volatile uint8_t *addr) 1025 | { 1026 | uint32_t result; 1027 | 1028 | #if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) 1029 | __ASM volatile ("ldrexb %0, %1" : "=r" (result) : "Q" (*addr) ); 1030 | #else 1031 | /* Prior to GCC 4.8, "Q" will be expanded to [rx, #0] which is not 1032 | accepted by assembler. So has to use following less efficient pattern. 1033 | */ 1034 | __ASM volatile ("ldrexb %0, [%1]" : "=r" (result) : "r" (addr) : "memory" ); 1035 | #endif 1036 | return ((uint8_t) result); /* Add explicit type cast here */ 1037 | } 1038 | 1039 | 1040 | /** 1041 | \brief LDR Exclusive (16 bit) 1042 | \details Executes a exclusive LDR instruction for 16 bit values. 1043 | \param [in] ptr Pointer to data 1044 | \return value of type uint16_t at (*ptr) 1045 | */ 1046 | __STATIC_FORCEINLINE uint16_t __LDREXH(volatile uint16_t *addr) 1047 | { 1048 | uint32_t result; 1049 | 1050 | #if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) 1051 | __ASM volatile ("ldrexh %0, %1" : "=r" (result) : "Q" (*addr) ); 1052 | #else 1053 | /* Prior to GCC 4.8, "Q" will be expanded to [rx, #0] which is not 1054 | accepted by assembler. So has to use following less efficient pattern. 1055 | */ 1056 | __ASM volatile ("ldrexh %0, [%1]" : "=r" (result) : "r" (addr) : "memory" ); 1057 | #endif 1058 | return ((uint16_t) result); /* Add explicit type cast here */ 1059 | } 1060 | 1061 | 1062 | /** 1063 | \brief LDR Exclusive (32 bit) 1064 | \details Executes a exclusive LDR instruction for 32 bit values. 1065 | \param [in] ptr Pointer to data 1066 | \return value of type uint32_t at (*ptr) 1067 | */ 1068 | __STATIC_FORCEINLINE uint32_t __LDREXW(volatile uint32_t *addr) 1069 | { 1070 | uint32_t result; 1071 | 1072 | __ASM volatile ("ldrex %0, %1" : "=r" (result) : "Q" (*addr) ); 1073 | return(result); 1074 | } 1075 | 1076 | 1077 | /** 1078 | \brief STR Exclusive (8 bit) 1079 | \details Executes a exclusive STR instruction for 8 bit values. 1080 | \param [in] value Value to store 1081 | \param [in] ptr Pointer to location 1082 | \return 0 Function succeeded 1083 | \return 1 Function failed 1084 | */ 1085 | __STATIC_FORCEINLINE uint32_t __STREXB(uint8_t value, volatile uint8_t *addr) 1086 | { 1087 | uint32_t result; 1088 | 1089 | __ASM volatile ("strexb %0, %2, %1" : "=&r" (result), "=Q" (*addr) : "r" ((uint32_t)value) ); 1090 | return(result); 1091 | } 1092 | 1093 | 1094 | /** 1095 | \brief STR Exclusive (16 bit) 1096 | \details Executes a exclusive STR instruction for 16 bit values. 1097 | \param [in] value Value to store 1098 | \param [in] ptr Pointer to location 1099 | \return 0 Function succeeded 1100 | \return 1 Function failed 1101 | */ 1102 | __STATIC_FORCEINLINE uint32_t __STREXH(uint16_t value, volatile uint16_t *addr) 1103 | { 1104 | uint32_t result; 1105 | 1106 | __ASM volatile ("strexh %0, %2, %1" : "=&r" (result), "=Q" (*addr) : "r" ((uint32_t)value) ); 1107 | return(result); 1108 | } 1109 | 1110 | 1111 | /** 1112 | \brief STR Exclusive (32 bit) 1113 | \details Executes a exclusive STR instruction for 32 bit values. 1114 | \param [in] value Value to store 1115 | \param [in] ptr Pointer to location 1116 | \return 0 Function succeeded 1117 | \return 1 Function failed 1118 | */ 1119 | __STATIC_FORCEINLINE uint32_t __STREXW(uint32_t value, volatile uint32_t *addr) 1120 | { 1121 | uint32_t result; 1122 | 1123 | __ASM volatile ("strex %0, %2, %1" : "=&r" (result), "=Q" (*addr) : "r" (value) ); 1124 | return(result); 1125 | } 1126 | 1127 | 1128 | /** 1129 | \brief Remove the exclusive lock 1130 | \details Removes the exclusive lock which is created by LDREX. 1131 | */ 1132 | __STATIC_FORCEINLINE void __CLREX(void) 1133 | { 1134 | __ASM volatile ("clrex" ::: "memory"); 1135 | } 1136 | 1137 | #endif /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ 1138 | (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ 1139 | (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ 1140 | (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) */ 1141 | 1142 | 1143 | #if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ 1144 | (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ 1145 | (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) ) 1146 | /** 1147 | \brief Signed Saturate 1148 | \details Saturates a signed value. 1149 | \param [in] ARG1 Value to be saturated 1150 | \param [in] ARG2 Bit position to saturate to (1..32) 1151 | \return Saturated value 1152 | */ 1153 | #define __SSAT(ARG1,ARG2) \ 1154 | __extension__ \ 1155 | ({ \ 1156 | int32_t __RES, __ARG1 = (ARG1); \ 1157 | __ASM ("ssat %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ 1158 | __RES; \ 1159 | }) 1160 | 1161 | 1162 | /** 1163 | \brief Unsigned Saturate 1164 | \details Saturates an unsigned value. 1165 | \param [in] ARG1 Value to be saturated 1166 | \param [in] ARG2 Bit position to saturate to (0..31) 1167 | \return Saturated value 1168 | */ 1169 | #define __USAT(ARG1,ARG2) \ 1170 | __extension__ \ 1171 | ({ \ 1172 | uint32_t __RES, __ARG1 = (ARG1); \ 1173 | __ASM ("usat %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ 1174 | __RES; \ 1175 | }) 1176 | 1177 | 1178 | /** 1179 | \brief Rotate Right with Extend (32 bit) 1180 | \details Moves each bit of a bitstring right by one bit. 1181 | The carry input is shifted in at the left end of the bitstring. 1182 | \param [in] value Value to rotate 1183 | \return Rotated value 1184 | */ 1185 | __STATIC_FORCEINLINE uint32_t __RRX(uint32_t value) 1186 | { 1187 | uint32_t result; 1188 | 1189 | __ASM volatile ("rrx %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) ); 1190 | return(result); 1191 | } 1192 | 1193 | 1194 | /** 1195 | \brief LDRT Unprivileged (8 bit) 1196 | \details Executes a Unprivileged LDRT instruction for 8 bit value. 1197 | \param [in] ptr Pointer to data 1198 | \return value of type uint8_t at (*ptr) 1199 | */ 1200 | __STATIC_FORCEINLINE uint8_t __LDRBT(volatile uint8_t *ptr) 1201 | { 1202 | uint32_t result; 1203 | 1204 | #if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) 1205 | __ASM volatile ("ldrbt %0, %1" : "=r" (result) : "Q" (*ptr) ); 1206 | #else 1207 | /* Prior to GCC 4.8, "Q" will be expanded to [rx, #0] which is not 1208 | accepted by assembler. So has to use following less efficient pattern. 1209 | */ 1210 | __ASM volatile ("ldrbt %0, [%1]" : "=r" (result) : "r" (ptr) : "memory" ); 1211 | #endif 1212 | return ((uint8_t) result); /* Add explicit type cast here */ 1213 | } 1214 | 1215 | 1216 | /** 1217 | \brief LDRT Unprivileged (16 bit) 1218 | \details Executes a Unprivileged LDRT instruction for 16 bit values. 1219 | \param [in] ptr Pointer to data 1220 | \return value of type uint16_t at (*ptr) 1221 | */ 1222 | __STATIC_FORCEINLINE uint16_t __LDRHT(volatile uint16_t *ptr) 1223 | { 1224 | uint32_t result; 1225 | 1226 | #if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) 1227 | __ASM volatile ("ldrht %0, %1" : "=r" (result) : "Q" (*ptr) ); 1228 | #else 1229 | /* Prior to GCC 4.8, "Q" will be expanded to [rx, #0] which is not 1230 | accepted by assembler. So has to use following less efficient pattern. 1231 | */ 1232 | __ASM volatile ("ldrht %0, [%1]" : "=r" (result) : "r" (ptr) : "memory" ); 1233 | #endif 1234 | return ((uint16_t) result); /* Add explicit type cast here */ 1235 | } 1236 | 1237 | 1238 | /** 1239 | \brief LDRT Unprivileged (32 bit) 1240 | \details Executes a Unprivileged LDRT instruction for 32 bit values. 1241 | \param [in] ptr Pointer to data 1242 | \return value of type uint32_t at (*ptr) 1243 | */ 1244 | __STATIC_FORCEINLINE uint32_t __LDRT(volatile uint32_t *ptr) 1245 | { 1246 | uint32_t result; 1247 | 1248 | __ASM volatile ("ldrt %0, %1" : "=r" (result) : "Q" (*ptr) ); 1249 | return(result); 1250 | } 1251 | 1252 | 1253 | /** 1254 | \brief STRT Unprivileged (8 bit) 1255 | \details Executes a Unprivileged STRT instruction for 8 bit values. 1256 | \param [in] value Value to store 1257 | \param [in] ptr Pointer to location 1258 | */ 1259 | __STATIC_FORCEINLINE void __STRBT(uint8_t value, volatile uint8_t *ptr) 1260 | { 1261 | __ASM volatile ("strbt %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) ); 1262 | } 1263 | 1264 | 1265 | /** 1266 | \brief STRT Unprivileged (16 bit) 1267 | \details Executes a Unprivileged STRT instruction for 16 bit values. 1268 | \param [in] value Value to store 1269 | \param [in] ptr Pointer to location 1270 | */ 1271 | __STATIC_FORCEINLINE void __STRHT(uint16_t value, volatile uint16_t *ptr) 1272 | { 1273 | __ASM volatile ("strht %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) ); 1274 | } 1275 | 1276 | 1277 | /** 1278 | \brief STRT Unprivileged (32 bit) 1279 | \details Executes a Unprivileged STRT instruction for 32 bit values. 1280 | \param [in] value Value to store 1281 | \param [in] ptr Pointer to location 1282 | */ 1283 | __STATIC_FORCEINLINE void __STRT(uint32_t value, volatile uint32_t *ptr) 1284 | { 1285 | __ASM volatile ("strt %1, %0" : "=Q" (*ptr) : "r" (value) ); 1286 | } 1287 | 1288 | #else /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ 1289 | (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ 1290 | (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) ) */ 1291 | 1292 | /** 1293 | \brief Signed Saturate 1294 | \details Saturates a signed value. 1295 | \param [in] value Value to be saturated 1296 | \param [in] sat Bit position to saturate to (1..32) 1297 | \return Saturated value 1298 | */ 1299 | __STATIC_FORCEINLINE int32_t __SSAT(int32_t val, uint32_t sat) 1300 | { 1301 | if ((sat >= 1U) && (sat <= 32U)) 1302 | { 1303 | const int32_t max = (int32_t)((1U << (sat - 1U)) - 1U); 1304 | const int32_t min = -1 - max ; 1305 | if (val > max) 1306 | { 1307 | return max; 1308 | } 1309 | else if (val < min) 1310 | { 1311 | return min; 1312 | } 1313 | } 1314 | return val; 1315 | } 1316 | 1317 | /** 1318 | \brief Unsigned Saturate 1319 | \details Saturates an unsigned value. 1320 | \param [in] value Value to be saturated 1321 | \param [in] sat Bit position to saturate to (0..31) 1322 | \return Saturated value 1323 | */ 1324 | __STATIC_FORCEINLINE uint32_t __USAT(int32_t val, uint32_t sat) 1325 | { 1326 | if (sat <= 31U) 1327 | { 1328 | const uint32_t max = ((1U << sat) - 1U); 1329 | if (val > (int32_t)max) 1330 | { 1331 | return max; 1332 | } 1333 | else if (val < 0) 1334 | { 1335 | return 0U; 1336 | } 1337 | } 1338 | return (uint32_t)val; 1339 | } 1340 | 1341 | #endif /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ 1342 | (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ 1343 | (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) ) */ 1344 | 1345 | 1346 | #if ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ 1347 | (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) 1348 | /** 1349 | \brief Load-Acquire (8 bit) 1350 | \details Executes a LDAB instruction for 8 bit value. 1351 | \param [in] ptr Pointer to data 1352 | \return value of type uint8_t at (*ptr) 1353 | */ 1354 | __STATIC_FORCEINLINE uint8_t __LDAB(volatile uint8_t *ptr) 1355 | { 1356 | uint32_t result; 1357 | 1358 | __ASM volatile ("ldab %0, %1" : "=r" (result) : "Q" (*ptr) ); 1359 | return ((uint8_t) result); 1360 | } 1361 | 1362 | 1363 | /** 1364 | \brief Load-Acquire (16 bit) 1365 | \details Executes a LDAH instruction for 16 bit values. 1366 | \param [in] ptr Pointer to data 1367 | \return value of type uint16_t at (*ptr) 1368 | */ 1369 | __STATIC_FORCEINLINE uint16_t __LDAH(volatile uint16_t *ptr) 1370 | { 1371 | uint32_t result; 1372 | 1373 | __ASM volatile ("ldah %0, %1" : "=r" (result) : "Q" (*ptr) ); 1374 | return ((uint16_t) result); 1375 | } 1376 | 1377 | 1378 | /** 1379 | \brief Load-Acquire (32 bit) 1380 | \details Executes a LDA instruction for 32 bit values. 1381 | \param [in] ptr Pointer to data 1382 | \return value of type uint32_t at (*ptr) 1383 | */ 1384 | __STATIC_FORCEINLINE uint32_t __LDA(volatile uint32_t *ptr) 1385 | { 1386 | uint32_t result; 1387 | 1388 | __ASM volatile ("lda %0, %1" : "=r" (result) : "Q" (*ptr) ); 1389 | return(result); 1390 | } 1391 | 1392 | 1393 | /** 1394 | \brief Store-Release (8 bit) 1395 | \details Executes a STLB instruction for 8 bit values. 1396 | \param [in] value Value to store 1397 | \param [in] ptr Pointer to location 1398 | */ 1399 | __STATIC_FORCEINLINE void __STLB(uint8_t value, volatile uint8_t *ptr) 1400 | { 1401 | __ASM volatile ("stlb %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) ); 1402 | } 1403 | 1404 | 1405 | /** 1406 | \brief Store-Release (16 bit) 1407 | \details Executes a STLH instruction for 16 bit values. 1408 | \param [in] value Value to store 1409 | \param [in] ptr Pointer to location 1410 | */ 1411 | __STATIC_FORCEINLINE void __STLH(uint16_t value, volatile uint16_t *ptr) 1412 | { 1413 | __ASM volatile ("stlh %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) ); 1414 | } 1415 | 1416 | 1417 | /** 1418 | \brief Store-Release (32 bit) 1419 | \details Executes a STL instruction for 32 bit values. 1420 | \param [in] value Value to store 1421 | \param [in] ptr Pointer to location 1422 | */ 1423 | __STATIC_FORCEINLINE void __STL(uint32_t value, volatile uint32_t *ptr) 1424 | { 1425 | __ASM volatile ("stl %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) ); 1426 | } 1427 | 1428 | 1429 | /** 1430 | \brief Load-Acquire Exclusive (8 bit) 1431 | \details Executes a LDAB exclusive instruction for 8 bit value. 1432 | \param [in] ptr Pointer to data 1433 | \return value of type uint8_t at (*ptr) 1434 | */ 1435 | __STATIC_FORCEINLINE uint8_t __LDAEXB(volatile uint8_t *ptr) 1436 | { 1437 | uint32_t result; 1438 | 1439 | __ASM volatile ("ldaexb %0, %1" : "=r" (result) : "Q" (*ptr) ); 1440 | return ((uint8_t) result); 1441 | } 1442 | 1443 | 1444 | /** 1445 | \brief Load-Acquire Exclusive (16 bit) 1446 | \details Executes a LDAH exclusive instruction for 16 bit values. 1447 | \param [in] ptr Pointer to data 1448 | \return value of type uint16_t at (*ptr) 1449 | */ 1450 | __STATIC_FORCEINLINE uint16_t __LDAEXH(volatile uint16_t *ptr) 1451 | { 1452 | uint32_t result; 1453 | 1454 | __ASM volatile ("ldaexh %0, %1" : "=r" (result) : "Q" (*ptr) ); 1455 | return ((uint16_t) result); 1456 | } 1457 | 1458 | 1459 | /** 1460 | \brief Load-Acquire Exclusive (32 bit) 1461 | \details Executes a LDA exclusive instruction for 32 bit values. 1462 | \param [in] ptr Pointer to data 1463 | \return value of type uint32_t at (*ptr) 1464 | */ 1465 | __STATIC_FORCEINLINE uint32_t __LDAEX(volatile uint32_t *ptr) 1466 | { 1467 | uint32_t result; 1468 | 1469 | __ASM volatile ("ldaex %0, %1" : "=r" (result) : "Q" (*ptr) ); 1470 | return(result); 1471 | } 1472 | 1473 | 1474 | /** 1475 | \brief Store-Release Exclusive (8 bit) 1476 | \details Executes a STLB exclusive instruction for 8 bit values. 1477 | \param [in] value Value to store 1478 | \param [in] ptr Pointer to location 1479 | \return 0 Function succeeded 1480 | \return 1 Function failed 1481 | */ 1482 | __STATIC_FORCEINLINE uint32_t __STLEXB(uint8_t value, volatile uint8_t *ptr) 1483 | { 1484 | uint32_t result; 1485 | 1486 | __ASM volatile ("stlexb %0, %2, %1" : "=&r" (result), "=Q" (*ptr) : "r" ((uint32_t)value) ); 1487 | return(result); 1488 | } 1489 | 1490 | 1491 | /** 1492 | \brief Store-Release Exclusive (16 bit) 1493 | \details Executes a STLH exclusive instruction for 16 bit values. 1494 | \param [in] value Value to store 1495 | \param [in] ptr Pointer to location 1496 | \return 0 Function succeeded 1497 | \return 1 Function failed 1498 | */ 1499 | __STATIC_FORCEINLINE uint32_t __STLEXH(uint16_t value, volatile uint16_t *ptr) 1500 | { 1501 | uint32_t result; 1502 | 1503 | __ASM volatile ("stlexh %0, %2, %1" : "=&r" (result), "=Q" (*ptr) : "r" ((uint32_t)value) ); 1504 | return(result); 1505 | } 1506 | 1507 | 1508 | /** 1509 | \brief Store-Release Exclusive (32 bit) 1510 | \details Executes a STL exclusive instruction for 32 bit values. 1511 | \param [in] value Value to store 1512 | \param [in] ptr Pointer to location 1513 | \return 0 Function succeeded 1514 | \return 1 Function failed 1515 | */ 1516 | __STATIC_FORCEINLINE uint32_t __STLEX(uint32_t value, volatile uint32_t *ptr) 1517 | { 1518 | uint32_t result; 1519 | 1520 | __ASM volatile ("stlex %0, %2, %1" : "=&r" (result), "=Q" (*ptr) : "r" ((uint32_t)value) ); 1521 | return(result); 1522 | } 1523 | 1524 | #endif /* ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ 1525 | (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) */ 1526 | 1527 | /*@}*/ /* end of group CMSIS_Core_InstructionInterface */ 1528 | 1529 | 1530 | /* ################### Compiler specific Intrinsics ########################### */ 1531 | /** \defgroup CMSIS_SIMD_intrinsics CMSIS SIMD Intrinsics 1532 | Access to dedicated SIMD instructions 1533 | @{ 1534 | */ 1535 | 1536 | #if (defined (__ARM_FEATURE_DSP) && (__ARM_FEATURE_DSP == 1)) 1537 | 1538 | __STATIC_FORCEINLINE uint32_t __SADD8(uint32_t op1, uint32_t op2) 1539 | { 1540 | uint32_t result; 1541 | 1542 | __ASM volatile ("sadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1543 | return(result); 1544 | } 1545 | 1546 | __STATIC_FORCEINLINE uint32_t __QADD8(uint32_t op1, uint32_t op2) 1547 | { 1548 | uint32_t result; 1549 | 1550 | __ASM volatile ("qadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1551 | return(result); 1552 | } 1553 | 1554 | __STATIC_FORCEINLINE uint32_t __SHADD8(uint32_t op1, uint32_t op2) 1555 | { 1556 | uint32_t result; 1557 | 1558 | __ASM volatile ("shadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1559 | return(result); 1560 | } 1561 | 1562 | __STATIC_FORCEINLINE uint32_t __UADD8(uint32_t op1, uint32_t op2) 1563 | { 1564 | uint32_t result; 1565 | 1566 | __ASM volatile ("uadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1567 | return(result); 1568 | } 1569 | 1570 | __STATIC_FORCEINLINE uint32_t __UQADD8(uint32_t op1, uint32_t op2) 1571 | { 1572 | uint32_t result; 1573 | 1574 | __ASM volatile ("uqadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1575 | return(result); 1576 | } 1577 | 1578 | __STATIC_FORCEINLINE uint32_t __UHADD8(uint32_t op1, uint32_t op2) 1579 | { 1580 | uint32_t result; 1581 | 1582 | __ASM volatile ("uhadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1583 | return(result); 1584 | } 1585 | 1586 | 1587 | __STATIC_FORCEINLINE uint32_t __SSUB8(uint32_t op1, uint32_t op2) 1588 | { 1589 | uint32_t result; 1590 | 1591 | __ASM volatile ("ssub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1592 | return(result); 1593 | } 1594 | 1595 | __STATIC_FORCEINLINE uint32_t __QSUB8(uint32_t op1, uint32_t op2) 1596 | { 1597 | uint32_t result; 1598 | 1599 | __ASM volatile ("qsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1600 | return(result); 1601 | } 1602 | 1603 | __STATIC_FORCEINLINE uint32_t __SHSUB8(uint32_t op1, uint32_t op2) 1604 | { 1605 | uint32_t result; 1606 | 1607 | __ASM volatile ("shsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1608 | return(result); 1609 | } 1610 | 1611 | __STATIC_FORCEINLINE uint32_t __USUB8(uint32_t op1, uint32_t op2) 1612 | { 1613 | uint32_t result; 1614 | 1615 | __ASM volatile ("usub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1616 | return(result); 1617 | } 1618 | 1619 | __STATIC_FORCEINLINE uint32_t __UQSUB8(uint32_t op1, uint32_t op2) 1620 | { 1621 | uint32_t result; 1622 | 1623 | __ASM volatile ("uqsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1624 | return(result); 1625 | } 1626 | 1627 | __STATIC_FORCEINLINE uint32_t __UHSUB8(uint32_t op1, uint32_t op2) 1628 | { 1629 | uint32_t result; 1630 | 1631 | __ASM volatile ("uhsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1632 | return(result); 1633 | } 1634 | 1635 | 1636 | __STATIC_FORCEINLINE uint32_t __SADD16(uint32_t op1, uint32_t op2) 1637 | { 1638 | uint32_t result; 1639 | 1640 | __ASM volatile ("sadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1641 | return(result); 1642 | } 1643 | 1644 | __STATIC_FORCEINLINE uint32_t __QADD16(uint32_t op1, uint32_t op2) 1645 | { 1646 | uint32_t result; 1647 | 1648 | __ASM volatile ("qadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1649 | return(result); 1650 | } 1651 | 1652 | __STATIC_FORCEINLINE uint32_t __SHADD16(uint32_t op1, uint32_t op2) 1653 | { 1654 | uint32_t result; 1655 | 1656 | __ASM volatile ("shadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1657 | return(result); 1658 | } 1659 | 1660 | __STATIC_FORCEINLINE uint32_t __UADD16(uint32_t op1, uint32_t op2) 1661 | { 1662 | uint32_t result; 1663 | 1664 | __ASM volatile ("uadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1665 | return(result); 1666 | } 1667 | 1668 | __STATIC_FORCEINLINE uint32_t __UQADD16(uint32_t op1, uint32_t op2) 1669 | { 1670 | uint32_t result; 1671 | 1672 | __ASM volatile ("uqadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1673 | return(result); 1674 | } 1675 | 1676 | __STATIC_FORCEINLINE uint32_t __UHADD16(uint32_t op1, uint32_t op2) 1677 | { 1678 | uint32_t result; 1679 | 1680 | __ASM volatile ("uhadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1681 | return(result); 1682 | } 1683 | 1684 | __STATIC_FORCEINLINE uint32_t __SSUB16(uint32_t op1, uint32_t op2) 1685 | { 1686 | uint32_t result; 1687 | 1688 | __ASM volatile ("ssub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1689 | return(result); 1690 | } 1691 | 1692 | __STATIC_FORCEINLINE uint32_t __QSUB16(uint32_t op1, uint32_t op2) 1693 | { 1694 | uint32_t result; 1695 | 1696 | __ASM volatile ("qsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1697 | return(result); 1698 | } 1699 | 1700 | __STATIC_FORCEINLINE uint32_t __SHSUB16(uint32_t op1, uint32_t op2) 1701 | { 1702 | uint32_t result; 1703 | 1704 | __ASM volatile ("shsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1705 | return(result); 1706 | } 1707 | 1708 | __STATIC_FORCEINLINE uint32_t __USUB16(uint32_t op1, uint32_t op2) 1709 | { 1710 | uint32_t result; 1711 | 1712 | __ASM volatile ("usub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1713 | return(result); 1714 | } 1715 | 1716 | __STATIC_FORCEINLINE uint32_t __UQSUB16(uint32_t op1, uint32_t op2) 1717 | { 1718 | uint32_t result; 1719 | 1720 | __ASM volatile ("uqsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1721 | return(result); 1722 | } 1723 | 1724 | __STATIC_FORCEINLINE uint32_t __UHSUB16(uint32_t op1, uint32_t op2) 1725 | { 1726 | uint32_t result; 1727 | 1728 | __ASM volatile ("uhsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1729 | return(result); 1730 | } 1731 | 1732 | __STATIC_FORCEINLINE uint32_t __SASX(uint32_t op1, uint32_t op2) 1733 | { 1734 | uint32_t result; 1735 | 1736 | __ASM volatile ("sasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1737 | return(result); 1738 | } 1739 | 1740 | __STATIC_FORCEINLINE uint32_t __QASX(uint32_t op1, uint32_t op2) 1741 | { 1742 | uint32_t result; 1743 | 1744 | __ASM volatile ("qasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1745 | return(result); 1746 | } 1747 | 1748 | __STATIC_FORCEINLINE uint32_t __SHASX(uint32_t op1, uint32_t op2) 1749 | { 1750 | uint32_t result; 1751 | 1752 | __ASM volatile ("shasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1753 | return(result); 1754 | } 1755 | 1756 | __STATIC_FORCEINLINE uint32_t __UASX(uint32_t op1, uint32_t op2) 1757 | { 1758 | uint32_t result; 1759 | 1760 | __ASM volatile ("uasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1761 | return(result); 1762 | } 1763 | 1764 | __STATIC_FORCEINLINE uint32_t __UQASX(uint32_t op1, uint32_t op2) 1765 | { 1766 | uint32_t result; 1767 | 1768 | __ASM volatile ("uqasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1769 | return(result); 1770 | } 1771 | 1772 | __STATIC_FORCEINLINE uint32_t __UHASX(uint32_t op1, uint32_t op2) 1773 | { 1774 | uint32_t result; 1775 | 1776 | __ASM volatile ("uhasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1777 | return(result); 1778 | } 1779 | 1780 | __STATIC_FORCEINLINE uint32_t __SSAX(uint32_t op1, uint32_t op2) 1781 | { 1782 | uint32_t result; 1783 | 1784 | __ASM volatile ("ssax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1785 | return(result); 1786 | } 1787 | 1788 | __STATIC_FORCEINLINE uint32_t __QSAX(uint32_t op1, uint32_t op2) 1789 | { 1790 | uint32_t result; 1791 | 1792 | __ASM volatile ("qsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1793 | return(result); 1794 | } 1795 | 1796 | __STATIC_FORCEINLINE uint32_t __SHSAX(uint32_t op1, uint32_t op2) 1797 | { 1798 | uint32_t result; 1799 | 1800 | __ASM volatile ("shsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1801 | return(result); 1802 | } 1803 | 1804 | __STATIC_FORCEINLINE uint32_t __USAX(uint32_t op1, uint32_t op2) 1805 | { 1806 | uint32_t result; 1807 | 1808 | __ASM volatile ("usax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1809 | return(result); 1810 | } 1811 | 1812 | __STATIC_FORCEINLINE uint32_t __UQSAX(uint32_t op1, uint32_t op2) 1813 | { 1814 | uint32_t result; 1815 | 1816 | __ASM volatile ("uqsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1817 | return(result); 1818 | } 1819 | 1820 | __STATIC_FORCEINLINE uint32_t __UHSAX(uint32_t op1, uint32_t op2) 1821 | { 1822 | uint32_t result; 1823 | 1824 | __ASM volatile ("uhsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1825 | return(result); 1826 | } 1827 | 1828 | __STATIC_FORCEINLINE uint32_t __USAD8(uint32_t op1, uint32_t op2) 1829 | { 1830 | uint32_t result; 1831 | 1832 | __ASM volatile ("usad8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1833 | return(result); 1834 | } 1835 | 1836 | __STATIC_FORCEINLINE uint32_t __USADA8(uint32_t op1, uint32_t op2, uint32_t op3) 1837 | { 1838 | uint32_t result; 1839 | 1840 | __ASM volatile ("usada8 %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); 1841 | return(result); 1842 | } 1843 | 1844 | #define __SSAT16(ARG1,ARG2) \ 1845 | ({ \ 1846 | int32_t __RES, __ARG1 = (ARG1); \ 1847 | __ASM ("ssat16 %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ 1848 | __RES; \ 1849 | }) 1850 | 1851 | #define __USAT16(ARG1,ARG2) \ 1852 | ({ \ 1853 | uint32_t __RES, __ARG1 = (ARG1); \ 1854 | __ASM ("usat16 %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ 1855 | __RES; \ 1856 | }) 1857 | 1858 | __STATIC_FORCEINLINE uint32_t __UXTB16(uint32_t op1) 1859 | { 1860 | uint32_t result; 1861 | 1862 | __ASM volatile ("uxtb16 %0, %1" : "=r" (result) : "r" (op1)); 1863 | return(result); 1864 | } 1865 | 1866 | __STATIC_FORCEINLINE uint32_t __UXTAB16(uint32_t op1, uint32_t op2) 1867 | { 1868 | uint32_t result; 1869 | 1870 | __ASM volatile ("uxtab16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1871 | return(result); 1872 | } 1873 | 1874 | __STATIC_FORCEINLINE uint32_t __SXTB16(uint32_t op1) 1875 | { 1876 | uint32_t result; 1877 | 1878 | __ASM volatile ("sxtb16 %0, %1" : "=r" (result) : "r" (op1)); 1879 | return(result); 1880 | } 1881 | 1882 | __STATIC_FORCEINLINE uint32_t __SXTAB16(uint32_t op1, uint32_t op2) 1883 | { 1884 | uint32_t result; 1885 | 1886 | __ASM volatile ("sxtab16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1887 | return(result); 1888 | } 1889 | 1890 | __STATIC_FORCEINLINE uint32_t __SMUAD (uint32_t op1, uint32_t op2) 1891 | { 1892 | uint32_t result; 1893 | 1894 | __ASM volatile ("smuad %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1895 | return(result); 1896 | } 1897 | 1898 | __STATIC_FORCEINLINE uint32_t __SMUADX (uint32_t op1, uint32_t op2) 1899 | { 1900 | uint32_t result; 1901 | 1902 | __ASM volatile ("smuadx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1903 | return(result); 1904 | } 1905 | 1906 | __STATIC_FORCEINLINE uint32_t __SMLAD (uint32_t op1, uint32_t op2, uint32_t op3) 1907 | { 1908 | uint32_t result; 1909 | 1910 | __ASM volatile ("smlad %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); 1911 | return(result); 1912 | } 1913 | 1914 | __STATIC_FORCEINLINE uint32_t __SMLADX (uint32_t op1, uint32_t op2, uint32_t op3) 1915 | { 1916 | uint32_t result; 1917 | 1918 | __ASM volatile ("smladx %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); 1919 | return(result); 1920 | } 1921 | 1922 | __STATIC_FORCEINLINE uint64_t __SMLALD (uint32_t op1, uint32_t op2, uint64_t acc) 1923 | { 1924 | union llreg_u{ 1925 | uint32_t w32[2]; 1926 | uint64_t w64; 1927 | } llr; 1928 | llr.w64 = acc; 1929 | 1930 | #ifndef __ARMEB__ /* Little endian */ 1931 | __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]) ); 1932 | #else /* Big endian */ 1933 | __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]) ); 1934 | #endif 1935 | 1936 | return(llr.w64); 1937 | } 1938 | 1939 | __STATIC_FORCEINLINE uint64_t __SMLALDX (uint32_t op1, uint32_t op2, uint64_t acc) 1940 | { 1941 | union llreg_u{ 1942 | uint32_t w32[2]; 1943 | uint64_t w64; 1944 | } llr; 1945 | llr.w64 = acc; 1946 | 1947 | #ifndef __ARMEB__ /* Little endian */ 1948 | __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]) ); 1949 | #else /* Big endian */ 1950 | __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]) ); 1951 | #endif 1952 | 1953 | return(llr.w64); 1954 | } 1955 | 1956 | __STATIC_FORCEINLINE uint32_t __SMUSD (uint32_t op1, uint32_t op2) 1957 | { 1958 | uint32_t result; 1959 | 1960 | __ASM volatile ("smusd %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1961 | return(result); 1962 | } 1963 | 1964 | __STATIC_FORCEINLINE uint32_t __SMUSDX (uint32_t op1, uint32_t op2) 1965 | { 1966 | uint32_t result; 1967 | 1968 | __ASM volatile ("smusdx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1969 | return(result); 1970 | } 1971 | 1972 | __STATIC_FORCEINLINE uint32_t __SMLSD (uint32_t op1, uint32_t op2, uint32_t op3) 1973 | { 1974 | uint32_t result; 1975 | 1976 | __ASM volatile ("smlsd %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); 1977 | return(result); 1978 | } 1979 | 1980 | __STATIC_FORCEINLINE uint32_t __SMLSDX (uint32_t op1, uint32_t op2, uint32_t op3) 1981 | { 1982 | uint32_t result; 1983 | 1984 | __ASM volatile ("smlsdx %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); 1985 | return(result); 1986 | } 1987 | 1988 | __STATIC_FORCEINLINE uint64_t __SMLSLD (uint32_t op1, uint32_t op2, uint64_t acc) 1989 | { 1990 | union llreg_u{ 1991 | uint32_t w32[2]; 1992 | uint64_t w64; 1993 | } llr; 1994 | llr.w64 = acc; 1995 | 1996 | #ifndef __ARMEB__ /* Little endian */ 1997 | __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]) ); 1998 | #else /* Big endian */ 1999 | __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]) ); 2000 | #endif 2001 | 2002 | return(llr.w64); 2003 | } 2004 | 2005 | __STATIC_FORCEINLINE uint64_t __SMLSLDX (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 ("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]) ); 2015 | #else /* Big endian */ 2016 | __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]) ); 2017 | #endif 2018 | 2019 | return(llr.w64); 2020 | } 2021 | 2022 | __STATIC_FORCEINLINE uint32_t __SEL (uint32_t op1, uint32_t op2) 2023 | { 2024 | uint32_t result; 2025 | 2026 | __ASM volatile ("sel %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 2027 | return(result); 2028 | } 2029 | 2030 | __STATIC_FORCEINLINE int32_t __QADD( int32_t op1, int32_t op2) 2031 | { 2032 | int32_t result; 2033 | 2034 | __ASM volatile ("qadd %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 2035 | return(result); 2036 | } 2037 | 2038 | __STATIC_FORCEINLINE int32_t __QSUB( int32_t op1, int32_t op2) 2039 | { 2040 | int32_t result; 2041 | 2042 | __ASM volatile ("qsub %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 2043 | return(result); 2044 | } 2045 | 2046 | #if 0 2047 | #define __PKHBT(ARG1,ARG2,ARG3) \ 2048 | ({ \ 2049 | uint32_t __RES, __ARG1 = (ARG1), __ARG2 = (ARG2); \ 2050 | __ASM ("pkhbt %0, %1, %2, lsl %3" : "=r" (__RES) : "r" (__ARG1), "r" (__ARG2), "I" (ARG3) ); \ 2051 | __RES; \ 2052 | }) 2053 | 2054 | #define __PKHTB(ARG1,ARG2,ARG3) \ 2055 | ({ \ 2056 | uint32_t __RES, __ARG1 = (ARG1), __ARG2 = (ARG2); \ 2057 | if (ARG3 == 0) \ 2058 | __ASM ("pkhtb %0, %1, %2" : "=r" (__RES) : "r" (__ARG1), "r" (__ARG2) ); \ 2059 | else \ 2060 | __ASM ("pkhtb %0, %1, %2, asr %3" : "=r" (__RES) : "r" (__ARG1), "r" (__ARG2), "I" (ARG3) ); \ 2061 | __RES; \ 2062 | }) 2063 | #endif 2064 | 2065 | #define __PKHBT(ARG1,ARG2,ARG3) ( ((((uint32_t)(ARG1)) ) & 0x0000FFFFUL) | \ 2066 | ((((uint32_t)(ARG2)) << (ARG3)) & 0xFFFF0000UL) ) 2067 | 2068 | #define __PKHTB(ARG1,ARG2,ARG3) ( ((((uint32_t)(ARG1)) ) & 0xFFFF0000UL) | \ 2069 | ((((uint32_t)(ARG2)) >> (ARG3)) & 0x0000FFFFUL) ) 2070 | 2071 | __STATIC_FORCEINLINE int32_t __SMMLA (int32_t op1, int32_t op2, int32_t op3) 2072 | { 2073 | int32_t result; 2074 | 2075 | __ASM volatile ("smmla %0, %1, %2, %3" : "=r" (result): "r" (op1), "r" (op2), "r" (op3) ); 2076 | return(result); 2077 | } 2078 | 2079 | #endif /* (__ARM_FEATURE_DSP == 1) */ 2080 | /*@} end of group CMSIS_SIMD_intrinsics */ 2081 | 2082 | 2083 | #pragma GCC diagnostic pop 2084 | 2085 | #endif /* __CMSIS_GCC_H */ 2086 | -------------------------------------------------------------------------------- /vendor/cmsis/cmsis_version.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************//** 2 | * @file cmsis_version.h 3 | * @brief CMSIS Core(M) Version definitions 4 | * @version V5.0.2 5 | * @date 19. April 2017 6 | ******************************************************************************/ 7 | /* 8 | * Copyright (c) 2009-2017 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 ( 1U) /*!< [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 | -------------------------------------------------------------------------------- /vendor/cmsis/stm32f10x.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mireq/st7789-stm32-driver/fa3d3470366c30afd2262db462fe894e3d56aa51/vendor/cmsis/stm32f10x.h -------------------------------------------------------------------------------- /vendor/cmsis/system_stm32f10x.h: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * @file system_stm32f10x.h 4 | * @author MCD Application Team 5 | * @version V3.5.0 6 | * @date 11-March-2011 7 | * @brief CMSIS Cortex-M3 Device Peripheral Access Layer System Header File. 8 | ****************************************************************************** 9 | * @attention 10 | * 11 | * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS 12 | * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE 13 | * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY 14 | * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING 15 | * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE 16 | * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. 17 | * 18 | *

© COPYRIGHT 2011 STMicroelectronics

19 | ****************************************************************************** 20 | */ 21 | 22 | /** @addtogroup CMSIS 23 | * @{ 24 | */ 25 | 26 | /** @addtogroup stm32f10x_system 27 | * @{ 28 | */ 29 | 30 | /** 31 | * @brief Define to prevent recursive inclusion 32 | */ 33 | #ifndef __SYSTEM_STM32F10X_H 34 | #define __SYSTEM_STM32F10X_H 35 | 36 | #ifdef __cplusplus 37 | extern "C" { 38 | #endif 39 | 40 | /** @addtogroup STM32F10x_System_Includes 41 | * @{ 42 | */ 43 | 44 | /** 45 | * @} 46 | */ 47 | 48 | 49 | /** @addtogroup STM32F10x_System_Exported_types 50 | * @{ 51 | */ 52 | 53 | extern uint32_t SystemCoreClock; /*!< System Clock Frequency (Core Clock) */ 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 2011 STMicroelectronics *****END OF FILE****/ 99 | --------------------------------------------------------------------------------