├── .gitignore ├── LICENSE ├── README.md ├── inc ├── TEMPLATE_nOSConfig.h ├── nOS.h └── port │ ├── GCC │ ├── ARM7TDMI │ │ └── nOSPort.h │ ├── ARM_Cortex_M0 │ │ └── nOSPort.h │ ├── ARM_Cortex_M3 │ │ └── nOSPort.h │ ├── ARM_Cortex_M4 │ │ └── nOSPort.h │ ├── ARM_Cortex_M7 │ │ └── nOSPort.h │ ├── AVR │ │ └── nOSPort.h │ ├── M16C_R8C │ │ └── nOSPort.h │ ├── MSP430 │ │ └── nOSPort.h │ └── RX600 │ │ └── nOSPort.h │ ├── IAR │ ├── ARM_Cortex_M0 │ │ └── nOSPort.h │ ├── ARM_Cortex_M3 │ │ └── nOSPort.h │ ├── ARM_Cortex_M4 │ │ └── nOSPort.h │ ├── ARM_Cortex_M7 │ │ └── nOSPort.h │ ├── AVR │ │ └── nOSPort.h │ ├── M16C_R8C │ │ └── nOSPort.h │ ├── MSP430 │ │ └── nOSPort.h │ ├── RX600 │ │ └── nOSPort.h │ └── STM8 │ │ └── nOSPort.h │ ├── Keil │ ├── ARM_Cortex_M0 │ │ └── nOSPort.h │ ├── ARM_Cortex_M3 │ │ └── nOSPort.h │ ├── ARM_Cortex_M4 │ │ └── nOSPort.h │ └── ARM_Cortex_M7 │ │ └── nOSPort.h │ ├── NC30 │ └── M16C_R8C │ │ └── nOSPort.h │ ├── POSIX │ └── nOSPort.h │ ├── WIN32 │ └── nOSPort.h │ └── XC16 │ └── PIC24 │ └── nOSPort.h └── src ├── nOSAlarm.c ├── nOSBarrier.c ├── nOSEvent.c ├── nOSFlag.c ├── nOSList.c ├── nOSMem.c ├── nOSMutex.c ├── nOSQueue.c ├── nOSSched.c ├── nOSSem.c ├── nOSSignal.c ├── nOSThread.c ├── nOSTime.c ├── nOSTimer.c └── port ├── GCC ├── ARM7_TDMI │ └── nOSPort.c ├── ARM_Cortex_M0 │ └── nOSPort.c ├── ARM_Cortex_M3 │ └── nOSPort.c ├── ARM_Cortex_M4 │ └── nOSPort.c ├── ARM_Cortex_M7 │ └── nOSPort.c ├── AVR │ └── nOSPort.c ├── M16C_R8C │ └── nOSPort.c ├── MSP430 │ └── nOSPort.c └── RX600 │ └── nOSPort.c ├── IAR ├── ARM_Cortex_M0 │ ├── nOSPort.c │ └── nOSPortASM.s ├── ARM_Cortex_M3 │ ├── nOSPort.c │ └── nOSPortASM.s ├── ARM_Cortex_M4 │ ├── nOSPort.c │ └── nOSPortASM.s ├── ARM_Cortex_M7 │ ├── nOSPort.c │ └── nOSPortASM.s ├── AVR │ └── nOSPort.c ├── M16C_R8C │ └── nOSPort.c ├── MSP430 │ └── nOSPort.c ├── RX600 │ ├── nOSPort.c │ └── nOSPortASM.s └── STM8 │ ├── nOSPort.c │ └── nOSPortASM.s ├── Keil ├── ARM_Cortex_M0 │ └── nOSPort.c ├── ARM_Cortex_M3 │ └── nOSPort.c ├── ARM_Cortex_M4 │ └── nOSPort.c └── ARM_Cortex_M7 │ └── nOSPort.c ├── NC30 └── M16C_R8C │ ├── nOSPort.c │ └── nOSPortASM.a30 ├── POSIX └── nOSPort.c ├── WIN32 └── nOSPort.c └── XC16 └── PIC24 └── nOSPort.c /.gitignore: -------------------------------------------------------------------------------- 1 | ################# 2 | ## Eclipse 3 | ################# 4 | 5 | *.pydevproject 6 | .project 7 | .metadata 8 | bin/ 9 | tmp/ 10 | *.tmp 11 | *.bak 12 | *.swp 13 | *~.nib 14 | local.properties 15 | .classpath 16 | .settings/ 17 | .loadpath 18 | 19 | # External tool builders 20 | .externalToolBuilders/ 21 | 22 | # Locally stored "Eclipse launch configurations" 23 | *.launch 24 | 25 | # CDT-specific 26 | .cproject 27 | 28 | # PDT-specific 29 | .buildpath 30 | 31 | 32 | ################# 33 | ## Visual Studio 34 | ################# 35 | 36 | ## Ignore Visual Studio temporary files, build results, and 37 | ## files generated by popular Visual Studio add-ons. 38 | 39 | # User-specific files 40 | *.suo 41 | *.user 42 | *.sln.docstates 43 | 44 | # Build results 45 | 46 | [Dd]ebug/ 47 | [Rr]elease/ 48 | x64/ 49 | build/ 50 | [Bb]in/ 51 | [Oo]bj/ 52 | *.o 53 | 54 | # MSTest test Results 55 | [Tt]est[Rr]esult*/ 56 | [Bb]uild[Ll]og.* 57 | 58 | *_i.c 59 | *_p.c 60 | *.ilk 61 | *.meta 62 | *.obj 63 | *.pch 64 | *.pdb 65 | *.pgc 66 | *.pgd 67 | *.rsp 68 | *.sbr 69 | *.tlb 70 | *.tli 71 | *.tlh 72 | *.tmp 73 | *.tmp_proj 74 | *.log 75 | *.vspscc 76 | *.vssscc 77 | .builds 78 | *.pidb 79 | *.log 80 | *.scc 81 | 82 | # Visual C++ cache files 83 | ipch/ 84 | *.aps 85 | *.ncb 86 | *.opensdf 87 | *.sdf 88 | *.cachefile 89 | 90 | # Visual Studio profiler 91 | *.psess 92 | *.vsp 93 | *.vspx 94 | 95 | # Guidance Automation Toolkit 96 | *.gpState 97 | 98 | # ReSharper is a .NET coding add-in 99 | _ReSharper*/ 100 | *.[Rr]e[Ss]harper 101 | 102 | # TeamCity is a build add-in 103 | _TeamCity* 104 | 105 | # DotCover is a Code Coverage Tool 106 | *.dotCover 107 | 108 | # NCrunch 109 | *.ncrunch* 110 | .*crunch*.local.xml 111 | 112 | # Installshield output folder 113 | [Ee]xpress/ 114 | 115 | # DocProject is a documentation generator add-in 116 | DocProject/buildhelp/ 117 | DocProject/Help/*.HxT 118 | DocProject/Help/*.HxC 119 | DocProject/Help/*.hhc 120 | DocProject/Help/*.hhk 121 | DocProject/Help/*.hhp 122 | DocProject/Help/Html2 123 | DocProject/Help/html 124 | 125 | # Click-Once directory 126 | publish/ 127 | 128 | # Publish Web Output 129 | *.Publish.xml 130 | *.pubxml 131 | *.publishproj 132 | 133 | # NuGet Packages Directory 134 | ## TODO: If you have NuGet Package Restore enabled, uncomment the next line 135 | #packages/ 136 | 137 | # Windows Azure Build Output 138 | csx 139 | *.build.csdef 140 | 141 | # Windows Store app package directory 142 | AppPackages/ 143 | 144 | # Others 145 | sql/ 146 | *.Cache 147 | ClientBin/ 148 | [Ss]tyle[Cc]op.* 149 | ~$* 150 | *~ 151 | *.dbmdl 152 | *.[Pp]ublish.xml 153 | *.pfx 154 | *.publishsettings 155 | 156 | # RIA/Silverlight projects 157 | Generated_Code/ 158 | 159 | # Backup & report files from converting an old project file to a newer 160 | # Visual Studio version. Backup files are not needed, because we have git ;-) 161 | _UpgradeReport_Files/ 162 | Backup*/ 163 | UpgradeLog*.XML 164 | UpgradeLog*.htm 165 | 166 | # SQL Server files 167 | App_Data/*.mdf 168 | App_Data/*.ldf 169 | 170 | ############# 171 | ## Windows detritus 172 | ############# 173 | 174 | # Windows image file caches 175 | Thumbs.db 176 | ehthumbs.db 177 | 178 | # Folder config file 179 | Desktop.ini 180 | 181 | # Recycle Bin used on file shares 182 | $RECYCLE.BIN/ 183 | 184 | # Mac crap 185 | .DS_Store 186 | 187 | 188 | ############# 189 | ## Python 190 | ############# 191 | 192 | *.py[cod] 193 | 194 | # Packages 195 | *.egg 196 | *.egg-info 197 | dist/ 198 | build/ 199 | eggs/ 200 | parts/ 201 | var/ 202 | sdist/ 203 | develop-eggs/ 204 | .installed.cfg 205 | 206 | # Installer logs 207 | pip-log.txt 208 | 209 | # Unit test / coverage reports 210 | .coverage 211 | .tox 212 | 213 | #Translations 214 | *.mo 215 | 216 | #Mr Developer 217 | .mr.developer.cfg 218 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # nOS 2 | 3 | [![Join the chat at https://gitter.im/jimtremblay/nOS](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/jimtremblay/nOS?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) 4 | [![MPLv2 License](https://img.shields.io/badge/license-MPLv2-blue.svg?style=flat)](https://www.mozilla.org/MPL/2.0/) 5 | 6 | ### Features: 7 | * Preemptive or cooperative scheduling (depending on your configuration) 8 | * Can be tickless for battery-powered application 9 | * Binary and counting semaphores 10 | * Mutexes with priority ceiling or priority inheritance 11 | * Queues for thread-safe communication 12 | * Flags for waiting on multiple events 13 | * Memory blocks for dynamic memory allocation 14 | * Software timers with callback and priority 15 | * Software interrupts (signal) with callback and priority 16 | * Real-time module compatible with UNIX timestamp 17 | * Software alarms with callback 18 | * No limits on number of nOS objects, except your available memory 19 | * Tiny footprint (as low as 1KB ROM/few bytes of RAM) 20 | * Fully configurable (ROM and RAM) 21 | * Open source, royalty free 22 | * Win32 and Linux simulator available 23 | 24 | [Documentation](https://github.com/jimtremblay/nOS/wiki) 25 | -------------------------------------------------------------------------------- /inc/port/GCC/ARM_Cortex_M0/nOSPort.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2019 Jim Tremblay 3 | * 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | */ 8 | 9 | #ifndef NOSPORT_H 10 | #define NOSPORT_H 11 | 12 | #ifdef __cplusplus 13 | extern "C" { 14 | #endif 15 | 16 | typedef uint32_t nOS_Stack; 17 | typedef uint32_t nOS_StatusReg; 18 | 19 | #define NOS_UNUSED(v) (void)v 20 | 21 | #define NOS_MEM_ALIGNMENT 4 22 | #define NOS_MEM_POINTER_WIDTH 4 23 | 24 | #define NOS_32_BITS_SCHEDULER 25 | 26 | #ifndef NOS_CONFIG_ISR_STACK_SIZE 27 | #error "nOSConfig.h: NOS_CONFIG_ISR_STACK_SIZE is not defined: must be higher than 0." 28 | #elif (NOS_CONFIG_ISR_STACK_SIZE == 0) 29 | #error "nOSConfig.h: NOS_CONFIG_ISR_STACK_SIZE is set to invalid value: must be higher than 0." 30 | #endif 31 | 32 | __attribute__( ( always_inline ) ) static inline uint32_t _GetMSP (void) 33 | { 34 | uint32_t r; 35 | __asm volatile ("MRS %0, MSP" : "=r" (r)); 36 | return r; 37 | } 38 | 39 | __attribute__( ( always_inline ) ) static inline void _SetMSP (uint32_t r) 40 | { 41 | __asm volatile ("MSR MSP, %0" :: "r" (r)); 42 | } 43 | 44 | __attribute__( ( always_inline ) ) static inline uint32_t _GetPSP (void) 45 | { 46 | uint32_t r; 47 | __asm volatile ("MRS %0, PSP" : "=r" (r)); 48 | return r; 49 | } 50 | 51 | __attribute__( ( always_inline ) ) static inline void _SetPSP (uint32_t r) 52 | { 53 | __asm volatile ("MSR PSP, %0" :: "r" (r)); 54 | } 55 | 56 | __attribute__( ( always_inline ) ) static inline uint32_t _GetCONTROL (void) 57 | { 58 | uint32_t r; 59 | __asm volatile ("MRS %0, CONTROL" : "=r" (r)); 60 | return r; 61 | } 62 | 63 | __attribute__( ( always_inline ) ) static inline void _SetCONTROL (uint32_t r) 64 | { 65 | __asm volatile ("MSR CONTROL, %0" :: "r" (r)); 66 | } 67 | 68 | __attribute__( ( always_inline ) ) static inline uint32_t _GetPRIMASK (void) 69 | { 70 | uint32_t r; 71 | __asm volatile ("MRS %0, PRIMASK" : "=r" (r)); 72 | return r; 73 | } 74 | 75 | __attribute__( ( always_inline ) ) static inline void _SetPRIMASK (uint32_t r) 76 | { 77 | __asm volatile ("MSR PRIMASK, %0" :: "r" (r)); 78 | } 79 | 80 | __attribute__( ( always_inline ) ) static inline void _DSB (void) 81 | { 82 | __asm volatile ("DSB"); 83 | } 84 | 85 | __attribute__( ( always_inline ) ) static inline void _ISB (void) 86 | { 87 | __asm volatile ("ISB"); 88 | } 89 | 90 | __attribute__( ( always_inline ) ) static inline void _NOP (void) 91 | { 92 | __asm volatile ("NOP"); 93 | } 94 | 95 | __attribute__( ( always_inline ) ) static inline void _DI (void) 96 | { 97 | __asm volatile ("CPSID I"); 98 | } 99 | 100 | __attribute__( ( always_inline ) ) static inline void _EI (void) 101 | { 102 | __asm volatile ("CPSIE I"); 103 | } 104 | 105 | #define nOS_EnterCritical(sr) \ 106 | do { \ 107 | sr = _GetPRIMASK(); \ 108 | _DI(); \ 109 | _DSB(); \ 110 | _ISB(); \ 111 | } while (0) 112 | 113 | #define nOS_LeaveCritical(sr) \ 114 | do { \ 115 | _SetPRIMASK(sr); \ 116 | _DSB(); \ 117 | _ISB(); \ 118 | } while (0) 119 | 120 | #define nOS_PeekCritical() \ 121 | do { \ 122 | _EI(); \ 123 | _DSB(); \ 124 | _ISB(); \ 125 | \ 126 | _NOP(); \ 127 | \ 128 | _DI(); \ 129 | _DSB(); \ 130 | _ISB(); \ 131 | } while (0) 132 | 133 | void nOS_EnterISR (void); 134 | void nOS_LeaveISR (void); 135 | 136 | #define NOS_ISR(func) \ 137 | void func##_ISR(void) __attribute__ ( ( always_inline ) ); \ 138 | void func(void) \ 139 | { \ 140 | nOS_EnterISR(); \ 141 | func##_ISR(); \ 142 | nOS_LeaveISR(); \ 143 | } \ 144 | inline void func##_ISR(void) 145 | 146 | #ifdef NOS_PRIVATE 147 | void nOS_InitSpecific (void); 148 | void nOS_InitContext (nOS_Thread *thread, nOS_Stack *stack, size_t ssize, nOS_ThreadEntry entry, void *arg); 149 | void nOS_SwitchContext (void); 150 | #endif 151 | 152 | #ifdef __cplusplus 153 | } 154 | #endif 155 | 156 | #endif /* NOSPORT_H */ 157 | -------------------------------------------------------------------------------- /inc/port/GCC/RX600/nOSPort.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2019 Jim Tremblay 3 | * 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | */ 8 | 9 | #ifndef NOSPORT_H 10 | #define NOSPORT_H 11 | 12 | #ifdef __cplusplus 13 | extern "C" { 14 | #endif 15 | 16 | typedef uint32_t nOS_Stack; 17 | typedef uint32_t nOS_StatusReg; 18 | 19 | #define NOS_UNUSED(v) (void)v 20 | 21 | #define NOS_MEM_ALIGNMENT 4 22 | #define NOS_MEM_POINTER_WIDTH 4 23 | 24 | #define NOS_32_BITS_SCHEDULER 25 | 26 | #ifdef NOS_CONFIG_MAX_UNSAFE_ISR_PRIO 27 | #if (NOS_CONFIG_MAX_UNSAFE_ISR_PRIO > 0) 28 | #define NOS_MAX_UNSAFE_IPL (NOS_CONFIG_MAX_UNSAFE_ISR_PRIO << 24) 29 | #else 30 | #undef NOS_CONFIG_MAX_UNSAFE_ISR_PRIO 31 | #endif 32 | #endif 33 | 34 | __attribute__( ( always_inline ) ) static inline uint32_t _GetIPL(void) 35 | { 36 | uint32_t ipl; 37 | __asm volatile( 38 | "MVFC PSW, %0 \n" 39 | "AND #0x0F000000, %0 \n" 40 | : "=r" (ipl) ); 41 | return ipl; 42 | } 43 | 44 | __attribute__( ( always_inline ) ) static inline void _SetIPL(uint32_t ipl) 45 | { 46 | uint32_t psw; 47 | __asm volatile( 48 | "MVFC PSW, %0 \n" 49 | "AND #0xF0FFFFFF, %0 \n" 50 | "OR %1, %0 \n" 51 | "MVTC %0, PSW \n" 52 | "NOP \n" 53 | : "=r" (psw), "=r" (ipl) ); 54 | } 55 | 56 | __attribute__( ( always_inline ) ) static inline uint32_t _GetI(void) 57 | { 58 | uint32_t i; 59 | __asm volatile( 60 | "MVFC PSW, %0 \n" 61 | "AND #0x00010000, %0 \n" 62 | : "=r" (i) ); 63 | return i; 64 | } 65 | 66 | __attribute__( ( always_inline ) ) static inline void _SetI(uint32_t i) 67 | { 68 | uint32_t psw; 69 | __asm volatile( 70 | "MVFC PSW, %0 \n" 71 | "AND #0xFFFEFFFF, %0 \n" 72 | "OR %1, %0 \n" 73 | "MVTC %0, PSW \n" 74 | "NOP \n" 75 | : "=r" (psw), "=r" (i) ); 76 | } 77 | 78 | __attribute( ( always_inline ) ) static inline void _EI(void) 79 | { 80 | __asm volatile( 81 | "SETPSW I \n" 82 | "NOP \n" 83 | ); 84 | } 85 | 86 | __attribute( ( always_inline ) ) static inline void _DI(void) 87 | { 88 | __asm volatile( 89 | "CLRPSW I \n" 90 | "NOP \n" 91 | ); 92 | } 93 | 94 | __attribute( ( always_inline ) ) static inline void _NOP(void) 95 | { 96 | __asm volatile("NOP"); 97 | } 98 | 99 | #ifdef NOS_MAX_UNSAFE_IPL 100 | #define nOS_EnterCritical(sr) \ 101 | do { \ 102 | sr = _GetIPL(); \ 103 | if (sr < NOS_MAX_UNSAFE_IPL) { \ 104 | _SetIPL(NOS_MAX_UNSAFE_IPL); \ 105 | } \ 106 | } while (0) 107 | 108 | #define nOS_LeaveCritical(sr) \ 109 | _SetIPL(sr) 110 | 111 | #define nOS_PeekCritical() \ 112 | do { \ 113 | _SetIPL(0); \ 114 | _NOP(); \ 115 | _SetIPL(NOS_MAX_UNSAFE_IPL); \ 116 | } while (0) 117 | #else 118 | #define nOS_EnterCritical(sr) \ 119 | do { \ 120 | sr = _GetI(); \ 121 | _DI(); \ 122 | } while (0) 123 | 124 | #define nOS_LeaveCritical(sr) \ 125 | _SetI(sr) 126 | 127 | #define nOS_PeekCritical() \ 128 | do { \ 129 | _EI(); \ 130 | _NOP(); \ 131 | _DI(); \ 132 | } while (0) 133 | #endif 134 | 135 | #define nOS_SwitchContext() __asm("INT #27") 136 | 137 | void nOS_EnterISR (void); 138 | void nOS_LeaveISR (void); 139 | 140 | #define NOS_ISR(vect) \ 141 | void vect(void) __attribute__ ( ( interrupt ) ); \ 142 | void vect##_ISR(void); \ 143 | void vect(void) \ 144 | { \ 145 | nOS_EnterISR(); \ 146 | vect##_ISR(); \ 147 | _DI(); \ 148 | nOS_LeaveISR(); \ 149 | } \ 150 | __attribute__ ( ( always_inline ) ) inline void vect##_ISR(void) 151 | 152 | #ifdef NOS_PRIVATE 153 | void nOS_InitSpecific (void); 154 | void nOS_InitContext (nOS_Thread *thread, nOS_Stack *stack, size_t ssize, nOS_ThreadEntry entry, void *arg); 155 | #endif 156 | 157 | #ifdef __cplusplus 158 | } 159 | #endif 160 | 161 | #endif /* NOSPORT_H */ 162 | -------------------------------------------------------------------------------- /inc/port/IAR/ARM_Cortex_M0/nOSPort.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2019 Jim Tremblay 3 | * 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | */ 8 | 9 | #ifndef NOSPORT_H 10 | #define NOSPORT_H 11 | 12 | #include 13 | 14 | #ifdef __cplusplus 15 | extern "C" { 16 | #endif 17 | 18 | typedef uint32_t nOS_Stack; 19 | typedef uint32_t nOS_StatusReg; 20 | 21 | #define NOS_UNUSED(v) (void)v 22 | 23 | #define NOS_MEM_ALIGNMENT 4 24 | #define NOS_MEM_POINTER_WIDTH 4 25 | 26 | #define NOS_32_BITS_SCHEDULER 27 | 28 | #ifndef NOS_CONFIG_ISR_STACK_SIZE 29 | #error "nOSConfig.h: NOS_CONFIG_ISR_STACK_SIZE is not defined: must be higher than 0." 30 | #elif (NOS_CONFIG_ISR_STACK_SIZE == 0) 31 | #error "nOSConfig.h: NOS_CONFIG_ISR_STACK_SIZE is set to invalid value: must be higher than 0." 32 | #endif 33 | 34 | #define nOS_EnterCritical(sr) \ 35 | do { \ 36 | sr = __get_PRIMASK(); \ 37 | __disable_interrupt(); \ 38 | __DSB(); \ 39 | __ISB(); \ 40 | } while (0) 41 | 42 | #define nOS_LeaveCritical(sr) \ 43 | do { \ 44 | __set_PRIMASK(sr); \ 45 | __DSB(); \ 46 | __ISB(); \ 47 | } while (0) 48 | 49 | #define nOS_PeekCritical() \ 50 | do { \ 51 | __enable_interrupt(); \ 52 | __DSB(); \ 53 | __ISB(); \ 54 | \ 55 | __no_operation(); \ 56 | \ 57 | __disable_interrupt(); \ 58 | __DSB(); \ 59 | __ISB(); \ 60 | } while (0) 61 | 62 | void nOS_EnterISR (void); 63 | void nOS_LeaveISR (void); 64 | 65 | #define NOS_ISR(func) \ 66 | void func##_ISR(void); \ 67 | void func(void) \ 68 | { \ 69 | nOS_EnterISR(); \ 70 | func##_ISR(); \ 71 | nOS_LeaveISR(); \ 72 | } \ 73 | void func##_ISR(void) 74 | 75 | #ifdef NOS_PRIVATE 76 | void nOS_InitSpecific (void); 77 | void nOS_InitContext (nOS_Thread *thread, nOS_Stack *stack, size_t ssize, nOS_ThreadEntry entry, void *arg); 78 | void nOS_SwitchContext (void); 79 | #endif 80 | 81 | #ifdef __cplusplus 82 | } 83 | #endif 84 | 85 | #endif /* NOSPORT_H */ 86 | -------------------------------------------------------------------------------- /inc/port/IAR/ARM_Cortex_M3/nOSPort.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2019 Jim Tremblay 3 | * 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | */ 8 | 9 | #ifndef NOSPORT_H 10 | #define NOSPORT_H 11 | 12 | #include 13 | 14 | #ifdef __cplusplus 15 | extern "C" { 16 | #endif 17 | 18 | typedef uint32_t nOS_Stack; 19 | typedef uint32_t nOS_StatusReg; 20 | 21 | #define NOS_UNUSED(v) (void)v 22 | 23 | #define NOS_MEM_ALIGNMENT 4 24 | #define NOS_MEM_POINTER_WIDTH 4 25 | 26 | #define NOS_32_BITS_SCHEDULER 27 | #define NOS_USE_CLZ 28 | 29 | #ifndef NOS_CONFIG_ISR_STACK_SIZE 30 | #error "nOSConfig.h: NOS_CONFIG_ISR_STACK_SIZE is not defined: must be higher than 0." 31 | #elif (NOS_CONFIG_ISR_STACK_SIZE == 0) 32 | #error "nOSConfig.h: NOS_CONFIG_ISR_STACK_SIZE is set to invalid value: must be higher than 0." 33 | #endif 34 | 35 | /* __NVIC_PRIO_BITS defined from CMSIS if used */ 36 | #ifdef NOS_CONFIG_NVIC_PRIO_BITS 37 | #define NOS_NVIC_PRIO_BITS NOS_CONFIG_NVIC_PRIO_BITS 38 | #elif defined(__NVIC_PRIO_BITS) 39 | #define NOS_NVIC_PRIO_BITS __NVIC_PRIO_BITS 40 | #else 41 | #define NOS_NVIC_PRIO_BITS 4 42 | #endif 43 | 44 | #ifdef NOS_CONFIG_MAX_UNSAFE_ISR_PRIO 45 | #if (NOS_CONFIG_MAX_UNSAFE_ISR_PRIO > 0) 46 | #define NOS_MAX_UNSAFE_BASEPRI (NOS_CONFIG_MAX_UNSAFE_ISR_PRIO << (8 - NOS_NVIC_PRIO_BITS)) 47 | #else 48 | #undef NOS_NVIC_PRIO_BITS 49 | #undef NOS_CONFIG_MAX_UNSAFE_ISR_PRIO 50 | #endif 51 | #endif 52 | 53 | #define _CLZ(n) __CLZ(n) 54 | 55 | #ifdef NOS_MAX_UNSAFE_BASEPRI 56 | #define nOS_EnterCritical(sr) \ 57 | do { \ 58 | sr = __get_BASEPRI(); \ 59 | if (sr == 0 || sr > NOS_MAX_UNSAFE_BASEPRI) { \ 60 | __set_BASEPRI(NOS_MAX_UNSAFE_BASEPRI); \ 61 | __DSB(); \ 62 | __ISB(); \ 63 | } \ 64 | } while (0) 65 | 66 | #define nOS_LeaveCritical(sr) \ 67 | do { \ 68 | __set_BASEPRI(sr); \ 69 | __DSB(); \ 70 | __ISB(); \ 71 | } while (0) 72 | 73 | #define nOS_PeekCritical() \ 74 | do { \ 75 | __set_BASEPRI(0); \ 76 | __DSB(); \ 77 | __ISB(); \ 78 | \ 79 | __no_operation(); \ 80 | \ 81 | __set_BASEPRI(NOS_MAX_UNSAFE_BASEPRI); \ 82 | __DSB(); \ 83 | __ISB(); \ 84 | } while (0) 85 | #else 86 | #define nOS_EnterCritical(sr) \ 87 | do { \ 88 | sr = __get_PRIMASK(); \ 89 | __disable_interrupt(); \ 90 | __DSB(); \ 91 | __ISB(); \ 92 | } while (0) 93 | 94 | #define nOS_LeaveCritical(sr) \ 95 | do { \ 96 | __set_PRIMASK(sr); \ 97 | __DSB(); \ 98 | __ISB(); \ 99 | } while (0) 100 | 101 | #define nOS_PeekCritical() \ 102 | do { \ 103 | __enable_interrupt(); \ 104 | __DSB(); \ 105 | __ISB(); \ 106 | \ 107 | __no_operation(); \ 108 | \ 109 | __disable_interrupt(); \ 110 | __DSB(); \ 111 | __ISB(); \ 112 | } while (0) 113 | #endif 114 | 115 | void nOS_EnterISR (void); 116 | void nOS_LeaveISR (void); 117 | 118 | #define NOS_ISR(func) \ 119 | void func##_ISR(void); \ 120 | void func(void) \ 121 | { \ 122 | nOS_EnterISR(); \ 123 | func##_ISR(); \ 124 | nOS_LeaveISR(); \ 125 | } \ 126 | void func##_ISR(void) 127 | 128 | #ifdef NOS_PRIVATE 129 | void nOS_InitSpecific (void); 130 | void nOS_InitContext (nOS_Thread *thread, nOS_Stack *stack, size_t ssize, nOS_ThreadEntry entry, void *arg); 131 | void nOS_SwitchContext (void); 132 | #endif 133 | 134 | #ifdef __cplusplus 135 | } 136 | #endif 137 | 138 | #endif /* NOSPORT_H */ 139 | -------------------------------------------------------------------------------- /inc/port/IAR/ARM_Cortex_M4/nOSPort.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2019 Jim Tremblay 3 | * 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | */ 8 | 9 | #ifndef NOSPORT_H 10 | #define NOSPORT_H 11 | 12 | #include 13 | 14 | #ifdef __cplusplus 15 | extern "C" { 16 | #endif 17 | 18 | typedef uint32_t nOS_Stack; 19 | typedef uint32_t nOS_StatusReg; 20 | 21 | #define NOS_UNUSED(v) (void)v 22 | 23 | #define NOS_MEM_ALIGNMENT 4 24 | #define NOS_MEM_POINTER_WIDTH 4 25 | 26 | #define NOS_32_BITS_SCHEDULER 27 | #define NOS_USE_CLZ 28 | 29 | #ifndef NOS_CONFIG_ISR_STACK_SIZE 30 | #error "nOSConfig.h: NOS_CONFIG_ISR_STACK_SIZE is not defined: must be higher than 0." 31 | #elif (NOS_CONFIG_ISR_STACK_SIZE == 0) 32 | #error "nOSConfig.h: NOS_CONFIG_ISR_STACK_SIZE is set to invalid value: must be higher than 0." 33 | #endif 34 | 35 | /* __NVIC_PRIO_BITS defined from CMSIS if used */ 36 | #ifdef NOS_CONFIG_NVIC_PRIO_BITS 37 | #define NOS_NVIC_PRIO_BITS NOS_CONFIG_NVIC_PRIO_BITS 38 | #elif defined(__NVIC_PRIO_BITS) 39 | #define NOS_NVIC_PRIO_BITS __NVIC_PRIO_BITS 40 | #else 41 | #define NOS_NVIC_PRIO_BITS 4 42 | #endif 43 | 44 | #ifdef NOS_CONFIG_MAX_UNSAFE_ISR_PRIO 45 | #if (NOS_CONFIG_MAX_UNSAFE_ISR_PRIO > 0) 46 | #define NOS_MAX_UNSAFE_BASEPRI (NOS_CONFIG_MAX_UNSAFE_ISR_PRIO << (8 - NOS_NVIC_PRIO_BITS)) 47 | #else 48 | #undef NOS_NVIC_PRIO_BITS 49 | #undef NOS_CONFIG_MAX_UNSAFE_ISR_PRIO 50 | #endif 51 | #endif 52 | 53 | #define _CLZ(n) __CLZ(n) 54 | 55 | #ifdef NOS_MAX_UNSAFE_BASEPRI 56 | #define nOS_EnterCritical(sr) \ 57 | do { \ 58 | sr = __get_BASEPRI(); \ 59 | if (sr == 0 || sr > NOS_MAX_UNSAFE_BASEPRI) { \ 60 | __set_BASEPRI(NOS_MAX_UNSAFE_BASEPRI); \ 61 | __DSB(); \ 62 | __ISB(); \ 63 | } \ 64 | } while (0) 65 | 66 | #define nOS_LeaveCritical(sr) \ 67 | do { \ 68 | __set_BASEPRI(sr); \ 69 | __DSB(); \ 70 | __ISB(); \ 71 | } while (0) 72 | 73 | #define nOS_PeekCritical() \ 74 | do { \ 75 | __set_BASEPRI(0); \ 76 | __DSB(); \ 77 | __ISB(); \ 78 | \ 79 | __no_operation(); \ 80 | \ 81 | __set_BASEPRI(NOS_MAX_UNSAFE_BASEPRI); \ 82 | __DSB(); \ 83 | __ISB(); \ 84 | } while (0) 85 | #else 86 | #define nOS_EnterCritical(sr) \ 87 | do { \ 88 | sr = __get_PRIMASK(); \ 89 | __disable_interrupt(); \ 90 | __DSB(); \ 91 | __ISB(); \ 92 | } while (0) 93 | 94 | #define nOS_LeaveCritical(sr) \ 95 | do { \ 96 | __set_PRIMASK(sr); \ 97 | __DSB(); \ 98 | __ISB(); \ 99 | } while (0) 100 | 101 | #define nOS_PeekCritical() \ 102 | do { \ 103 | __enable_interrupt(); \ 104 | __DSB(); \ 105 | __ISB(); \ 106 | \ 107 | __no_operation(); \ 108 | \ 109 | __disable_interrupt(); \ 110 | __DSB(); \ 111 | __ISB(); \ 112 | } while (0) 113 | #endif 114 | 115 | void nOS_EnterISR (void); 116 | void nOS_LeaveISR (void); 117 | 118 | #define NOS_ISR(func) \ 119 | void func##_ISR(void); \ 120 | void func(void) \ 121 | { \ 122 | nOS_EnterISR(); \ 123 | func##_ISR(); \ 124 | nOS_LeaveISR(); \ 125 | } \ 126 | void func##_ISR(void) 127 | 128 | #ifdef NOS_PRIVATE 129 | void nOS_InitSpecific (void); 130 | void nOS_InitContext (nOS_Thread *thread, nOS_Stack *stack, size_t ssize, nOS_ThreadEntry entry, void *arg); 131 | void nOS_SwitchContext (void); 132 | #endif 133 | 134 | #ifdef __cplusplus 135 | } 136 | #endif 137 | 138 | #endif /* NOSPORT_H */ 139 | -------------------------------------------------------------------------------- /inc/port/IAR/ARM_Cortex_M7/nOSPort.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2019 Jim Tremblay 3 | * 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | */ 8 | 9 | #ifndef NOSPORT_H 10 | #define NOSPORT_H 11 | 12 | #include 13 | 14 | #ifdef __cplusplus 15 | extern "C" { 16 | #endif 17 | 18 | typedef uint32_t nOS_Stack; 19 | typedef uint32_t nOS_StatusReg; 20 | 21 | #define NOS_UNUSED(v) (void)v 22 | 23 | #define NOS_MEM_ALIGNMENT 4 24 | #define NOS_MEM_POINTER_WIDTH 4 25 | 26 | #define NOS_32_BITS_SCHEDULER 27 | #define NOS_USE_CLZ 28 | 29 | #ifndef NOS_CONFIG_ISR_STACK_SIZE 30 | #error "nOSConfig.h: NOS_CONFIG_ISR_STACK_SIZE is not defined: must be higher than 0." 31 | #elif (NOS_CONFIG_ISR_STACK_SIZE == 0) 32 | #error "nOSConfig.h: NOS_CONFIG_ISR_STACK_SIZE is set to invalid value: must be higher than 0." 33 | #endif 34 | 35 | /* __NVIC_PRIO_BITS defined from CMSIS if used */ 36 | #ifdef NOS_CONFIG_NVIC_PRIO_BITS 37 | #define NOS_NVIC_PRIO_BITS NOS_CONFIG_NVIC_PRIO_BITS 38 | #elif defined(__NVIC_PRIO_BITS) 39 | #define NOS_NVIC_PRIO_BITS __NVIC_PRIO_BITS 40 | #else 41 | #define NOS_NVIC_PRIO_BITS 4 42 | #endif 43 | 44 | #ifdef NOS_CONFIG_MAX_UNSAFE_ISR_PRIO 45 | #if (NOS_CONFIG_MAX_UNSAFE_ISR_PRIO > 0) 46 | #define NOS_MAX_UNSAFE_BASEPRI (NOS_CONFIG_MAX_UNSAFE_ISR_PRIO << (8 - NOS_NVIC_PRIO_BITS)) 47 | #else 48 | #undef NOS_NVIC_PRIO_BITS 49 | #undef NOS_CONFIG_MAX_UNSAFE_ISR_PRIO 50 | #endif 51 | #endif 52 | 53 | #define _CLZ(n) __CLZ(n) 54 | 55 | #ifdef NOS_MAX_UNSAFE_BASEPRI 56 | #define nOS_EnterCritical(sr) \ 57 | do { \ 58 | sr = __get_BASEPRI(); \ 59 | if (sr == 0 || sr > NOS_MAX_UNSAFE_BASEPRI) { \ 60 | __set_BASEPRI(NOS_MAX_UNSAFE_BASEPRI); \ 61 | __DSB(); \ 62 | __ISB(); \ 63 | } \ 64 | } while (0) 65 | 66 | #define nOS_LeaveCritical(sr) \ 67 | do { \ 68 | __set_BASEPRI(sr); \ 69 | __DSB(); \ 70 | __ISB(); \ 71 | } while (0) 72 | 73 | #define nOS_PeekCritical() \ 74 | do { \ 75 | __set_BASEPRI(0); \ 76 | __DSB(); \ 77 | __ISB(); \ 78 | __no_operation(); \ 79 | __set_BASEPRI(NOS_MAX_UNSAFE_BASEPRI); \ 80 | __DSB(); \ 81 | __ISB(); \ 82 | } while (0) 83 | #else 84 | #define nOS_EnterCritical(sr) \ 85 | do { \ 86 | sr = __get_PRIMASK(); \ 87 | __disable_interrupt(); \ 88 | __DSB(); \ 89 | __ISB(); \ 90 | } while (0) 91 | 92 | #define nOS_LeaveCritical(sr) \ 93 | do { \ 94 | __set_PRIMASK(sr); \ 95 | __DSB(); \ 96 | __ISB(); \ 97 | } while (0) 98 | 99 | #define nOS_PeekCritical() \ 100 | do { \ 101 | __enable_interrupt(); \ 102 | __DSB(); \ 103 | __ISB(); \ 104 | \ 105 | __no_operation(); \ 106 | \ 107 | __disable_interrupt(); \ 108 | __DSB(); \ 109 | __ISB(); \ 110 | } while (0) 111 | #endif 112 | 113 | void nOS_EnterISR (void); 114 | void nOS_LeaveISR (void); 115 | 116 | #define NOS_ISR(func) \ 117 | void func##_ISR(void); \ 118 | void func(void) \ 119 | { \ 120 | nOS_EnterISR(); \ 121 | func##_ISR(); \ 122 | nOS_LeaveISR(); \ 123 | } \ 124 | void func##_ISR(void) 125 | 126 | #ifdef NOS_PRIVATE 127 | void nOS_InitSpecific (void); 128 | void nOS_InitContext (nOS_Thread *thread, nOS_Stack *stack, size_t ssize, nOS_ThreadEntry entry, void *arg); 129 | void nOS_SwitchContext (void); 130 | #endif 131 | 132 | #ifdef __cplusplus 133 | } 134 | #endif 135 | 136 | #endif /* NOSPORT_H */ 137 | -------------------------------------------------------------------------------- /inc/port/IAR/RX600/nOSPort.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2019 Jim Tremblay 3 | * 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | */ 8 | 9 | #ifndef NOSPORT_H 10 | #define NOSPORT_H 11 | 12 | #include 13 | 14 | #ifdef __cplusplus 15 | extern "C" { 16 | #endif 17 | 18 | typedef uint32_t nOS_Stack; 19 | 20 | #define NOS_UNUSED(v) (void)v 21 | 22 | #define NOS_MEM_ALIGNMENT 4 23 | #define NOS_MEM_POINTER_WIDTH 4 24 | 25 | #define NOS_32_BITS_SCHEDULER 26 | 27 | #ifndef NOS_CONFIG_ISR_STACK_SIZE 28 | #error "nOSConfig.h: NOS_CONFIG_ISR_STACK_SIZE is not defined: must be higher than 0." 29 | #elif (NOS_CONFIG_ISR_STACK_SIZE == 0) 30 | #error "nOSConfig.h: NOS_CONFIG_ISR_STACK_SIZE is set to invalid value: must be higher than 0." 31 | #endif 32 | 33 | #ifdef NOS_CONFIG_MAX_UNSAFE_ISR_PRIO 34 | #if (NOS_CONFIG_MAX_UNSAFE_ISR_PRIO > 0) 35 | #define NOS_MAX_UNSAFE_IPL NOS_CONFIG_MAX_UNSAFE_ISR_PRIO 36 | #else 37 | #undef NOS_CONFIG_MAX_UNSAFE_ISR_PRIO 38 | #endif 39 | #endif 40 | 41 | #ifndef NOS_MAX_UNSAFE_IPL 42 | typedef __istate_t nOS_StatusReg; 43 | #else 44 | typedef __ilevel_t nOS_StatusReg; 45 | #endif 46 | 47 | #ifdef NOS_MAX_UNSAFE_IPL 48 | #define nOS_EnterCritical(sr) \ 49 | do { \ 50 | sr = __get_interrupt_level(); \ 51 | if (sr < NOS_MAX_UNSAFE_IPL) { \ 52 | __set_interrupt_level(NOS_MAX_UNSAFE_IPL); \ 53 | } \ 54 | } while (0) 55 | 56 | #define nOS_LeaveCritical(sr) \ 57 | __set_interrupt_level(sr) 58 | 59 | #define nOS_PeekCritical() \ 60 | do { \ 61 | __set_interrupt_level(0); \ 62 | __no_operation(); \ 63 | __set_interrupt_level(NOS_MAX_UNSAFE_IPL); \ 64 | } while (0) 65 | #else 66 | #define nOS_EnterCritical(sr) \ 67 | do { \ 68 | sr = __get_interrupt_state(); \ 69 | __disable_interrupt(); \ 70 | } while (0) 71 | 72 | #define nOS_LeaveCritical(sr) \ 73 | __set_interrupt_state(sr) 74 | 75 | #define nOS_PeekCritical() \ 76 | do { \ 77 | __enable_interrupt(); \ 78 | __no_operation(); \ 79 | __disable_interrupt(); \ 80 | } while (0) 81 | #endif 82 | 83 | #define nOS_SwitchContext() __asm("INT #27") 84 | 85 | void nOS_EnterISR (void); 86 | void nOS_LeaveISR (void); 87 | 88 | #define NOS_ISR(vect) \ 89 | void vect##_ISR_L2(void); \ 90 | _Pragma(_STRINGIFY(vector=vect)) \ 91 | __interrupt void vect##_ISR(void) \ 92 | { \ 93 | nOS_EnterISR(); \ 94 | vect##_ISR_L2(); \ 95 | __disable_interrupt(); \ 96 | nOS_LeaveISR(); \ 97 | } \ 98 | inline void vect##_ISR_L2(void) 99 | 100 | #ifdef NOS_PRIVATE 101 | void nOS_InitSpecific (void); 102 | void nOS_InitContext (nOS_Thread *thread, nOS_Stack *stack, size_t ssize, nOS_ThreadEntry entry, void *arg); 103 | #endif 104 | 105 | #ifdef __cplusplus 106 | } 107 | #endif 108 | 109 | #endif /* NOSPORT_H */ 110 | -------------------------------------------------------------------------------- /inc/port/Keil/ARM_Cortex_M0/nOSPort.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2019 Jim Tremblay 3 | * 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | */ 8 | 9 | #ifndef NOSPORT_H 10 | #define NOSPORT_H 11 | 12 | #ifdef __cplusplus 13 | extern "C" { 14 | #endif 15 | 16 | typedef uint32_t nOS_Stack; 17 | typedef uint32_t nOS_StatusReg; 18 | 19 | #define NOS_UNUSED(v) (void)v 20 | 21 | #define NOS_MEM_ALIGNMENT 4 22 | #define NOS_MEM_POINTER_WIDTH 4 23 | 24 | #define NOS_32_BITS_SCHEDULER 25 | 26 | #ifndef NOS_CONFIG_ISR_STACK_SIZE 27 | #error "nOSConfig.h: NOS_CONFIG_ISR_STACK_SIZE is not defined: must be higher than 0." 28 | #elif (NOS_CONFIG_ISR_STACK_SIZE == 0) 29 | #error "nOSConfig.h: NOS_CONFIG_ISR_STACK_SIZE is set to invalid value: must be higher than 0." 30 | #endif 31 | 32 | static inline uint32_t _GetMSP (void) 33 | { 34 | register uint32_t volatile _msp __asm("msp"); 35 | 36 | return _msp; 37 | } 38 | 39 | static inline void _SetMSP (uint32_t r) 40 | { 41 | register uint32_t volatile _msp __asm("msp"); 42 | 43 | _msp = r; 44 | } 45 | 46 | static inline uint32_t _GetPSP (void) 47 | { 48 | register uint32_t volatile _psp __asm("psp"); 49 | 50 | return _psp; 51 | } 52 | 53 | static inline void _SetPSP (uint32_t r) 54 | { 55 | register uint32_t volatile _psp __asm("psp"); 56 | 57 | _psp = r; 58 | } 59 | 60 | static inline uint32_t _GetCONTROL (void) 61 | { 62 | register uint32_t volatile _control __asm("control"); 63 | 64 | return _control; 65 | } 66 | 67 | static inline void _SetCONTROL (uint32_t r) 68 | { 69 | register uint32_t volatile _control __asm("control"); 70 | 71 | _control = r; 72 | } 73 | 74 | static inline uint32_t _GetPRIMASK (void) 75 | { 76 | register uint32_t volatile _primask __asm("primask"); 77 | 78 | return _primask; 79 | } 80 | 81 | static inline void _SetPRIMASK (uint32_t r) 82 | { 83 | register uint32_t volatile _primask __asm("primask"); 84 | 85 | _primask = r; 86 | } 87 | 88 | #define nOS_EnterCritical(sr) \ 89 | do { \ 90 | sr = _GetPRIMASK(); \ 91 | __disable_irq(); \ 92 | __dsb(0xF); \ 93 | __isb(0xF); \ 94 | } while (0) 95 | 96 | #define nOS_LeaveCritical(sr) \ 97 | do { \ 98 | _SetPRIMASK(sr); \ 99 | __dsb(0xF); \ 100 | __isb(0xF); \ 101 | } while (0) 102 | 103 | #define nOS_PeekCritical() \ 104 | do { \ 105 | __enable_irq(); \ 106 | __dsb(0xF); \ 107 | __isb(0xF); \ 108 | \ 109 | __nop(); \ 110 | \ 111 | __disable_irq(); \ 112 | __dsb(0xF); \ 113 | __isb(0xF); \ 114 | } while (0) 115 | 116 | void nOS_EnterISR (void); 117 | void nOS_LeaveISR (void); 118 | 119 | #define NOS_ISR(func) \ 120 | void func##_ISR(void); \ 121 | void func(void) \ 122 | { \ 123 | nOS_EnterISR(); \ 124 | func##_ISR(); \ 125 | nOS_LeaveISR(); \ 126 | } \ 127 | void func##_ISR(void) 128 | 129 | #ifdef NOS_PRIVATE 130 | void nOS_InitSpecific (void); 131 | void nOS_InitContext (nOS_Thread *thread, nOS_Stack *stack, size_t ssize, nOS_ThreadEntry entry, void *arg); 132 | void nOS_SwitchContext (void); 133 | #endif 134 | 135 | #ifdef __cplusplus 136 | } 137 | #endif 138 | 139 | #endif /* NOSPORT_H */ 140 | -------------------------------------------------------------------------------- /inc/port/POSIX/nOSPort.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2019 Jim Tremblay 3 | * 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | */ 8 | 9 | #ifndef NOSPORT_H 10 | #define NOSPORT_H 11 | 12 | #include 13 | 14 | #ifdef __cplusplus 15 | extern "C" { 16 | #endif 17 | 18 | #define NOS_UNUSED(v) (void)v 19 | 20 | #define NOS_MEM_ALIGNMENT 8 21 | #ifdef __x86_64__ 22 | #define NOS_MEM_POINTER_WIDTH 8 23 | #else 24 | #define NOS_MEM_POINTER_WIDTH 4 25 | #endif 26 | 27 | #define NOS_32_BITS_SCHEDULER 28 | 29 | #define NOS_SIMULATED_STACK 30 | 31 | typedef struct nOS_Stack 32 | { 33 | pthread_t handle; 34 | nOS_ThreadEntry entry; 35 | void *arg; 36 | uint32_t crit; 37 | pthread_cond_t cond; 38 | bool started; 39 | bool running; 40 | } nOS_Stack; 41 | 42 | typedef uint32_t nOS_StatusReg; 43 | 44 | #ifndef NOS_CONFIG_TICKS_PER_SECOND 45 | #error "nOSConfig.h: NOS_CONFIG_TICKS_PER_SECOND is not defined: must be set between 1 and 100 inclusively." 46 | #elif (NOS_CONFIG_TICKS_PER_SECOND < 1) || (NOS_CONFIG_TICKS_PER_SECOND > 100) 47 | #error "nOSConfig.h: NOS_CONFIG_TICKS_PER_SECOND is set to invalid value: must be set between 1 and 100 inclusively." 48 | #endif 49 | 50 | #define nOS_EnterCritical(sr) \ 51 | do { \ 52 | NOS_UNUSED(sr); \ 53 | pthread_mutex_lock(&nOS_criticalSection); \ 54 | if (nOS_criticalNestingCounter > 0) { \ 55 | /* Lock mutex only one time */ \ 56 | pthread_mutex_unlock(&nOS_criticalSection); \ 57 | } \ 58 | nOS_criticalNestingCounter++; \ 59 | } while (0) 60 | 61 | #define nOS_LeaveCritical(sr) \ 62 | do { \ 63 | NOS_UNUSED(sr); \ 64 | nOS_criticalNestingCounter--; \ 65 | if (nOS_criticalNestingCounter == 0) { \ 66 | /* Unlock mutex when nesting counter reach zero */ \ 67 | pthread_mutex_unlock(&nOS_criticalSection); \ 68 | } \ 69 | } while (0) 70 | 71 | #define nOS_PeekCritical() \ 72 | do { \ 73 | uint32_t count = nOS_criticalNestingCounter; \ 74 | /* Leave critical section */ \ 75 | nOS_criticalNestingCounter = 0; \ 76 | pthread_mutex_unlock(&nOS_criticalSection); \ 77 | \ 78 | /* Enter critical section */ \ 79 | pthread_mutex_lock(&nOS_criticalSection); \ 80 | nOS_criticalNestingCounter = count; \ 81 | } while (0) 82 | 83 | extern volatile uint32_t nOS_criticalNestingCounter; 84 | extern pthread_mutex_t nOS_criticalSection; 85 | 86 | int nOS_Print (const char *format, ...); 87 | 88 | #ifdef NOS_PRIVATE 89 | void nOS_InitSpecific (void); 90 | void nOS_InitContext (nOS_Thread *thread, nOS_Stack *stack, size_t ssize, nOS_ThreadEntry entry, void *arg); 91 | void nOS_SwitchContext (void); 92 | #endif 93 | 94 | #ifdef __cplusplus 95 | } 96 | #endif 97 | 98 | #endif /* NOSPORT_H */ 99 | -------------------------------------------------------------------------------- /inc/port/WIN32/nOSPort.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2019 Jim Tremblay 3 | * 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | */ 8 | 9 | #ifndef NOSPORT_H 10 | #define NOSPORT_H 11 | 12 | #include 13 | 14 | #ifdef __cplusplus 15 | extern "C" { 16 | #endif 17 | 18 | #define NOS_UNUSED(v) (void)v 19 | 20 | #define NOS_MEM_ALIGNMENT 8 21 | #define NOS_MEM_POINTER_WIDTH 4 22 | 23 | #define NOS_32_BITS_SCHEDULER 24 | 25 | #define NOS_SIMULATED_STACK 26 | 27 | typedef struct nOS_Stack 28 | { 29 | HANDLE handle; 30 | DWORD id; 31 | nOS_ThreadEntry entry; 32 | void *arg; 33 | bool sync; 34 | HANDLE hsync; 35 | } nOS_Stack; 36 | 37 | typedef DWORD nOS_StatusReg; 38 | 39 | #ifndef NOS_CONFIG_TICKS_PER_SECOND 40 | #error "nOSConfig.h: NOS_CONFIG_TICKS_PER_SECOND is not defined: must be set between 1 and 100 inclusively." 41 | #elif (NOS_CONFIG_TICKS_PER_SECOND < 1) || (NOS_CONFIG_TICKS_PER_SECOND > 100) 42 | #error "nOSConfig.h: NOS_CONFIG_TICKS_PER_SECOND is set to invalid value: must be set between 1 and 100 inclusively." 43 | #endif 44 | 45 | #define nOS_EnterCritical(sr) \ 46 | do { \ 47 | NOS_UNUSED(sr); \ 48 | if (nOS_running) { \ 49 | /* Enter critical section */ \ 50 | while(WaitForSingleObject(nOS_hCritical, INFINITE) != WAIT_OBJECT_0);\ 51 | if (nOS_criticalNestingCounter > 0) { \ 52 | /* Keep only one level of lock to leave critical section */ \ 53 | ReleaseMutex(nOS_hCritical); \ 54 | } \ 55 | nOS_criticalNestingCounter++; \ 56 | } \ 57 | } while (0) 58 | 59 | #define nOS_LeaveCritical(sr) \ 60 | do { \ 61 | NOS_UNUSED(sr); \ 62 | if (nOS_running) { \ 63 | nOS_criticalNestingCounter--; \ 64 | if (nOS_criticalNestingCounter == 0) { \ 65 | /* Leave critical section */ \ 66 | ReleaseMutex(nOS_hCritical); \ 67 | } \ 68 | } \ 69 | } while (0) 70 | 71 | #define nOS_PeekCritical() \ 72 | do { \ 73 | uint32_t count = nOS_criticalNestingCounter; \ 74 | /* Leave critical section */ \ 75 | nOS_criticalNestingCounter = 0; \ 76 | ReleaseMutex(nOS_hCritical); \ 77 | \ 78 | /* Enter critical section */ \ 79 | while(WaitForSingleObject(nOS_hCritical, INFINITE) != WAIT_OBJECT_0); \ 80 | nOS_criticalNestingCounter = count; \ 81 | } while (0) 82 | 83 | extern HANDLE nOS_hCritical; 84 | extern uint32_t nOS_criticalNestingCounter; 85 | 86 | int nOS_Print (const char *format, ...); 87 | 88 | #ifdef NOS_PRIVATE 89 | void nOS_InitSpecific (void); 90 | void nOS_InitContext (nOS_Thread *thread, nOS_Stack *stack, size_t ssize, nOS_ThreadEntry entry, void *arg); 91 | void nOS_SwitchContext (void); 92 | #endif 93 | 94 | #ifdef __cplusplus 95 | } 96 | #endif 97 | 98 | #endif /* NOSPORT_H */ 99 | -------------------------------------------------------------------------------- /src/nOSBarrier.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2019 Jim Tremblay 3 | * 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | */ 8 | 9 | #define NOS_PRIVATE 10 | #include "nOS.h" 11 | 12 | #ifdef __cplusplus 13 | extern "C" { 14 | #endif 15 | 16 | #if (NOS_CONFIG_BARRIER_ENABLE > 0) 17 | nOS_Error nOS_BarrierCreate (nOS_Barrier *barrier, uint8_t max) 18 | { 19 | nOS_Error err; 20 | nOS_StatusReg sr; 21 | 22 | #if (NOS_CONFIG_SAFE > 0) 23 | if (barrier == NULL) { 24 | err = NOS_E_INV_OBJ; 25 | } 26 | else if (max == 0) { 27 | err = NOS_E_INV_VAL; 28 | } else 29 | #endif 30 | { 31 | nOS_EnterCritical(sr); 32 | #if (NOS_CONFIG_SAFE > 0) 33 | if (barrier->e.type != NOS_EVENT_INVALID) { 34 | err = NOS_E_INV_OBJ; 35 | } else 36 | #endif 37 | { 38 | nOS_CreateEvent((nOS_Event*)barrier 39 | #if (NOS_CONFIG_SAFE > 0) 40 | ,NOS_EVENT_BARRIER 41 | #endif 42 | ); 43 | barrier->count = max; 44 | barrier->max = max; 45 | 46 | err = NOS_OK; 47 | } 48 | nOS_LeaveCritical(sr); 49 | } 50 | 51 | return err; 52 | } 53 | 54 | #if (NOS_CONFIG_BARRIER_DELETE_ENABLE > 0) 55 | nOS_Error nOS_BarrierDelete (nOS_Barrier *barrier) 56 | { 57 | nOS_Error err; 58 | nOS_StatusReg sr; 59 | 60 | #if (NOS_CONFIG_SAFE > 0) 61 | if (barrier == NULL) { 62 | err = NOS_E_INV_OBJ; 63 | } else 64 | #endif 65 | { 66 | nOS_EnterCritical(sr); 67 | #if (NOS_CONFIG_SAFE > 0) 68 | if (barrier->e.type != NOS_EVENT_BARRIER) { 69 | err = NOS_E_INV_OBJ; 70 | } else 71 | #endif 72 | { 73 | barrier->count = 0; 74 | barrier->max = 0; 75 | nOS_DeleteEvent((nOS_Event*)barrier); 76 | 77 | err = NOS_OK; 78 | } 79 | nOS_LeaveCritical(sr); 80 | } 81 | 82 | return err; 83 | } 84 | #endif 85 | 86 | nOS_Error nOS_BarrierWait (nOS_Barrier *barrier) 87 | { 88 | nOS_Error err; 89 | nOS_StatusReg sr; 90 | 91 | #if (NOS_CONFIG_SAFE > 0) 92 | if (barrier == NULL) { 93 | err = NOS_E_INV_OBJ; 94 | } 95 | else if (nOS_isrNestingCounter > 0) { 96 | err = NOS_E_ISR; 97 | } else 98 | #endif 99 | { 100 | nOS_EnterCritical(sr); 101 | #if (NOS_CONFIG_SAFE > 0) 102 | if (barrier->e.type != NOS_EVENT_BARRIER) { 103 | /* Not a barrier event object */ 104 | err = NOS_E_INV_OBJ; 105 | } else 106 | #endif 107 | if (barrier->count == 1) { 108 | barrier->count = barrier->max; 109 | /* Wake up all threads waiting on barrier */ 110 | nOS_BroadcastEvent((nOS_Event*)barrier, NOS_OK); 111 | 112 | err = NOS_OK; 113 | } else 114 | #if (NOS_CONFIG_SAFE > 0) 115 | #if (NOS_CONFIG_SCHED_LOCK_ENABLE > 0) 116 | if (nOS_lockNestingCounter > 0) { 117 | /* Can't wait when scheduler is locked */ 118 | err = NOS_E_LOCKED; 119 | } else 120 | #endif 121 | #endif 122 | { 123 | barrier->count--; 124 | /* Calling thread must wait for other threads. */ 125 | err = nOS_WaitForEvent((nOS_Event*)barrier, 126 | NOS_THREAD_ON_BARRIER 127 | #if (NOS_CONFIG_WAITING_TIMEOUT_ENABLE > 0) || (NOS_CONFIG_SLEEP_ENABLE > 0) || (NOS_CONFIG_SLEEP_UNTIL_ENABLE > 0) 128 | ,NOS_WAIT_INFINITE 129 | #endif 130 | ); 131 | } 132 | nOS_LeaveCritical(sr); 133 | } 134 | 135 | return err; 136 | } 137 | 138 | #endif /* NOS_CONFIG_BARRIER_ENABLE */ 139 | 140 | #ifdef __cplusplus 141 | } 142 | #endif 143 | -------------------------------------------------------------------------------- /src/nOSEvent.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2019 Jim Tremblay 3 | * 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | */ 8 | 9 | #define NOS_PRIVATE 10 | #include "nOS.h" 11 | 12 | #ifdef __cplusplus 13 | extern "C" { 14 | #endif 15 | 16 | void nOS_CreateEvent (nOS_Event *event 17 | #if (NOS_CONFIG_SAFE > 0) 18 | 19 | ,nOS_EventType type 20 | #endif 21 | ) 22 | { 23 | #if (NOS_CONFIG_SAFE > 0) 24 | event->type = type; 25 | #endif 26 | nOS_InitList(&event->waitList); 27 | } 28 | 29 | void nOS_DeleteEvent (nOS_Event *event) 30 | { 31 | #if (NOS_CONFIG_SAFE > 0) 32 | event->type = NOS_EVENT_INVALID; 33 | #endif 34 | nOS_BroadcastEvent(event, NOS_E_DELETED); 35 | } 36 | 37 | void nOS_BroadcastEvent (nOS_Event *event, nOS_Error err) 38 | { 39 | while (nOS_SendEvent(event, err) != NULL); 40 | #if (NOS_CONFIG_SCHED_PREEMPTIVE_ENABLE > 0) 41 | /* Verify if a highest prio thread is ready to run */ 42 | nOS_Schedule(); 43 | #endif 44 | } 45 | 46 | nOS_Error nOS_WaitForEvent (nOS_Event *event, 47 | nOS_ThreadState state 48 | #if (NOS_CONFIG_WAITING_TIMEOUT_ENABLE > 0) || (NOS_CONFIG_SLEEP_ENABLE > 0) || (NOS_CONFIG_SLEEP_UNTIL_ENABLE > 0) 49 | ,nOS_TickCounter timeout 50 | #endif 51 | ) 52 | { 53 | nOS_Error err; 54 | 55 | if (nOS_isrNestingCounter > 0) { 56 | /* Can't wait from ISR */ 57 | err = NOS_E_ISR; 58 | } else 59 | #if (NOS_CONFIG_SCHED_LOCK_ENABLE > 0) 60 | if (nOS_lockNestingCounter > 0) { 61 | /* Can't switch context when scheduler is locked */ 62 | err = NOS_E_LOCKED; 63 | } else 64 | #endif 65 | { 66 | nOS_RemoveThreadFromReadyList((nOS_Thread*)nOS_runningThread); 67 | 68 | nOS_runningThread->state = (nOS_ThreadState)(nOS_runningThread->state | (state & NOS_THREAD_WAITING_MASK)); 69 | nOS_runningThread->event = event; 70 | if (event != NULL) { 71 | nOS_AppendToList(&event->waitList, (nOS_Node*)&nOS_runningThread->readyWait); 72 | } 73 | 74 | #if (NOS_CONFIG_WAITING_TIMEOUT_ENABLE > 0) || (NOS_CONFIG_SLEEP_ENABLE > 0) || (NOS_CONFIG_SLEEP_UNTIL_ENABLE > 0) 75 | if ((timeout > 0) && (timeout < NOS_WAIT_INFINITE)) { 76 | nOS_runningThread->timeout = nOS_tickCounter + timeout; 77 | nOS_runningThread->state = (nOS_ThreadState)(nOS_runningThread->state | NOS_THREAD_WAIT_TIMEOUT); 78 | nOS_AppendToList((nOS_List*)&nOS_timeoutThreadsList, (nOS_Node*)&nOS_runningThread->tout); 79 | } 80 | #endif 81 | 82 | nOS_Schedule(); 83 | 84 | err = (nOS_Error)nOS_runningThread->error; 85 | } 86 | 87 | return err; 88 | } 89 | 90 | nOS_Error nOS_WaitOnHold ( 91 | #if (NOS_CONFIG_WAITING_TIMEOUT_ENABLE > 0) || (NOS_CONFIG_SLEEP_ENABLE > 0) || (NOS_CONFIG_SLEEP_UNTIL_ENABLE > 0) 92 | nOS_TickCounter timeout 93 | #endif 94 | ) 95 | { 96 | nOS_StatusReg sr; 97 | nOS_Error err; 98 | 99 | nOS_EnterCritical(sr); 100 | err = nOS_WaitForEvent(NULL, 101 | NOS_THREAD_ON_HOLD 102 | #if (NOS_CONFIG_WAITING_TIMEOUT_ENABLE > 0) || (NOS_CONFIG_SLEEP_ENABLE > 0) || (NOS_CONFIG_SLEEP_UNTIL_ENABLE > 0) 103 | ,timeout 104 | #endif 105 | ); 106 | nOS_LeaveCritical(sr); 107 | 108 | return err; 109 | } 110 | 111 | nOS_Thread* nOS_SendEvent (nOS_Event *event, nOS_Error err) 112 | { 113 | nOS_Thread *thread; 114 | 115 | thread = (nOS_Thread*)nOS_GetHeadOfList(&event->waitList); 116 | if (thread != NULL) { 117 | nOS_WakeUpThread(thread, err); 118 | } 119 | 120 | return thread; 121 | } 122 | 123 | #ifdef __cplusplus 124 | } 125 | #endif 126 | -------------------------------------------------------------------------------- /src/nOSList.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2019 Jim Tremblay 3 | * 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | */ 8 | 9 | #define NOS_PRIVATE 10 | #include "nOS.h" 11 | 12 | #ifdef __cplusplus 13 | extern "C" { 14 | #endif 15 | 16 | void nOS_AppendToList (nOS_List *list, nOS_Node *node) 17 | { 18 | node->prev = list->tail; 19 | node->next = NULL; 20 | if (node->prev != NULL) { 21 | node->prev->next = node; 22 | } 23 | list->tail = node; 24 | if (list->head == NULL) { 25 | list->head = node; 26 | } 27 | } 28 | 29 | void nOS_RemoveFromList (nOS_List *list, nOS_Node *node) 30 | { 31 | if (list->head == node) { 32 | list->head = node->next; 33 | } 34 | if (list->tail == node) { 35 | list->tail = node->prev; 36 | } 37 | if (node->prev != NULL) { 38 | node->prev->next = node->next; 39 | } 40 | if (node->next != NULL) { 41 | node->next->prev = node->prev; 42 | } 43 | node->prev = NULL; 44 | node->next = NULL; 45 | } 46 | 47 | void nOS_RotateList (nOS_List *list) 48 | { 49 | if (list->head != NULL) { 50 | if (list->head->next != NULL) { 51 | list->head->prev = list->tail; 52 | list->tail->next = list->head; 53 | list->head = list->head->next; 54 | list->tail = list->tail->next; 55 | list->head->prev = NULL; 56 | list->tail->next = NULL; 57 | } 58 | } 59 | } 60 | 61 | void nOS_WalkInList (nOS_List *list, nOS_NodeHandler handler, void *arg) 62 | { 63 | nOS_Node *it = list->head; 64 | nOS_Node *next; 65 | 66 | while (it != NULL) { 67 | next = it->next; 68 | handler(it->payload, arg); 69 | it = next; 70 | } 71 | } 72 | 73 | #ifdef __cplusplus 74 | } 75 | #endif 76 | -------------------------------------------------------------------------------- /src/nOSSem.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2019 Jim Tremblay 3 | * 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | */ 8 | 9 | #define NOS_PRIVATE 10 | #include "nOS.h" 11 | 12 | #ifdef __cplusplus 13 | extern "C" { 14 | #endif 15 | 16 | #if (NOS_CONFIG_SEM_ENABLE > 0) 17 | nOS_Error nOS_SemCreate (nOS_Sem *sem, nOS_SemCounter count, nOS_SemCounter max) 18 | { 19 | nOS_Error err; 20 | nOS_StatusReg sr; 21 | 22 | #if (NOS_CONFIG_SAFE > 0) 23 | if (sem == NULL) { 24 | err = NOS_E_INV_OBJ; 25 | } 26 | else if (count > max) { 27 | err = NOS_E_INV_VAL; 28 | } else 29 | #endif 30 | { 31 | nOS_EnterCritical(sr); 32 | #if (NOS_CONFIG_SAFE > 0) 33 | if (sem->e.type != NOS_EVENT_INVALID) { 34 | err = NOS_E_INV_OBJ; 35 | } else 36 | #endif 37 | { 38 | nOS_CreateEvent((nOS_Event*)sem 39 | #if (NOS_CONFIG_SAFE > 0) 40 | ,NOS_EVENT_SEM 41 | #endif 42 | ); 43 | sem->count = count; 44 | sem->max = max; 45 | 46 | err = NOS_OK; 47 | } 48 | nOS_LeaveCritical(sr); 49 | } 50 | 51 | return err; 52 | } 53 | 54 | #if (NOS_CONFIG_SEM_DELETE_ENABLE > 0) 55 | nOS_Error nOS_SemDelete (nOS_Sem *sem) 56 | { 57 | nOS_Error err; 58 | nOS_StatusReg sr; 59 | 60 | #if (NOS_CONFIG_SAFE > 0) 61 | if (sem == NULL) { 62 | err = NOS_E_INV_OBJ; 63 | } else 64 | #endif 65 | { 66 | nOS_EnterCritical(sr); 67 | #if (NOS_CONFIG_SAFE > 0) 68 | if (sem->e.type != NOS_EVENT_SEM) { 69 | err = NOS_E_INV_OBJ; 70 | } else 71 | #endif 72 | { 73 | sem->count = 0; 74 | sem->max = 0; 75 | nOS_DeleteEvent((nOS_Event*)sem); 76 | 77 | err = NOS_OK; 78 | } 79 | nOS_LeaveCritical(sr); 80 | } 81 | 82 | return err; 83 | } 84 | #endif 85 | 86 | nOS_Error nOS_SemTake (nOS_Sem *sem, nOS_TickCounter timeout) 87 | { 88 | nOS_Error err; 89 | nOS_StatusReg sr; 90 | 91 | #if (NOS_CONFIG_SAFE > 0) 92 | if (sem == NULL) { 93 | err = NOS_E_INV_OBJ; 94 | } else 95 | #endif 96 | { 97 | nOS_EnterCritical(sr); 98 | #if (NOS_CONFIG_SAFE > 0) 99 | if (sem->e.type != NOS_EVENT_SEM) { 100 | err = NOS_E_INV_OBJ; 101 | } else 102 | #endif 103 | if (sem->count > 0) { 104 | /* Sem available. */ 105 | sem->count--; 106 | err = NOS_OK; 107 | } 108 | else if (timeout == NOS_NO_WAIT) { 109 | /* Calling thread can't wait. */ 110 | err = NOS_E_AGAIN; 111 | } 112 | else { 113 | /* Calling thread must wait on sem. */ 114 | err = nOS_WaitForEvent((nOS_Event*)sem, 115 | NOS_THREAD_TAKING_SEM 116 | #if (NOS_CONFIG_WAITING_TIMEOUT_ENABLE > 0) 117 | ,timeout 118 | #elif (NOS_CONFIG_SLEEP_ENABLE > 0) || (NOS_CONFIG_SLEEP_UNTIL_ENABLE > 0) 119 | ,NOS_WAIT_INFINITE 120 | #endif 121 | ); 122 | } 123 | nOS_LeaveCritical(sr); 124 | } 125 | 126 | return err; 127 | } 128 | 129 | nOS_Error nOS_SemGive (nOS_Sem *sem) 130 | { 131 | nOS_Error err; 132 | nOS_StatusReg sr; 133 | nOS_Thread *thread; 134 | 135 | #if (NOS_CONFIG_SAFE > 0) 136 | if (sem == NULL) { 137 | err = NOS_E_INV_OBJ; 138 | } else 139 | #endif 140 | { 141 | nOS_EnterCritical(sr); 142 | #if (NOS_CONFIG_SAFE > 0) 143 | if (sem->e.type != NOS_EVENT_SEM) { 144 | err = NOS_E_INV_OBJ; 145 | } else 146 | #endif 147 | { 148 | thread = nOS_SendEvent((nOS_Event*)sem, NOS_OK); 149 | if (thread != NULL) { 150 | #if (NOS_CONFIG_SCHED_PREEMPTIVE_ENABLE > 0) 151 | /* Verify if a highest prio thread is ready to run */ 152 | nOS_Schedule(); 153 | #endif 154 | err = NOS_OK; 155 | } 156 | /* No thread waiting for semaphore, can we increase count? */ 157 | else if (sem->count < sem->max) { 158 | sem->count++; 159 | err = NOS_OK; 160 | } 161 | else if (sem->max > 0) { 162 | err = NOS_E_OVERFLOW; 163 | } 164 | else { 165 | /* No thread waiting to consume sem, inform producer */ 166 | err = NOS_E_NO_CONSUMER; 167 | } 168 | } 169 | nOS_LeaveCritical(sr); 170 | } 171 | 172 | return err; 173 | } 174 | 175 | bool nOS_SemIsAvailable (nOS_Sem *sem) 176 | { 177 | nOS_StatusReg sr; 178 | bool avail; 179 | 180 | #if (NOS_CONFIG_SAFE > 0) 181 | if (sem == NULL) { 182 | avail = false; 183 | } else 184 | #endif 185 | { 186 | nOS_EnterCritical(sr); 187 | #if (NOS_CONFIG_SAFE > 0) 188 | if (sem->e.type != NOS_EVENT_SEM) { 189 | avail = false; 190 | } else 191 | #endif 192 | { 193 | avail = (sem->count > 0); 194 | } 195 | nOS_LeaveCritical(sr); 196 | } 197 | 198 | return avail; 199 | } 200 | #endif /* NOS_CONFIG_SEM_ENABLE */ 201 | 202 | #ifdef __cplusplus 203 | } 204 | #endif 205 | -------------------------------------------------------------------------------- /src/port/GCC/ARM7_TDMI/nOSPort.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018-2019 Alain Royer, Jim Tremblay 3 | * 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | */ 8 | #define NOS_PRIVATE 9 | #include "nOS.h" 10 | 11 | #ifdef __cplusplus 12 | extern "C" { 13 | #endif 14 | 15 | void nOS_InitContext (nOS_Thread *thread, nOS_Stack *stack, size_t ssize, nOS_ThreadEntry entry, void *arg) 16 | { 17 | nOS_Stack *tos = (nOS_Stack*)((uint32_t)(stack + ssize) & 0xFFFFFFF8UL); 18 | #if (NOS_CONFIG_DEBUG > 0) 19 | size_t i; 20 | 21 | for (i = 0; i < ssize; i++) { 22 | stack[i] = 0xFFFFFFFFUL; 23 | } 24 | #endif 25 | 26 | *(--tos) = (nOS_Stack)entry + 4; /* PC */ 27 | #if (NOS_CONFIG_DEBUG > 0) 28 | *(--tos) = 0x00000000; /* LR */ 29 | #else 30 | tos -= 1; 31 | #endif 32 | *(--tos) = (nOS_Stack)(stack + ssize) & 0xFFFFFFF8UL; /* SP */ 33 | #if (NOS_CONFIG_DEBUG > 0) 34 | *(--tos) = 0x12121212UL; /* R12 */ 35 | *(--tos) = 0x11111111UL; /* R11 */ 36 | *(--tos) = 0x10101010UL; /* R10 */ 37 | *(--tos) = 0x09090909UL; /* R9 */ 38 | *(--tos) = 0x08080808UL; /* R8 */ 39 | *(--tos) = 0x07070707UL; /* R7 */ 40 | *(--tos) = 0x06060606UL; /* R6 */ 41 | *(--tos) = 0x05050505UL; /* R5 */ 42 | *(--tos) = 0x04040404UL; /* R4 */ 43 | *(--tos) = 0x03030303UL; /* R3 */ 44 | *(--tos) = 0x02020202UL; /* R2 */ 45 | *(--tos) = 0x01010101UL; /* R1 */ 46 | #else 47 | tos -= 12; /* R12 - R1 */ 48 | #endif 49 | *(--tos) = (nOS_Stack)arg; /* R0 */ 50 | *(--tos) = 0x0000001FUL; /* SPSR */ 51 | 52 | thread->stackPtr = tos; 53 | } 54 | 55 | void nOS_EnterISR (void) 56 | { 57 | nOS_StatusReg sr; 58 | 59 | #if (NOS_CONFIG_SAFE > 0) 60 | if (nOS_running) 61 | #endif 62 | { 63 | nOS_EnterCritical(sr); 64 | nOS_isrNestingCounter++; 65 | nOS_LeaveCritical(sr); 66 | } 67 | } 68 | 69 | void nOS_LeaveISR (void) 70 | { 71 | nOS_StatusReg sr; 72 | nOS_Thread *highPrioThread; 73 | 74 | #if (NOS_CONFIG_SAFE > 0) 75 | if (nOS_running) 76 | #endif 77 | { 78 | nOS_EnterCritical(sr); 79 | nOS_isrNestingCounter--; 80 | if (nOS_isrNestingCounter == 0) { 81 | #if (NOS_CONFIG_SCHED_LOCK_ENABLE > 0) 82 | if (nOS_lockNestingCounter == 0) 83 | #endif 84 | { 85 | highPrioThread = nOS_FindHighPrioThread(); 86 | if (highPrioThread != NULL) { 87 | #if (NOS_CONFIG_SCHED_PREEMPTIVE_ENABLE > 0) || (NOS_CONFIG_SCHED_ROUND_ROBIN_ENABLE > 0) 88 | nOS_highPrioThread = highPrioThread; 89 | nOS_runningThread = nOS_highPrioThread; 90 | #endif 91 | } else { 92 | nOS_highPrioThread = &nOS_mainHandle; 93 | nOS_runningThread = nOS_highPrioThread; 94 | } 95 | } 96 | } 97 | nOS_LeaveCritical(sr); 98 | } 99 | } 100 | 101 | void SWI_Handler (void) 102 | { 103 | /* Within an IRQ ISR the link register has an offset from the true return 104 | address, but an SWI ISR does not. Add the offset manually so the same 105 | ISR return code can be used in both cases. */ 106 | __asm volatile ( "ADD LR, LR, #4" ); 107 | 108 | /* Perform the context switch. First save the context of the current task. */ 109 | PUSH_CONTEXT(); 110 | 111 | nOS_runningThread = nOS_highPrioThread; 112 | 113 | /* Restore the context of the new task. */ 114 | POP_CONTEXT(); 115 | } 116 | 117 | #ifdef __cplusplus 118 | } 119 | #endif 120 | -------------------------------------------------------------------------------- /src/port/GCC/ARM_Cortex_M3/nOSPort.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2019 Jim Tremblay 3 | * 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | */ 8 | 9 | #define NOS_PRIVATE 10 | #include "nOS.h" 11 | 12 | #ifdef __cplusplus 13 | extern "C" { 14 | #endif 15 | 16 | void PendSV_Handler (void) __attribute__( ( naked ) ); 17 | 18 | #ifdef NOS_CONFIG_ISR_STACK_SECTION 19 | static nOS_Stack _isrStack[NOS_CONFIG_ISR_STACK_SIZE] __attribute__ ( ( section(NOS_CONFIG_ISR_STACK_SECTION) ) ); 20 | #else 21 | static nOS_Stack _isrStack[NOS_CONFIG_ISR_STACK_SIZE]; 22 | #endif 23 | 24 | void nOS_InitSpecific (void) 25 | { 26 | #if (NOS_CONFIG_DEBUG > 0) 27 | size_t i; 28 | 29 | for (i = 0; i < NOS_CONFIG_ISR_STACK_SIZE; i++) { 30 | _isrStack[i] = 0xFFFFFFFFUL; 31 | } 32 | #endif 33 | 34 | /* Copy MSP to PSP */ 35 | _SetPSP(_GetMSP()); 36 | /* Set MSP to local ISR stack */ 37 | _SetMSP((uint32_t)&_isrStack[NOS_CONFIG_ISR_STACK_SIZE] & 0xFFFFFFF8UL); 38 | /* Set current stack to PSP and privileged mode */ 39 | _SetCONTROL(_GetCONTROL() | 0x00000002UL); 40 | /* Set PendSV exception to lowest priority */ 41 | *(volatile uint32_t *)0xE000ED20UL |= 0x00FF0000UL; 42 | } 43 | 44 | void nOS_InitContext (nOS_Thread *thread, nOS_Stack *stack, size_t ssize, nOS_ThreadEntry entry, void *arg) 45 | { 46 | nOS_Stack *tos = (nOS_Stack*)((uint32_t)(stack + ssize) & 0xFFFFFFF8UL); 47 | #if (NOS_CONFIG_DEBUG > 0) 48 | size_t i; 49 | 50 | for (i = 0; i < ssize; i++) { 51 | stack[i] = 0xFFFFFFFFUL; 52 | } 53 | #endif 54 | 55 | *(--tos) = 0x01000000UL; /* xPSR */ 56 | *(--tos) = (nOS_Stack)entry;/* PC */ 57 | *(--tos) = 0x00000000UL; /* LR */ 58 | #if (NOS_CONFIG_DEBUG > 0) 59 | *(--tos) = 0x12121212UL; /* R12 */ 60 | *(--tos) = 0x03030303UL; /* R3 */ 61 | *(--tos) = 0x02020202UL; /* R2 */ 62 | *(--tos) = 0x01010101UL; /* R1 */ 63 | #else 64 | tos -= 4; /* R12, R3, R2 and R1 */ 65 | #endif 66 | *(--tos) = (nOS_Stack)arg; /* R0 */ 67 | #if (NOS_CONFIG_DEBUG > 0) 68 | *(--tos) = 0x11111111UL; /* R11 */ 69 | *(--tos) = 0x10101010UL; /* R10 */ 70 | *(--tos) = 0x09090909UL; /* R9 */ 71 | *(--tos) = 0x08080808UL; /* R8 */ 72 | *(--tos) = 0x07070707UL; /* R7 */ 73 | *(--tos) = 0x06060606UL; /* R6 */ 74 | *(--tos) = 0x05050505UL; /* R5 */ 75 | *(--tos) = 0x04040404UL; /* R4 */ 76 | #else 77 | tos -= 8; /* R11, R10, R9, R8, R7, R6, R5 and R4 */ 78 | #endif 79 | 80 | thread->stackPtr = tos; 81 | } 82 | 83 | void nOS_SwitchContext (void) 84 | { 85 | /* Request context switch */ 86 | *(volatile uint32_t *)0xE000ED04UL = 0x10000000UL; 87 | nOS_PeekCritical(); 88 | } 89 | 90 | void nOS_EnterISR (void) 91 | { 92 | nOS_StatusReg sr; 93 | 94 | #if (NOS_CONFIG_SAFE > 0) 95 | if (nOS_running) 96 | #endif 97 | { 98 | nOS_EnterCritical(sr); 99 | nOS_isrNestingCounter++; 100 | nOS_LeaveCritical(sr); 101 | } 102 | } 103 | 104 | void nOS_LeaveISR (void) 105 | { 106 | nOS_StatusReg sr; 107 | nOS_Thread *highPrioThread; 108 | 109 | #if (NOS_CONFIG_SAFE > 0) 110 | if (nOS_running) 111 | #endif 112 | { 113 | nOS_EnterCritical(sr); 114 | nOS_isrNestingCounter--; 115 | if (nOS_isrNestingCounter == 0) { 116 | #if (NOS_CONFIG_SCHED_LOCK_ENABLE > 0) 117 | if (nOS_lockNestingCounter == 0) 118 | #endif 119 | { 120 | highPrioThread = nOS_FindHighPrioThread(); 121 | if (highPrioThread != NULL) { 122 | #if (NOS_CONFIG_SCHED_PREEMPTIVE_ENABLE > 0) || (NOS_CONFIG_SCHED_ROUND_ROBIN_ENABLE > 0) 123 | nOS_highPrioThread = highPrioThread; 124 | if (nOS_runningThread != nOS_highPrioThread) { 125 | *(volatile uint32_t *)0xE000ED04UL = 0x10000000UL; 126 | } 127 | #endif 128 | } else if (nOS_runningThread != &nOS_mainHandle) { 129 | nOS_highPrioThread = &nOS_mainHandle; 130 | *(volatile uint32_t *)0xE000ED04UL = 0x10000000UL; 131 | } 132 | } 133 | } 134 | nOS_LeaveCritical(sr); 135 | } 136 | } 137 | 138 | void PendSV_Handler (void) 139 | { 140 | __asm volatile ( 141 | /* Disable interrupts */ 142 | "CPSID I \n" 143 | "ISB \n" 144 | 145 | /* Save PSP before doing anything, PendSV_Handler already running on MSP */ 146 | "MRS R0, PSP \n" 147 | 148 | /* Get the location of nOS_runningThread */ 149 | "LDR R3, runningThread \n" 150 | "LDR R2, [R3] \n" 151 | 152 | /* Push remaining registers on thread stack */ 153 | "STMDB R0!, {R4-R11} \n" 154 | 155 | /* Save PSP to nOS_Thread object of current running thread */ 156 | "STR R0, [R2] \n" 157 | 158 | /* Get the location of nOS_highPrioThread */ 159 | "LDR R1, highPrioThread \n" 160 | "LDR R2, [R1] \n" 161 | 162 | /* Copy nOS_highPrioThread to nOS_runningThread */ 163 | "STR R2, [R3] \n" 164 | 165 | /* Restore PSP from nOS_Thread object of high prio thread */ 166 | "LDR R0, [R2] \n" 167 | 168 | /* Pop registers from thread stack */ 169 | "LDMIA R0!, {R4-R11} \n" 170 | 171 | /* Restore PSP to high prio thread stack */ 172 | "MSR PSP, R0 \n" 173 | 174 | /* Enable interrupts */ 175 | "CPSIE I \n" 176 | "ISB \n" 177 | 178 | /* Return */ 179 | "BX LR \n" 180 | 181 | ".align 2 \n" 182 | "runningThread: .word nOS_runningThread \n" 183 | "highPrioThread: .word nOS_highPrioThread \n" 184 | ); 185 | } 186 | 187 | #ifdef __cplusplus 188 | } 189 | #endif 190 | -------------------------------------------------------------------------------- /src/port/GCC/ARM_Cortex_M4/nOSPort.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2019 Jim Tremblay 3 | * 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | */ 8 | 9 | #define NOS_PRIVATE 10 | #include "nOS.h" 11 | 12 | #ifdef __cplusplus 13 | extern "C" { 14 | #endif 15 | 16 | void PendSV_Handler (void) __attribute__( ( naked ) ); 17 | 18 | #ifdef NOS_CONFIG_ISR_STACK_SECTION 19 | static nOS_Stack _isrStack[NOS_CONFIG_ISR_STACK_SIZE] __attribute__ ( ( section(NOS_CONFIG_ISR_STACK_SECTION) ) ); 20 | #else 21 | static nOS_Stack _isrStack[NOS_CONFIG_ISR_STACK_SIZE]; 22 | #endif 23 | 24 | void nOS_InitSpecific (void) 25 | { 26 | #if (NOS_CONFIG_DEBUG > 0) 27 | size_t i; 28 | 29 | for (i = 0; i < NOS_CONFIG_ISR_STACK_SIZE; i++) { 30 | _isrStack[i] = 0xFFFFFFFFUL; 31 | } 32 | #endif 33 | 34 | /* Copy MSP to PSP */ 35 | _SetPSP(_GetMSP()); 36 | /* Set MSP to local ISR stack */ 37 | _SetMSP((uint32_t)&_isrStack[NOS_CONFIG_ISR_STACK_SIZE] & 0xFFFFFFF8UL); 38 | /* Set current stack to PSP and privileged mode */ 39 | _SetCONTROL(_GetCONTROL() | 0x00000002UL); 40 | /* Set PendSV exception to lowest priority */ 41 | *(volatile uint32_t *)0xE000ED20UL |= 0x00FF0000UL; 42 | } 43 | 44 | void nOS_InitContext (nOS_Thread *thread, nOS_Stack *stack, size_t ssize, nOS_ThreadEntry entry, void *arg) 45 | { 46 | nOS_Stack *tos = (nOS_Stack*)((uint32_t)(stack + ssize) & 0xFFFFFFF8UL); 47 | #if (NOS_CONFIG_DEBUG > 0) 48 | size_t i; 49 | 50 | for (i = 0; i < ssize; i++) { 51 | stack[i] = 0xFFFFFFFFUL; 52 | } 53 | #endif 54 | 55 | *(--tos) = 0x01000000UL; /* xPSR */ 56 | *(--tos) = (nOS_Stack)entry;/* PC */ 57 | *(--tos) = 0x00000000UL; /* LR */ 58 | #if (NOS_CONFIG_DEBUG > 0) 59 | *(--tos) = 0x12121212UL; /* R12 */ 60 | *(--tos) = 0x03030303UL; /* R3 */ 61 | *(--tos) = 0x02020202UL; /* R2 */ 62 | *(--tos) = 0x01010101UL; /* R1 */ 63 | #else 64 | tos -= 4; /* R12, R3, R2 and R1 */ 65 | #endif 66 | *(--tos) = (nOS_Stack)arg; /* R0 */ 67 | *(--tos) = 0xFFFFFFFDUL; /* EXC_RETURN (Thread mode, Thread use PSP) */ 68 | #if (NOS_CONFIG_DEBUG > 0) 69 | *(--tos) = 0x11111111UL; /* R11 */ 70 | *(--tos) = 0x10101010UL; /* R10 */ 71 | *(--tos) = 0x09090909UL; /* R9 */ 72 | *(--tos) = 0x08080808UL; /* R8 */ 73 | *(--tos) = 0x07070707UL; /* R7 */ 74 | *(--tos) = 0x06060606UL; /* R6 */ 75 | *(--tos) = 0x05050505UL; /* R5 */ 76 | *(--tos) = 0x04040404UL; /* R4 */ 77 | #else 78 | tos -= 8; /* R11, R10, R9, R8, R7, R6, R5 and R4 */ 79 | #endif 80 | 81 | thread->stackPtr = tos; 82 | } 83 | 84 | void nOS_SwitchContext (void) 85 | { 86 | /* Request context switch */ 87 | *(volatile uint32_t *)0xE000ED04UL = 0x10000000UL; 88 | nOS_PeekCritical(); 89 | } 90 | 91 | void nOS_EnterISR (void) 92 | { 93 | nOS_StatusReg sr; 94 | 95 | #if (NOS_CONFIG_SAFE > 0) 96 | if (nOS_running) 97 | #endif 98 | { 99 | nOS_EnterCritical(sr); 100 | nOS_isrNestingCounter++; 101 | nOS_LeaveCritical(sr); 102 | } 103 | } 104 | 105 | void nOS_LeaveISR (void) 106 | { 107 | nOS_StatusReg sr; 108 | nOS_Thread *highPrioThread; 109 | 110 | #if (NOS_CONFIG_SAFE > 0) 111 | if (nOS_running) 112 | #endif 113 | { 114 | nOS_EnterCritical(sr); 115 | nOS_isrNestingCounter--; 116 | if (nOS_isrNestingCounter == 0) { 117 | #if (NOS_CONFIG_SCHED_LOCK_ENABLE > 0) 118 | if (nOS_lockNestingCounter == 0) 119 | #endif 120 | { 121 | highPrioThread = nOS_FindHighPrioThread(); 122 | if (highPrioThread != NULL) { 123 | #if (NOS_CONFIG_SCHED_PREEMPTIVE_ENABLE > 0) || (NOS_CONFIG_SCHED_ROUND_ROBIN_ENABLE > 0) 124 | nOS_highPrioThread = highPrioThread; 125 | if (nOS_runningThread != nOS_highPrioThread) { 126 | *(volatile uint32_t *)0xE000ED04UL = 0x10000000UL; 127 | } 128 | #endif 129 | } else if (nOS_runningThread != &nOS_mainHandle) { 130 | nOS_highPrioThread = &nOS_mainHandle; 131 | *(volatile uint32_t *)0xE000ED04UL = 0x10000000UL; 132 | } 133 | } 134 | } 135 | nOS_LeaveCritical(sr); 136 | } 137 | } 138 | 139 | void PendSV_Handler (void) 140 | { 141 | __asm volatile ( 142 | /* Disable interrupts */ 143 | "CPSID I \n" 144 | "ISB \n" 145 | 146 | /* Save PSP before doing anything, PendSV_Handler already running on MSP */ 147 | "MRS R0, PSP \n" 148 | 149 | /* Get the location of nOS_runningThread */ 150 | "LDR R3, runningThread \n" 151 | "LDR R2, [R3] \n" 152 | 153 | #if defined(__VFP_FP__) && !defined(__SOFTFP__) 154 | /* Is thread using FPU? Yes, push high VFP registers to stack */ 155 | "TST LR, #0x10 \n" 156 | "IT EQ \n" 157 | "VSTMDBEQ R0!, {S16-S31} \n" 158 | #endif 159 | 160 | /* Push remaining registers on thread stack */ 161 | "STMDB R0!, {R4-R11, LR} \n" 162 | 163 | /* Save PSP to nOS_Thread object of current running thread */ 164 | "STR R0, [R2] \n" 165 | 166 | /* Get the location of nOS_highPrioThread */ 167 | "LDR R1, highPrioThread \n" 168 | "LDR R2, [R1] \n" 169 | 170 | /* Copy nOS_highPrioThread to nOS_runningThread */ 171 | "STR R2, [R3] \n" 172 | 173 | /* Restore PSP from nOS_Thread object of high prio thread */ 174 | "LDR R0, [R2] \n" 175 | 176 | /* Pop registers from thread stack */ 177 | "LDMIA R0!, {R4-R11, LR} \n" 178 | 179 | #if defined(__VFP_FP__) && !defined(__SOFTFP__) 180 | /* Is thread using FPU? Yes, pop high VFP registers from stack */ 181 | "TST LR, #0x10 \n" 182 | "IT EQ \n" 183 | "VLDMIAEQ R0!, {S16-S31} \n" 184 | #endif 185 | 186 | /* Restore PSP to high prio thread stack */ 187 | "MSR PSP, R0 \n" 188 | 189 | /* Enable interrupts */ 190 | "CPSIE I \n" 191 | "ISB \n" 192 | 193 | /* Return */ 194 | "BX LR \n" 195 | 196 | ".align 2 \n" 197 | "runningThread: .word nOS_runningThread \n" 198 | "highPrioThread: .word nOS_highPrioThread \n" 199 | ); 200 | } 201 | 202 | #ifdef __cplusplus 203 | } 204 | #endif 205 | -------------------------------------------------------------------------------- /src/port/GCC/ARM_Cortex_M7/nOSPort.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2019 Jim Tremblay 3 | * 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | */ 8 | 9 | #define NOS_PRIVATE 10 | #include "nOS.h" 11 | 12 | #ifdef __cplusplus 13 | extern "C" { 14 | #endif 15 | 16 | void PendSV_Handler (void) __attribute__( ( naked ) ); 17 | 18 | #ifdef NOS_CONFIG_ISR_STACK_SECTION 19 | static nOS_Stack _isrStack[NOS_CONFIG_ISR_STACK_SIZE] __attribute__ ( ( section(NOS_CONFIG_ISR_STACK_SECTION) ) ); 20 | #else 21 | static nOS_Stack _isrStack[NOS_CONFIG_ISR_STACK_SIZE]; 22 | #endif 23 | 24 | void nOS_InitSpecific (void) 25 | { 26 | #if (NOS_CONFIG_DEBUG > 0) 27 | size_t i; 28 | 29 | for (i = 0; i < NOS_CONFIG_ISR_STACK_SIZE; i++) { 30 | _isrStack[i] = 0xFFFFFFFFUL; 31 | } 32 | #endif 33 | 34 | /* Copy MSP to PSP */ 35 | _SetPSP(_GetMSP()); 36 | /* Set MSP to local ISR stack */ 37 | _SetMSP((uint32_t)&_isrStack[NOS_CONFIG_ISR_STACK_SIZE] & 0xFFFFFFF8UL); 38 | /* Set current stack to PSP and privileged mode */ 39 | _SetCONTROL(_GetCONTROL() | 0x00000002UL); 40 | /* Set PendSV exception to lowest priority */ 41 | *(volatile uint32_t *)0xE000ED20UL |= 0x00FF0000UL; 42 | } 43 | 44 | void nOS_InitContext (nOS_Thread *thread, nOS_Stack *stack, size_t ssize, nOS_ThreadEntry entry, void *arg) 45 | { 46 | nOS_Stack *tos = (nOS_Stack*)((uint32_t)(stack + ssize) & 0xFFFFFFF8UL); 47 | #if (NOS_CONFIG_DEBUG > 0) 48 | size_t i; 49 | 50 | for (i = 0; i < ssize; i++) { 51 | stack[i] = 0xFFFFFFFFUL; 52 | } 53 | #endif 54 | 55 | *(--tos) = 0x01000000UL; /* xPSR */ 56 | *(--tos) = (nOS_Stack)entry;/* PC */ 57 | *(--tos) = 0x00000000UL; /* LR */ 58 | #if (NOS_CONFIG_DEBUG > 0) 59 | *(--tos) = 0x12121212UL; /* R12 */ 60 | *(--tos) = 0x03030303UL; /* R3 */ 61 | *(--tos) = 0x02020202UL; /* R2 */ 62 | *(--tos) = 0x01010101UL; /* R1 */ 63 | #else 64 | tos -= 4; /* R12, R3, R2 and R1 */ 65 | #endif 66 | *(--tos) = (nOS_Stack)arg; /* R0 */ 67 | *(--tos) = 0xFFFFFFFDUL; /* EXC_RETURN (Thread mode, Thread use PSP) */ 68 | #if (NOS_CONFIG_DEBUG > 0) 69 | *(--tos) = 0x11111111UL; /* R11 */ 70 | *(--tos) = 0x10101010UL; /* R10 */ 71 | *(--tos) = 0x09090909UL; /* R9 */ 72 | *(--tos) = 0x08080808UL; /* R8 */ 73 | *(--tos) = 0x07070707UL; /* R7 */ 74 | *(--tos) = 0x06060606UL; /* R6 */ 75 | *(--tos) = 0x05050505UL; /* R5 */ 76 | *(--tos) = 0x04040404UL; /* R4 */ 77 | #else 78 | tos -= 8; /* R11, R10, R9, R8, R7, R6, R5 and R4 */ 79 | #endif 80 | 81 | thread->stackPtr = tos; 82 | } 83 | 84 | void nOS_SwitchContext (void) 85 | { 86 | /* Request context switch */ 87 | *(volatile uint32_t *)0xE000ED04UL = 0x10000000UL; 88 | nOS_PeekCritical(); 89 | } 90 | 91 | void nOS_EnterISR (void) 92 | { 93 | nOS_StatusReg sr; 94 | 95 | #if (NOS_CONFIG_SAFE > 0) 96 | if (nOS_running) 97 | #endif 98 | { 99 | nOS_EnterCritical(sr); 100 | nOS_isrNestingCounter++; 101 | nOS_LeaveCritical(sr); 102 | } 103 | } 104 | 105 | void nOS_LeaveISR (void) 106 | { 107 | nOS_StatusReg sr; 108 | nOS_Thread *highPrioThread; 109 | 110 | #if (NOS_CONFIG_SAFE > 0) 111 | if (nOS_running) 112 | #endif 113 | { 114 | nOS_EnterCritical(sr); 115 | nOS_isrNestingCounter--; 116 | if (nOS_isrNestingCounter == 0) { 117 | #if (NOS_CONFIG_SCHED_LOCK_ENABLE > 0) 118 | if (nOS_lockNestingCounter == 0) 119 | #endif 120 | { 121 | highPrioThread = nOS_FindHighPrioThread(); 122 | if (highPrioThread != NULL) { 123 | #if (NOS_CONFIG_SCHED_PREEMPTIVE_ENABLE > 0) || (NOS_CONFIG_SCHED_ROUND_ROBIN_ENABLE > 0) 124 | nOS_highPrioThread = highPrioThread; 125 | if (nOS_runningThread != nOS_highPrioThread) { 126 | *(volatile uint32_t *)0xE000ED04UL = 0x10000000UL; 127 | } 128 | #endif 129 | } else if (nOS_runningThread != &nOS_mainHandle) { 130 | nOS_highPrioThread = &nOS_mainHandle; 131 | *(volatile uint32_t *)0xE000ED04UL = 0x10000000UL; 132 | } 133 | } 134 | } 135 | nOS_LeaveCritical(sr); 136 | } 137 | } 138 | 139 | void PendSV_Handler (void) 140 | { 141 | __asm volatile ( 142 | /* Disable interrupts */ 143 | "CPSID I \n" 144 | "ISB \n" 145 | 146 | /* Save PSP before doing anything, PendSV_Handler already running on MSP */ 147 | "MRS R0, PSP \n" 148 | 149 | /* Get the location of nOS_runningThread */ 150 | "LDR R3, runningThread \n" 151 | "LDR R2, [R3] \n" 152 | 153 | #if defined(__VFP_FP__) && !defined(__SOFTFP__) 154 | /* Is thread using FPU? Yes, push high VFP registers to stack */ 155 | "TST LR, #0x10 \n" 156 | "IT EQ \n" 157 | "VSTMDBEQ R0!, {S16-S31} \n" 158 | #endif 159 | 160 | /* Push remaining registers on thread stack */ 161 | "STMDB R0!, {R4-R11, LR} \n" 162 | 163 | /* Save PSP to nOS_Thread object of current running thread */ 164 | "STR R0, [R2] \n" 165 | 166 | /* Get the location of nOS_highPrioThread */ 167 | "LDR R1, highPrioThread \n" 168 | "LDR R2, [R1] \n" 169 | 170 | /* Copy nOS_highPrioThread to nOS_runningThread */ 171 | "STR R2, [R3] \n" 172 | 173 | /* Restore PSP from nOS_Thread object of high prio thread */ 174 | "LDR R0, [R2] \n" 175 | 176 | /* Pop registers from thread stack */ 177 | "LDMIA R0!, {R4-R11, LR} \n" 178 | 179 | #if defined(__VFP_FP__) && !defined(__SOFTFP__) 180 | /* Is thread using FPU? Yes, pop high VFP registers from stack */ 181 | "TST LR, #0x10 \n" 182 | "IT EQ \n" 183 | "VLDMIAEQ R0!, {S16-S31} \n" 184 | #endif 185 | 186 | /* Restore PSP to high prio thread stack */ 187 | "MSR PSP, R0 \n" 188 | 189 | /* Enable interrupts */ 190 | "CPSIE I \n" 191 | "ISB \n" 192 | 193 | /* Return */ 194 | "BX LR \n" 195 | 196 | ".align 2 \n" 197 | "runningThread: .word nOS_runningThread \n" 198 | "highPrioThread: .word nOS_highPrioThread \n" 199 | ); 200 | } 201 | 202 | #ifdef __cplusplus 203 | } 204 | #endif 205 | -------------------------------------------------------------------------------- /src/port/GCC/AVR/nOSPort.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2019 Jim Tremblay 3 | * 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | */ 8 | 9 | #define NOS_PRIVATE 10 | #include "nOS.h" 11 | #include 12 | 13 | #ifdef __cplusplus 14 | extern "C" { 15 | #endif 16 | 17 | #ifdef NOS_CONFIG_ISR_STACK_SIZE 18 | static nOS_Stack _isrStack[NOS_CONFIG_ISR_STACK_SIZE]; 19 | #endif 20 | 21 | void nOS_InitSpecific (void) 22 | { 23 | #ifdef NOS_CONFIG_ISR_STACK_SIZE 24 | #if (NOS_CONFIG_DEBUG > 0) 25 | size_t i; 26 | 27 | for (i = 0; i < NOS_CONFIG_ISR_STACK_SIZE; i++) { 28 | _isrStack[i] = 0xFF; 29 | } 30 | #endif 31 | #endif 32 | } 33 | 34 | void nOS_InitContext (nOS_Thread *thread, nOS_Stack *stack, size_t ssize, nOS_ThreadEntry entry, void *arg) 35 | { 36 | /* Stack grow from high to low address */ 37 | nOS_Stack *tos = stack + (ssize - 1); 38 | #if (NOS_CONFIG_DEBUG > 0) 39 | size_t i; 40 | 41 | for (i = 0; i < ssize; i++) { 42 | stack[i] = 0xFF; 43 | } 44 | #endif 45 | 46 | /* Simulate a call to thread function */ 47 | *tos-- = (nOS_Stack)((uint16_t)entry); 48 | *tos-- = (nOS_Stack)((uint16_t)entry >> 8); 49 | #ifdef __AVR_3_BYTE_PC__ 50 | *tos-- = 0x00; /* Always set high part of address to 0 */ 51 | #endif 52 | 53 | /* Simulate a call of nOS_PushContext */ 54 | #if (NOS_CONFIG_DEBUG > 0) 55 | *tos-- = 0x01; /* R0 */ 56 | #else 57 | tos -= 1; /* R0 */ 58 | #endif 59 | *tos-- = 0x80; /* SREG: Interrupts enabled */ 60 | #ifdef __AVR_HAVE_RAMPZ__ 61 | tos -= 1; /* RAMPZ */ 62 | #endif 63 | #ifdef __AVR_3_BYTE_PC__ 64 | tos -= 1; /* EIND */ 65 | #endif 66 | *tos-- = 0x00; /* R1 always 0 */ 67 | #if (NOS_CONFIG_DEBUG > 0) 68 | *tos-- = 0x02; /* R2 */ 69 | *tos-- = 0x03; /* R3 */ 70 | *tos-- = 0x04; /* R4 */ 71 | *tos-- = 0x05; /* R5 */ 72 | *tos-- = 0x06; /* R6 */ 73 | *tos-- = 0x07; /* R7 */ 74 | *tos-- = 0x08; /* R8 */ 75 | *tos-- = 0x09; /* R9 */ 76 | *tos-- = 0x10; /* R10 */ 77 | *tos-- = 0x11; /* R11 */ 78 | *tos-- = 0x12; /* R12 */ 79 | *tos-- = 0x13; /* R13 */ 80 | *tos-- = 0x14; /* R14 */ 81 | *tos-- = 0x15; /* R15 */ 82 | *tos-- = 0x16; /* R16 */ 83 | *tos-- = 0x17; /* R17 */ 84 | *tos-- = 0x18; /* R18 */ 85 | *tos-- = 0x19; /* R19 */ 86 | *tos-- = 0x20; /* R20 */ 87 | *tos-- = 0x21; /* R21 */ 88 | *tos-- = 0x22; /* R22 */ 89 | *tos-- = 0x23; /* R23 */ 90 | #else 91 | tos -= 22; /* R2 to R23 */ 92 | #endif 93 | *tos-- = (nOS_Stack)((uint16_t)arg); /* R24: arg LSB */ 94 | *tos-- = (nOS_Stack)((uint16_t)arg >> 8); /* R25: arg MSB */ 95 | #if (NOS_CONFIG_DEBUG > 0) 96 | *tos-- = 0x26; /* R26 */ 97 | *tos-- = 0x27; /* R27 */ 98 | *tos-- = 0x28; /* R28 */ 99 | *tos-- = 0x29; /* R29 */ 100 | *tos-- = 0x30; /* R30 */ 101 | *tos-- = 0x31; /* R31 */ 102 | #else 103 | tos -= 6; /* R26 to R31 */ 104 | #endif 105 | 106 | thread->stackPtr = tos; 107 | } 108 | 109 | /* Absolutely need a naked function because function call push the return address on the stack */ 110 | void nOS_SwitchContext (void) 111 | { 112 | PUSH_CONTEXT(); 113 | nOS_runningThread->stackPtr = (uint8_t*)SP; 114 | nOS_runningThread = nOS_highPrioThread; 115 | SP = (int)nOS_highPrioThread->stackPtr; 116 | POP_CONTEXT(); 117 | asm volatile("ret"); 118 | } 119 | 120 | nOS_Stack *nOS_EnterISR (nOS_Stack *sp) 121 | { 122 | #if (NOS_CONFIG_SAFE > 0) 123 | if (nOS_running) 124 | #endif 125 | { 126 | /* Interrupts already disabled when entering in ISR */ 127 | if (nOS_isrNestingCounter == 0) { 128 | nOS_runningThread->stackPtr = sp; 129 | #ifdef NOS_CONFIG_ISR_STACK_SIZE 130 | sp = &_isrStack[NOS_CONFIG_ISR_STACK_SIZE-1]; 131 | #else 132 | sp = nOS_mainHandle.stackPtr; 133 | #endif 134 | } 135 | nOS_isrNestingCounter++; 136 | } 137 | 138 | return sp; 139 | } 140 | 141 | nOS_Stack *nOS_LeaveISR (nOS_Stack *sp) 142 | { 143 | nOS_Thread *highPrioThread; 144 | 145 | #if (NOS_CONFIG_SAFE > 0) 146 | if (nOS_running) 147 | #endif 148 | { 149 | /* Interrupts already disabled before leaving ISR */ 150 | nOS_isrNestingCounter--; 151 | if (nOS_isrNestingCounter == 0) { 152 | #if (NOS_CONFIG_SCHED_LOCK_ENABLE > 0) 153 | if (nOS_lockNestingCounter == 0) 154 | #endif 155 | { 156 | highPrioThread = nOS_FindHighPrioThread(); 157 | if (highPrioThread != NULL) { 158 | #if (NOS_CONFIG_SCHED_PREEMPTIVE_ENABLE > 0) || (NOS_CONFIG_SCHED_ROUND_ROBIN_ENABLE > 0) 159 | nOS_highPrioThread = highPrioThread; 160 | nOS_runningThread = nOS_highPrioThread; 161 | #endif 162 | } else { 163 | nOS_highPrioThread = &nOS_mainHandle; 164 | nOS_runningThread = nOS_highPrioThread; 165 | } 166 | } 167 | sp = nOS_runningThread->stackPtr; 168 | } 169 | } 170 | return sp; 171 | } 172 | 173 | #ifdef __cplusplus 174 | } 175 | #endif 176 | -------------------------------------------------------------------------------- /src/port/GCC/M16C_R8C/nOSPort.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2019 Jim Tremblay 3 | * 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | */ 8 | 9 | #define NOS_PRIVATE 10 | #include "nOS.h" 11 | 12 | #ifdef __cplusplus 13 | extern "C" { 14 | #endif 15 | 16 | void nOS_InitContext (nOS_Thread *thread, nOS_Stack *stack, size_t ssize, nOS_ThreadEntry entry, void *arg) 17 | { 18 | nOS_Stack *tos = (nOS_Stack*)((uint16_t)(stack + ssize) & 0xFFFE); 19 | #if (NOS_CONFIG_DEBUG > 0) 20 | size_t i; 21 | 22 | for (i = 0; i < ssize; i++) { 23 | stack[i] = 0xFFFF; 24 | } 25 | #endif 26 | 27 | /* FLG = 0x0C0 = interrupts enabled, USP stack pointer */ 28 | *(--tos) = 0x00C0; 29 | *(--tos) = (nOS_Stack)entry; 30 | 31 | #if (NOS_CONFIG_DEBUG > 0) 32 | *(--tos) = 0xFFFF; /* FB */ 33 | *(--tos) = 0xCCCC; /* SB */ 34 | *(--tos) = 0xBBBB; /* A1 */ 35 | *(--tos) = 0xAAAA; /* A0 */ 36 | *(--tos) = 0x3333; /* R3 */ 37 | *(--tos) = 0x2222; /* R2 */ 38 | #else 39 | tos -= 6; /* FB, SB, A1, A0, R3, R2 */ 40 | #endif 41 | *(--tos) = (nOS_Stack)arg; /* R1 */ 42 | #if (NOS_CONFIG_DEBUG > 0) 43 | *(--tos) = 0x1111; /* R0 */ 44 | #else 45 | tos -= 1; /* R0 */ 46 | #endif 47 | 48 | thread->stackPtr = tos; 49 | } 50 | 51 | void nOS_EnterISR (void) 52 | { 53 | nOS_StatusReg sr; 54 | 55 | #if (NOS_CONFIG_SAFE > 0) 56 | if (nOS_running) 57 | #endif 58 | { 59 | nOS_EnterCritical(sr); 60 | nOS_isrNestingCounter++; 61 | nOS_LeaveCritical(sr); 62 | } 63 | } 64 | 65 | bool nOS_LeaveISR (void) 66 | { 67 | nOS_StatusReg sr; 68 | nOS_Thread *highPrioThread; 69 | bool swctx = false; 70 | 71 | #if (NOS_CONFIG_SAFE > 0) 72 | if (nOS_running) 73 | #endif 74 | { 75 | nOS_EnterCritical(sr); 76 | nOS_isrNestingCounter--; 77 | if (nOS_isrNestingCounter == 0) { 78 | #if (NOS_CONFIG_SCHED_LOCK_ENABLE > 0) 79 | if (nOS_lockNestingCounter == 0) 80 | #endif 81 | { 82 | highPrioThread = nOS_FindHighPrioThread(); 83 | if (highPrioThread != NULL) { 84 | #if (NOS_CONFIG_SCHED_PREEMPTIVE_ENABLE > 0) || (NOS_CONFIG_SCHED_ROUND_ROBIN_ENABLE > 0) 85 | nOS_highPrioThread = highPrioThread; 86 | if (nOS_runningThread != nOS_highPrioThread) { 87 | swctx = true; 88 | } 89 | #endif 90 | } else if (nOS_runningThread != &nOS_mainHandle) { 91 | nOS_highPrioThread = &nOS_mainHandle; 92 | swctx = true; 93 | } 94 | } 95 | } 96 | nOS_LeaveCritical(sr); 97 | } 98 | return swctx; 99 | } 100 | 101 | void nOS_SwitchContextHandler (void) 102 | { 103 | __asm volatile ( 104 | /* Push all registers on thread stack */ 105 | "PUSHM R0,R1,R2,R3,A0,A1,SB,FB \n" 106 | 107 | /* Save SP to nOS_Thread object of current running thread */ 108 | "MOV.W _nOS_runningThread, A0 \n" 109 | "STC SP, [A0] \n" 110 | 111 | /* Copy nOS_highPrioThread to nOS_runningThread */ 112 | "MOV.W _nOS_highPrioThread, _nOS_runningThread \n" 113 | 114 | /* Restore SP from nOS_Thread object of high prio thread */ 115 | "MOV.W _nOS_highPrioThread, A0 \n" 116 | "LDC [A0], SP \n" 117 | 118 | /* Pop all registers from thread stack */ 119 | "POPM R0,R1,R2,R3,A0,A1,SB,FB \n" 120 | ); 121 | } 122 | 123 | void nOS_SwitchContextFromIsrHandler (void) 124 | { 125 | __asm volatile ( 126 | /* Push all registers on thread stack */ 127 | "PUSHM R0,R1,R2,R3,A0,A1,SB,FB \n" 128 | 129 | /* Move PC and FLG from ISTACK to USTACK */ 130 | "STC ISP, A0 \n" 131 | "MOV.W 0[A0], 16[SP] \n" 132 | "MOV.W 2[A0], 18[SP] \n" 133 | 134 | /* Adjust ISTACK (remove PC and FLG) */ 135 | "ADD.W #4, A0 \n" 136 | "LDC A0, ISP \n" 137 | 138 | /* Save SP to nOS_Thread object of current running thread */ 139 | "MOV.W _nOS_runningThread, A0 \n" 140 | "STC SP, [A0] \n" 141 | 142 | /* Copy nOS_highPrioThread to nOS_runningThread */ 143 | "MOV.W _nOS_highPrioThread, _nOS_runningThread \n" 144 | 145 | /* Restore SP from nOS_Thread object of high prio thread */ 146 | "MOV.W _nOS_highPrioThread, A0 \n" 147 | "LDC [A0], SP \n" 148 | 149 | /* Pop all registers from thread stack */ 150 | "POPM R0,R1,R2,R3,A0,A1,SB,FB \n" 151 | ); 152 | } 153 | 154 | #ifdef __cplusplus 155 | } 156 | #endif 157 | -------------------------------------------------------------------------------- /src/port/GCC/MSP430/nOSPort.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2019 Jim Tremblay 3 | * 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | */ 8 | 9 | #define NOS_PRIVATE 10 | #include "nOS.h" 11 | 12 | #ifdef __cplusplus 13 | extern "C" { 14 | #endif 15 | 16 | #ifdef NOS_CONFIG_ISR_STACK_SIZE 17 | static nOS_Stack _isrStack[NOS_CONFIG_ISR_STACK_SIZE]; 18 | #endif 19 | 20 | void nOS_InitContext (nOS_Thread *thread, nOS_Stack *stack, size_t ssize, nOS_ThreadEntry entry, void *arg) 21 | { 22 | /* Stack grow from high to low address */ 23 | nOS_Stack *tos = stack + (ssize - 1); 24 | uint16_t *tos16; 25 | #if (NOS_CONFIG_DEBUG > 0) 26 | size_t i; 27 | 28 | for (i = 0; i < ssize; i++) { 29 | stack[i] = (nOS_Stack)0xFFFFFFFF; 30 | } 31 | #endif 32 | 33 | tos16 = (uint16_t*)tos; 34 | #if (__MSP430X_LARGE__ > 0) 35 | *tos16-- = (uint16_t)((nOS_Stack)entry >> 16); /* PC MSB */ 36 | #endif 37 | *tos16-- = (uint16_t)((nOS_Stack)entry); /* PC LSB */ 38 | *tos16-- = 0x0008; /* SR */ 39 | #if (__MSP430X_LARGE__ > 0) 40 | tos16 -= 1; 41 | #endif 42 | tos = (nOS_Stack*)tos16; 43 | 44 | #if (NOS_CONFIG_DEBUG > 0) 45 | *tos-- = (nOS_Stack)0x15151515; /* R15 */ 46 | *tos-- = (nOS_Stack)0x14141414; /* R14 */ 47 | *tos-- = (nOS_Stack)0x13131313; /* R13 */ 48 | #else 49 | tos -= 3; /* R15 to R13 */ 50 | #endif 51 | 52 | *tos-- = (nOS_Stack)arg; /* R12 */ 53 | #if (NOS_CONFIG_DEBUG > 0) 54 | *tos-- = (nOS_Stack)0x11111111; /* R11 */ 55 | *tos-- = (nOS_Stack)0x10101010; /* R10 */ 56 | *tos-- = (nOS_Stack)0x09090909; /* R9 */ 57 | *tos-- = (nOS_Stack)0x08080808; /* R8 */ 58 | *tos-- = (nOS_Stack)0x07070707; /* R7 */ 59 | *tos-- = (nOS_Stack)0x06060606; /* R6 */ 60 | *tos-- = (nOS_Stack)0x05050505; /* R5 */ 61 | *tos = (nOS_Stack)0x04040404; /* R4 */ 62 | #else 63 | tos -= 7; /* R11 to R4 */ 64 | #endif 65 | 66 | thread->stackPtr = tos; 67 | } 68 | 69 | void nOS_SwitchContextHandler (void) 70 | { 71 | asm volatile ( 72 | /* Simulate an interrupt by pushing SR */ 73 | PUSH_SR" \n" 74 | " \n" 75 | /* Push all registers to running thread stack */ 76 | PUSH_CONTEXT" \n" 77 | " \n" 78 | /* Save stack pointer to running thread structure */ 79 | MOV_X" &nOS_runningThread, r12 \n" 80 | MOV_X" sp, 0(r12) \n" 81 | " \n" 82 | /* Copy nOS_highPrioThread to nOS_runningThread */ 83 | MOV_X" &nOS_highPrioThread, r12 \n" 84 | MOV_X" #nOS_runningThread, r11 \n" 85 | MOV_X" r12, 0(r11) \n" 86 | " \n" 87 | /* Restore stack pointer from high prio thread structure */ 88 | MOV_X" @r12, sp \n" 89 | " \n" 90 | /* Pop all registers from high prio thread stack */ 91 | POP_CONTEXT" \n" 92 | " \n" 93 | POP_SR" \n" 94 | " \n" 95 | RET_X" \n" 96 | ); 97 | } 98 | 99 | nOS_Stack* nOS_EnterISR (nOS_Stack *sp) 100 | { 101 | #if (NOS_CONFIG_SAFE > 0) 102 | if (nOS_running) 103 | #endif 104 | { 105 | if (nOS_isrNestingCounter == 0) { 106 | nOS_runningThread->stackPtr = sp; 107 | #ifdef NOS_CONFIG_ISR_STACK_SIZE 108 | sp = &_isrStack[NOS_CONFIG_ISR_STACK_SIZE-1]; 109 | #else 110 | sp = nOS_mainHandle.stackPtr; 111 | #endif 112 | } 113 | nOS_isrNestingCounter++; 114 | } 115 | 116 | return sp; 117 | } 118 | 119 | nOS_Stack* nOS_LeaveISR (nOS_Stack *sp) 120 | { 121 | nOS_Thread *highPrioThread; 122 | 123 | #if (NOS_CONFIG_SAFE > 0) 124 | if (nOS_running) 125 | #endif 126 | { 127 | nOS_isrNestingCounter--; 128 | if (nOS_isrNestingCounter == 0) { 129 | #if (NOS_CONFIG_SCHED_LOCK_ENABLE > 0) 130 | if (nOS_lockNestingCounter == 0) 131 | #endif 132 | { 133 | highPrioThread = nOS_FindHighPrioThread(); 134 | if (highPrioThread != NULL) { 135 | #if (NOS_CONFIG_SCHED_PREEMPTIVE_ENABLE > 0) || (NOS_CONFIG_SCHED_ROUND_ROBIN_ENABLE > 0) 136 | nOS_highPrioThread = highPrioThread; 137 | nOS_runningThread = nOS_highPrioThread; 138 | #endif 139 | } else { 140 | nOS_highPrioThread = &nOS_mainHandle; 141 | nOS_runningThread = nOS_highPrioThread; 142 | } 143 | } 144 | sp = nOS_runningThread->stackPtr; 145 | } 146 | } 147 | return sp; 148 | } 149 | 150 | #ifdef __cplusplus 151 | } 152 | #endif 153 | -------------------------------------------------------------------------------- /src/port/GCC/RX600/nOSPort.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2019 Jim Tremblay 3 | * 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | */ 8 | 9 | #define NOS_PRIVATE 10 | #include "nOS.h" 11 | 12 | #ifdef __cplusplus 13 | extern "C" { 14 | #endif 15 | 16 | void INT_Excep_ICU_SWINT(void) __attribute__((naked)); 17 | 18 | void nOS_InitSpecific (void) 19 | { 20 | /* Enable software interrupt */ 21 | *(uint8_t*)0x00087203UL |= (uint8_t)0x08; 22 | 23 | /* Clear software interrupt */ 24 | *(uint8_t*)0x00087003UL &=~ (uint8_t)0x08; 25 | 26 | /* Set software interrupt to lowest priority level */ 27 | *(uint8_t*)0x00087303UL = (uint8_t)1; 28 | } 29 | 30 | void nOS_InitContext (nOS_Thread *thread, nOS_Stack *stack, size_t ssize, nOS_ThreadEntry entry, void *arg) 31 | { 32 | nOS_Stack *tos = (stack + (ssize - 1)); 33 | #if (NOS_CONFIG_DEBUG > 0) 34 | size_t i; 35 | 36 | for (i = 0; i < ssize; i++) { 37 | stack[i] = 0xFFFFFFFFUL; 38 | } 39 | #endif 40 | 41 | *tos-- = 0x00030000UL; /* Interrupts enabled, User stack selected, Supervisor mode */ 42 | *tos-- = (nOS_Stack)entry; 43 | #if (NOS_CONFIG_DEBUG > 0) 44 | *tos-- = 0x15151515UL; 45 | *tos-- = 0x14141414UL; 46 | *tos-- = 0x13131313UL; 47 | *tos-- = 0x12121212UL; 48 | *tos-- = 0x11111111UL; 49 | *tos-- = 0x10101010UL; 50 | *tos-- = 0x09090909UL; 51 | *tos-- = 0x08080808UL; 52 | *tos-- = 0x07070707UL; 53 | *tos-- = 0x06060606UL; 54 | *tos-- = 0x05050505UL; 55 | *tos-- = 0x04040404UL; 56 | *tos-- = 0x03030303UL; 57 | *tos-- = 0x02020202UL; 58 | #else 59 | tos -= 14; 60 | #endif 61 | *tos-- = (nOS_Stack)arg; 62 | *tos-- = 0x00000100UL; /* Floating-point status word (default) */ 63 | #if (NOS_CONFIG_DEBUG > 0) 64 | *tos-- = 0x01234567UL; /* Accumulator high */ 65 | *tos = 0x89ABCDEFUL; /* Accumulator low */ 66 | #else 67 | tos -= 1; 68 | #endif 69 | 70 | thread->stackPtr = tos; 71 | } 72 | 73 | void nOS_EnterISR (void) 74 | { 75 | nOS_StatusReg sr; 76 | 77 | #if (NOS_CONFIG_SAFE > 0) 78 | if (nOS_running) 79 | #endif 80 | { 81 | nOS_EnterCritical(sr); 82 | nOS_isrNestingCounter++; 83 | nOS_LeaveCritical(sr); 84 | } 85 | } 86 | 87 | void nOS_LeaveISR (void) 88 | { 89 | nOS_StatusReg sr; 90 | nOS_Thread *highPrioThread; 91 | 92 | #if (NOS_CONFIG_SAFE > 0) 93 | if (nOS_running) 94 | #endif 95 | { 96 | nOS_EnterCritical(sr); 97 | nOS_isrNestingCounter--; 98 | if (nOS_isrNestingCounter == 0) { 99 | #if (NOS_CONFIG_SCHED_LOCK_ENABLE > 0) 100 | if (nOS_lockNestingCounter == 0) 101 | #endif 102 | { 103 | highPrioThread = nOS_FindHighPrioThread(); 104 | if (highPrioThread != NULL) { 105 | #if (NOS_CONFIG_SCHED_PREEMPTIVE_ENABLE > 0) || (NOS_CONFIG_SCHED_ROUND_ROBIN_ENABLE > 0) 106 | nOS_highPrioThread = highPrioThread; 107 | if (nOS_runningThread != nOS_highPrioThread) { 108 | /* Request a software interrupt when going out of ISR */ 109 | *(uint8_t*)0x000872E0UL = (uint8_t)1; 110 | } 111 | #endif 112 | } else if (nOS_runningThread != &nOS_mainHandle) { 113 | nOS_highPrioThread = &nOS_mainHandle; 114 | /* Return to main thread when going out of ISR */ 115 | *(uint8_t*)0x000872E0UL = (uint8_t)1; 116 | } 117 | } 118 | } 119 | nOS_LeaveCritical(sr); 120 | } 121 | } 122 | 123 | void INT_Excep_ICU_SWINT (void) 124 | { 125 | __asm volatile( 126 | /* Push R15 on ISP (we will use it) */ 127 | "PUSH.L R15 \n" 128 | 129 | /* Get running thread stack and adjust it to contains PSW, PC and R15 */ 130 | "MVFC USP, R15 \n" 131 | "SUB #12, R15 \n" 132 | 133 | /* Set USP to adjusted value */ 134 | "MVTC R15, USP \n" 135 | 136 | /* Moved pushed registers from ISP to running thread stack */ 137 | "MOV.L [R0], [R15] \n" 138 | "MOV.L 4[R0], 4[R15] \n" 139 | "MOV.L 8[R0], 8[R15] \n" 140 | 141 | /* Adjust ISP (Remove R15, PC and PSW from the stack) */ 142 | "ADD #12, R0 \n" 143 | 144 | /* At this point, we can continue on USP */ 145 | "SETPSW U \n" 146 | 147 | /* Push all remaining registers to running thread stack */ 148 | "PUSHM R1-R14 \n" 149 | 150 | /* Push floating-point status register to running thread stack */ 151 | "PUSHC FPSW \n" 152 | 153 | /* Push accumulator register to running thread stack */ 154 | "MVFACHI R15 \n" 155 | "MVFACMI R14 \n" 156 | "SHLL #16, R14 \n" 157 | "PUSHM R14-R15 \n" 158 | 159 | /* Save SP in nOS_runningThread object */ 160 | "MOV.L #_nOS_runningThread, R15 \n" 161 | "MOV.L [R15], R14 \n" 162 | "MOV.L R0, [R14] \n" 163 | 164 | /* nOS_runningThread = nOS_highPrioThread */ 165 | "MOV.L #_nOS_highPrioThread, R14 \n" 166 | "MOV.L [R14], [R15] \n" 167 | 168 | /* Restore SP from nOS_highPrioThread object */ 169 | "MOV.L [R14], R15 \n" 170 | "MOV.L [R15], R0 \n" 171 | 172 | /* Pop accumulator register from high prio thread stack */ 173 | "POPM R14-R15 \n" 174 | "MVTACLO R14 \n" 175 | "MVTACHI R15 \n" 176 | 177 | /* Pop floating-point status register from high prio thread stack */ 178 | "POPC FPSW \n" 179 | 180 | /* Pop all registers from high prio thread stack */ 181 | "POPM R1-R15 \n" 182 | 183 | /* Return from interrupt (will pop PC and PSW) */ 184 | "RTE \n" 185 | "NOP \n" 186 | "NOP \n" 187 | ); 188 | } 189 | 190 | #ifdef __cplusplus 191 | } 192 | #endif 193 | -------------------------------------------------------------------------------- /src/port/IAR/ARM_Cortex_M0/nOSPort.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2019 Jim Tremblay 3 | * 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | */ 8 | 9 | #define NOS_PRIVATE 10 | #include "nOS.h" 11 | 12 | #ifdef __cplusplus 13 | extern "C" { 14 | #endif 15 | 16 | static nOS_Stack _isrStack[NOS_CONFIG_ISR_STACK_SIZE]; 17 | 18 | void nOS_InitSpecific (void) 19 | { 20 | #if (NOS_CONFIG_DEBUG > 0) 21 | uint32_t i; 22 | 23 | for (i = 0; i < NOS_CONFIG_ISR_STACK_SIZE; i++) { 24 | _isrStack[i] = 0xFFFFFFFFUL; 25 | } 26 | #endif 27 | 28 | /* Copy MSP to PSP */ 29 | __set_PSP(__get_MSP()); 30 | /* Set MSP to local ISR stack */ 31 | __set_MSP((uint32_t)&_isrStack[NOS_CONFIG_ISR_STACK_SIZE] & 0xFFFFFFF8UL); 32 | /* Set current stack to PSP and priviledge mode */ 33 | __set_CONTROL(__get_CONTROL() | 0x00000002UL); 34 | /* Set PendSV exception to lowest priority */ 35 | *(volatile uint32_t *)0xE000ED20UL |= 0x00FF0000UL; 36 | } 37 | 38 | void nOS_InitContext (nOS_Thread *thread, nOS_Stack *stack, size_t ssize, nOS_ThreadEntry entry, void *arg) 39 | { 40 | nOS_Stack *tos = (nOS_Stack*)((uint32_t)(stack + ssize) & 0xFFFFFFF8UL); 41 | #if (NOS_CONFIG_DEBUG > 0) 42 | uint32_t i; 43 | 44 | for (i = 0; i < ssize; i++) { 45 | stack[i] = 0xFFFFFFFFUL; 46 | } 47 | #endif 48 | 49 | *(--tos) = 0x01000000UL; /* xPSR */ 50 | *(--tos) = (nOS_Stack)entry;/* PC */ 51 | *(--tos) = 0x00000000UL; /* LR */ 52 | #if (NOS_CONFIG_DEBUG > 0) 53 | *(--tos) = 0x12121212UL; /* R12 */ 54 | *(--tos) = 0x03030303UL; /* R3 */ 55 | *(--tos) = 0x02020202UL; /* R2 */ 56 | *(--tos) = 0x01010101UL; /* R1 */ 57 | #else 58 | tos -= 4; /* R12, R3, R2 and R1 */ 59 | #endif 60 | *(--tos) = (nOS_Stack)arg; /* R0 */ 61 | #if (NOS_CONFIG_DEBUG > 0) 62 | *(--tos) = 0x11111111UL; /* R11 */ 63 | *(--tos) = 0x10101010UL; /* R10 */ 64 | *(--tos) = 0x09090909UL; /* R9 */ 65 | *(--tos) = 0x08080808UL; /* R8 */ 66 | *(--tos) = 0x07070707UL; /* R7 */ 67 | *(--tos) = 0x06060606UL; /* R6 */ 68 | *(--tos) = 0x05050505UL; /* R5 */ 69 | *(--tos) = 0x04040404UL; /* R4 */ 70 | #else 71 | tos -= 8; /* R11, R10, R9, R8, R7, R6, R5 and R4 */ 72 | #endif 73 | 74 | thread->stackPtr = tos; 75 | } 76 | 77 | void nOS_SwitchContext (void) 78 | { 79 | /* Request context switch */ 80 | *(volatile uint32_t *)0xE000ED04UL = 0x10000000UL; 81 | nOS_PeekCritical(); 82 | } 83 | 84 | void nOS_EnterISR (void) 85 | { 86 | nOS_StatusReg sr; 87 | 88 | #if (NOS_CONFIG_SAFE > 0) 89 | if (nOS_running) 90 | #endif 91 | { 92 | nOS_EnterCritical(sr); 93 | nOS_isrNestingCounter++; 94 | nOS_LeaveCritical(sr); 95 | } 96 | } 97 | 98 | void nOS_LeaveISR (void) 99 | { 100 | nOS_StatusReg sr; 101 | nOS_Thread *highPrioThread; 102 | 103 | #if (NOS_CONFIG_SAFE > 0) 104 | if (nOS_running) 105 | #endif 106 | { 107 | nOS_EnterCritical(sr); 108 | nOS_isrNestingCounter--; 109 | if (nOS_isrNestingCounter == 0) { 110 | #if (NOS_CONFIG_SCHED_LOCK_ENABLE > 0) 111 | if (nOS_lockNestingCounter == 0) 112 | #endif 113 | { 114 | highPrioThread = nOS_FindHighPrioThread(); 115 | if (highPrioThread != NULL) { 116 | #if (NOS_CONFIG_SCHED_PREEMPTIVE_ENABLE > 0) || (NOS_CONFIG_SCHED_ROUND_ROBIN_ENABLE > 0) 117 | nOS_highPrioThread = highPrioThread; 118 | if (nOS_runningThread != nOS_highPrioThread) { 119 | *(volatile uint32_t *)0xE000ED04UL = 0x10000000UL; 120 | } 121 | #endif 122 | } else if (nOS_runningThread != &nOS_mainHandle) { 123 | nOS_highPrioThread = &nOS_mainHandle; 124 | *(volatile uint32_t *)0xE000ED04UL = 0x10000000UL; 125 | } 126 | } 127 | } 128 | nOS_LeaveCritical(sr); 129 | } 130 | } 131 | 132 | #ifdef __cplusplus 133 | } 134 | #endif 135 | -------------------------------------------------------------------------------- /src/port/IAR/ARM_Cortex_M0/nOSPortASM.s: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2019 Jim Tremblay 3 | * 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | */ 8 | 9 | RSEG CODE:CODE(2) 10 | thumb 11 | 12 | EXTERN nOS_runningThread 13 | EXTERN nOS_highPrioThread 14 | 15 | PUBLIC PendSV_Handler 16 | 17 | PendSV_Handler: 18 | /* Disable interrupts */ 19 | CPSID I 20 | ISB 21 | 22 | /* Save PSP before doing anything, PendSV_Handler already running on MSP */ 23 | MRS R0, PSP 24 | 25 | /* Get the location of nOS_runningThread */ 26 | LDR R3, =nOS_runningThread 27 | LDR R2, [R3] 28 | 29 | /* Make space for the remaining registers */ 30 | SUBS R0, R0, #32 31 | 32 | /* Save PSP to nOS_Thread object of current running thread */ 33 | STR R0, [R2] 34 | 35 | /* Push low registers on thread stack */ 36 | STMIA R0!, {R4-R7} 37 | 38 | /* Copy high registers to low registers */ 39 | MOV R4, R8 40 | MOV R5, R9 41 | MOV R6, R10 42 | MOV R7, R11 43 | /* Push high registers on thread stack */ 44 | STMIA R0!, {R4-R7} 45 | 46 | /* Get the location of nOS_highPrioThread */ 47 | LDR R1, =nOS_highPrioThread 48 | LDR R2, [R1] 49 | 50 | /* Copy nOS_highPrioThread to nOS_runningThread */ 51 | STR R2, [R3] 52 | 53 | /* Restore PSP from nOS_Thread object of high prio thread */ 54 | LDR R0, [R2] 55 | 56 | /* Move to the high registers */ 57 | ADDS R0, R0, #16 58 | 59 | /* Pop high registers from thread stack */ 60 | LDMIA R0!, {R4-R7} 61 | /* Copy low registers to high registers */ 62 | MOV R11, R7 63 | MOV R10, R6 64 | MOV R9, R5 65 | MOV R8, R4 66 | 67 | /* Restore PSP to high prio thread stack */ 68 | MSR PSP, R0 69 | 70 | /* Go back for the low registers */ 71 | SUBS R0, R0, #32 72 | 73 | /* Pop low registers from thread stack */ 74 | LDMIA R0!, {R4-R7} 75 | 76 | /* Enable interrupts */ 77 | CPSIE I 78 | ISB 79 | 80 | /* Return */ 81 | BX LR 82 | 83 | END 84 | -------------------------------------------------------------------------------- /src/port/IAR/ARM_Cortex_M3/nOSPort.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2019 Jim Tremblay 3 | * 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | */ 8 | 9 | #define NOS_PRIVATE 10 | #include "nOS.h" 11 | 12 | #ifdef __cplusplus 13 | extern "C" { 14 | #endif 15 | 16 | static nOS_Stack _isrStack[NOS_CONFIG_ISR_STACK_SIZE]; 17 | 18 | void nOS_InitSpecific (void) 19 | { 20 | #if (NOS_CONFIG_DEBUG > 0) 21 | uint32_t i; 22 | 23 | for (i = 0; i < NOS_CONFIG_ISR_STACK_SIZE; i++) { 24 | _isrStack[i] = 0xFFFFFFFFUL; 25 | } 26 | #endif 27 | 28 | /* Copy MSP to PSP */ 29 | __set_PSP(__get_MSP()); 30 | /* Set MSP to local ISR stack */ 31 | __set_MSP((uint32_t)&_isrStack[NOS_CONFIG_ISR_STACK_SIZE] & 0xFFFFFFF8UL); 32 | /* Set current stack to PSP and priviledge mode */ 33 | __set_CONTROL(__get_CONTROL() | 0x00000002UL); 34 | /* Set PendSV exception to lowest priority */ 35 | *(volatile uint32_t *)0xE000ED20UL |= 0x00FF0000UL; 36 | } 37 | 38 | void nOS_InitContext (nOS_Thread *thread, nOS_Stack *stack, size_t ssize, nOS_ThreadEntry entry, void *arg) 39 | { 40 | nOS_Stack *tos = (nOS_Stack*)((uint32_t)(stack + ssize) & 0xFFFFFFF8UL); 41 | #if (NOS_CONFIG_DEBUG > 0) 42 | uint32_t i; 43 | 44 | for (i = 0; i < ssize; i++) { 45 | stack[i] = 0xFFFFFFFFUL; 46 | } 47 | #endif 48 | 49 | *(--tos) = 0x01000000UL; /* xPSR */ 50 | *(--tos) = (nOS_Stack)entry;/* PC */ 51 | *(--tos) = 0x00000000UL; /* LR */ 52 | #if (NOS_CONFIG_DEBUG > 0) 53 | *(--tos) = 0x12121212UL; /* R12 */ 54 | *(--tos) = 0x03030303UL; /* R3 */ 55 | *(--tos) = 0x02020202UL; /* R2 */ 56 | *(--tos) = 0x01010101UL; /* R1 */ 57 | #else 58 | tos -= 4; /* R12, R3, R2 and R1 */ 59 | #endif 60 | *(--tos) = (nOS_Stack)arg; /* R0 */ 61 | #if (NOS_CONFIG_DEBUG > 0) 62 | *(--tos) = 0x11111111UL; /* R11 */ 63 | *(--tos) = 0x10101010UL; /* R10 */ 64 | *(--tos) = 0x09090909UL; /* R9 */ 65 | *(--tos) = 0x08080808UL; /* R8 */ 66 | *(--tos) = 0x07070707UL; /* R7 */ 67 | *(--tos) = 0x06060606UL; /* R6 */ 68 | *(--tos) = 0x05050505UL; /* R5 */ 69 | *(--tos) = 0x04040404UL; /* R4 */ 70 | #else 71 | tos -= 8; /* R11, R10, R9, R8, R7, R6, R5 and R4 */ 72 | #endif 73 | 74 | thread->stackPtr = tos; 75 | } 76 | 77 | void nOS_SwitchContext (void) 78 | { 79 | /* Request context switch */ 80 | *(volatile uint32_t *)0xE000ED04UL = 0x10000000UL; 81 | nOS_PeekCritical(); 82 | } 83 | 84 | void nOS_EnterISR (void) 85 | { 86 | nOS_StatusReg sr; 87 | 88 | #if (NOS_CONFIG_SAFE > 0) 89 | if (nOS_running) 90 | #endif 91 | { 92 | nOS_EnterCritical(sr); 93 | nOS_isrNestingCounter++; 94 | nOS_LeaveCritical(sr); 95 | } 96 | } 97 | 98 | void nOS_LeaveISR (void) 99 | { 100 | nOS_StatusReg sr; 101 | nOS_Thread *highPrioThread; 102 | 103 | #if (NOS_CONFIG_SAFE > 0) 104 | if (nOS_running) 105 | #endif 106 | { 107 | nOS_EnterCritical(sr); 108 | nOS_isrNestingCounter--; 109 | if (nOS_isrNestingCounter == 0) { 110 | #if (NOS_CONFIG_SCHED_LOCK_ENABLE > 0) 111 | if (nOS_lockNestingCounter == 0) 112 | #endif 113 | { 114 | highPrioThread = nOS_FindHighPrioThread(); 115 | if (highPrioThread != NULL) { 116 | #if (NOS_CONFIG_SCHED_PREEMPTIVE_ENABLE > 0) || (NOS_CONFIG_SCHED_ROUND_ROBIN_ENABLE > 0) 117 | nOS_highPrioThread = highPrioThread; 118 | if (nOS_runningThread != nOS_highPrioThread) { 119 | *(volatile uint32_t *)0xE000ED04UL = 0x10000000UL; 120 | } 121 | #endif 122 | } else if (nOS_runningThread != &nOS_mainHandle) { 123 | nOS_highPrioThread = &nOS_mainHandle; 124 | *(volatile uint32_t *)0xE000ED04UL = 0x10000000UL; 125 | } 126 | } 127 | } 128 | nOS_LeaveCritical(sr); 129 | } 130 | } 131 | 132 | #ifdef __cplusplus 133 | } 134 | #endif 135 | -------------------------------------------------------------------------------- /src/port/IAR/ARM_Cortex_M3/nOSPortASM.s: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2019 Jim Tremblay 3 | * 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | */ 8 | 9 | RSEG CODE:CODE(2) 10 | thumb 11 | 12 | EXTERN nOS_runningThread 13 | EXTERN nOS_highPrioThread 14 | 15 | PUBLIC PendSV_Handler 16 | 17 | PendSV_Handler: 18 | /* Disable interrupts */ 19 | CPSID I 20 | ISB 21 | 22 | /* Save PSP before doing anything, PendSV_Handler already running on MSP */ 23 | MRS R0, PSP 24 | 25 | /* Get the location of nOS_runningThread */ 26 | LDR R3, =nOS_runningThread 27 | LDR R2, [R3] 28 | 29 | /* Push remaining registers on thread stack */ 30 | STMDB R0!, {R4-R11} 31 | 32 | /* Save PSP to nOS_Thread object of current running thread */ 33 | STR R0, [R2] 34 | 35 | /* Get the location of nOS_highPrioThread */ 36 | LDR R1, =nOS_highPrioThread 37 | LDR R2, [R1] 38 | 39 | /* Copy nOS_highPrioThread to nOS_runningThread */ 40 | STR R2, [R3] 41 | 42 | /* Restore PSP from nOS_Thread object of high prio thread */ 43 | LDR R0, [R2] 44 | 45 | /* Pop registers from thread stack */ 46 | LDMIA R0!, {R4-R11} 47 | 48 | /* Restore PSP to high prio thread stack */ 49 | MSR PSP, R0 50 | 51 | /* Enable interrupts */ 52 | CPSIE I 53 | ISB 54 | 55 | /* Return */ 56 | BX LR 57 | 58 | END 59 | -------------------------------------------------------------------------------- /src/port/IAR/ARM_Cortex_M4/nOSPort.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2019 Jim Tremblay 3 | * 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | */ 8 | 9 | #define NOS_PRIVATE 10 | #include "nOS.h" 11 | 12 | #ifdef __cplusplus 13 | extern "C" { 14 | #endif 15 | 16 | static nOS_Stack _isrStack[NOS_CONFIG_ISR_STACK_SIZE]; 17 | 18 | void nOS_InitSpecific (void) 19 | { 20 | #if (NOS_CONFIG_DEBUG > 0) 21 | uint32_t i; 22 | 23 | for (i = 0; i < NOS_CONFIG_ISR_STACK_SIZE; i++) { 24 | _isrStack[i] = 0xFFFFFFFFUL; 25 | } 26 | #endif 27 | 28 | /* Copy MSP to PSP */ 29 | __set_PSP(__get_MSP()); 30 | /* Set MSP to local ISR stack */ 31 | __set_MSP((uint32_t)&_isrStack[NOS_CONFIG_ISR_STACK_SIZE] & 0xFFFFFFF8UL); 32 | /* Set current stack to PSP and privileged mode */ 33 | __set_CONTROL(__get_CONTROL() | 0x00000002UL); 34 | /* Set PendSV exception to lowest priority */ 35 | *(volatile uint32_t *)0xE000ED20UL |= 0x00FF0000UL; 36 | } 37 | 38 | void nOS_InitContext (nOS_Thread *thread, nOS_Stack *stack, size_t ssize, nOS_ThreadEntry entry, void *arg) 39 | { 40 | nOS_Stack *tos = (nOS_Stack*)((uint32_t)(stack + ssize) & 0xFFFFFFF8UL); 41 | #if (NOS_CONFIG_DEBUG > 0) 42 | uint32_t i; 43 | 44 | for (i = 0; i < ssize; i++) { 45 | stack[i] = 0xFFFFFFFFUL; 46 | } 47 | #endif 48 | 49 | *(--tos) = 0x01000000UL; /* xPSR */ 50 | *(--tos) = (nOS_Stack)entry;/* PC */ 51 | *(--tos) = 0x00000000UL; /* LR */ 52 | #if (NOS_CONFIG_DEBUG > 0) 53 | *(--tos) = 0x12121212UL; /* R12 */ 54 | *(--tos) = 0x03030303UL; /* R3 */ 55 | *(--tos) = 0x02020202UL; /* R2 */ 56 | *(--tos) = 0x01010101UL; /* R1 */ 57 | #else 58 | tos -= 4; /* R12, R3, R2 and R1 */ 59 | #endif 60 | *(--tos) = (nOS_Stack)arg; /* R0 */ 61 | *(--tos) = 0xFFFFFFFDUL; /* EXC_RETURN (Thread mode, Thread use PSP) */ 62 | #if (NOS_CONFIG_DEBUG > 0) 63 | *(--tos) = 0x11111111UL; /* R11 */ 64 | *(--tos) = 0x10101010UL; /* R10 */ 65 | *(--tos) = 0x09090909UL; /* R9 */ 66 | *(--tos) = 0x08080808UL; /* R8 */ 67 | *(--tos) = 0x07070707UL; /* R7 */ 68 | *(--tos) = 0x06060606UL; /* R6 */ 69 | *(--tos) = 0x05050505UL; /* R5 */ 70 | *(--tos) = 0x04040404UL; /* R4 */ 71 | #else 72 | tos -= 8; /* R11, R10, R9, R8, R7, R6, R5 and R4 */ 73 | #endif 74 | 75 | thread->stackPtr = tos; 76 | } 77 | 78 | void nOS_SwitchContext (void) 79 | { 80 | /* Request context switch */ 81 | *(volatile uint32_t *)0xE000ED04UL = 0x10000000UL; 82 | nOS_PeekCritical(); 83 | } 84 | 85 | void nOS_EnterISR (void) 86 | { 87 | nOS_StatusReg sr; 88 | 89 | #if (NOS_CONFIG_SAFE > 0) 90 | if (nOS_running) 91 | #endif 92 | { 93 | nOS_EnterCritical(sr); 94 | nOS_isrNestingCounter++; 95 | nOS_LeaveCritical(sr); 96 | } 97 | } 98 | 99 | void nOS_LeaveISR (void) 100 | { 101 | nOS_StatusReg sr; 102 | nOS_Thread *highPrioThread; 103 | 104 | #if (NOS_CONFIG_SAFE > 0) 105 | if (nOS_running) 106 | #endif 107 | { 108 | nOS_EnterCritical(sr); 109 | nOS_isrNestingCounter--; 110 | if (nOS_isrNestingCounter == 0) { 111 | #if (NOS_CONFIG_SCHED_LOCK_ENABLE > 0) 112 | if (nOS_lockNestingCounter == 0) 113 | #endif 114 | { 115 | highPrioThread = nOS_FindHighPrioThread(); 116 | if (highPrioThread != NULL) { 117 | #if (NOS_CONFIG_SCHED_PREEMPTIVE_ENABLE > 0) || (NOS_CONFIG_SCHED_ROUND_ROBIN_ENABLE > 0) 118 | nOS_highPrioThread = highPrioThread; 119 | if (nOS_runningThread != nOS_highPrioThread) { 120 | *(volatile uint32_t *)0xE000ED04UL = 0x10000000UL; 121 | } 122 | #endif 123 | } else if (nOS_runningThread != &nOS_mainHandle) { 124 | nOS_highPrioThread = &nOS_mainHandle; 125 | *(volatile uint32_t *)0xE000ED04UL = 0x10000000UL; 126 | } 127 | } 128 | } 129 | nOS_LeaveCritical(sr); 130 | } 131 | } 132 | 133 | #ifdef __cplusplus 134 | } 135 | #endif 136 | -------------------------------------------------------------------------------- /src/port/IAR/ARM_Cortex_M4/nOSPortASM.s: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2019 Jim Tremblay 3 | * 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | */ 8 | 9 | RSEG CODE:CODE(2) 10 | thumb 11 | 12 | EXTERN nOS_runningThread 13 | EXTERN nOS_highPrioThread 14 | 15 | PUBLIC PendSV_Handler 16 | 17 | PendSV_Handler: 18 | /* Disable interrupts */ 19 | CPSID I 20 | ISB 21 | 22 | /* Save PSP before doing anything, PendSV_Handler already running on MSP */ 23 | MRS R0, PSP 24 | 25 | /* Get the location of nOS_runningThread */ 26 | LDR R3, =nOS_runningThread 27 | LDR R2, [R3] 28 | 29 | #ifdef __ARMVFP__ 30 | /* Is thread using FPU? Yes, push high VFP registers to stack */ 31 | TST LR, #0x10 32 | IT EQ 33 | VSTMDBEQ R0!, {S16-S31} 34 | #endif 35 | 36 | /* Push remaining registers on thread stack */ 37 | STMDB R0!, {R4-R11, LR} 38 | 39 | /* Save PSP to nOS_Thread object of current running thread */ 40 | STR R0, [R2] 41 | 42 | /* Get the location of nOS_highPrioThread */ 43 | LDR R1, =nOS_highPrioThread 44 | LDR R2, [R1] 45 | 46 | /* Copy nOS_highPrioThread to nOS_runningThread */ 47 | STR R2, [R3] 48 | 49 | /* Restore PSP from nOS_Thread object of high prio thread */ 50 | LDR R0, [R2] 51 | 52 | /* Pop registers from thread stack */ 53 | LDMIA R0!, {R4-R11, LR} 54 | 55 | #ifdef __ARMVFP__ 56 | /* Is thread using FPU? Yes, pop high VFP registers from stack */ 57 | TST LR, #0x10 58 | IT EQ 59 | VLDMIAEQ R0!, {S16-S31} 60 | #endif 61 | 62 | /* Restore PSP to high prio thread stack */ 63 | MSR PSP, R0 64 | 65 | /* Enable interrupts */ 66 | CPSIE I 67 | ISB 68 | 69 | /* Return */ 70 | BX LR 71 | 72 | END 73 | -------------------------------------------------------------------------------- /src/port/IAR/ARM_Cortex_M7/nOSPort.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2019 Jim Tremblay 3 | * 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | */ 8 | 9 | #define NOS_PRIVATE 10 | #include "nOS.h" 11 | 12 | #ifdef __cplusplus 13 | extern "C" { 14 | #endif 15 | 16 | static nOS_Stack _isrStack[NOS_CONFIG_ISR_STACK_SIZE]; 17 | 18 | void nOS_InitSpecific (void) 19 | { 20 | #if (NOS_CONFIG_DEBUG > 0) 21 | size_t i; 22 | 23 | for (i = 0; i < NOS_CONFIG_ISR_STACK_SIZE; i++) { 24 | _isrStack[i] = 0xFFFFFFFFUL; 25 | } 26 | #endif 27 | 28 | /* Copy MSP to PSP */ 29 | __set_PSP(__get_MSP()); 30 | /* Set MSP to local ISR stack */ 31 | __set_MSP((uint32_t)&_isrStack[NOS_CONFIG_ISR_STACK_SIZE] & 0xFFFFFFF8UL); 32 | /* Set current stack to PSP and privileged mode */ 33 | __set_CONTROL(__get_CONTROL() | 0x00000002UL); 34 | /* Set PendSV exception to lowest priority */ 35 | *(volatile uint32_t *)0xE000ED20UL |= 0x00FF0000UL; 36 | } 37 | 38 | void nOS_InitContext (nOS_Thread *thread, nOS_Stack *stack, size_t ssize, nOS_ThreadEntry entry, void *arg) 39 | { 40 | nOS_Stack *tos = (nOS_Stack*)((uint32_t)(stack + ssize) & 0xFFFFFFF8UL); 41 | #if (NOS_CONFIG_DEBUG > 0) 42 | size_t i; 43 | 44 | for (i = 0; i < ssize; i++) { 45 | stack[i] = 0xFFFFFFFFUL; 46 | } 47 | #endif 48 | 49 | *(--tos) = 0x01000000UL; /* xPSR */ 50 | *(--tos) = (nOS_Stack)entry;/* PC */ 51 | *(--tos) = 0x00000000UL; /* LR */ 52 | #if (NOS_CONFIG_DEBUG > 0) 53 | *(--tos) = 0x12121212UL; /* R12 */ 54 | *(--tos) = 0x03030303UL; /* R3 */ 55 | *(--tos) = 0x02020202UL; /* R2 */ 56 | *(--tos) = 0x01010101UL; /* R1 */ 57 | #else 58 | tos -= 4; /* R12, R3, R2 and R1 */ 59 | #endif 60 | *(--tos) = (nOS_Stack)arg; /* R0 */ 61 | *(--tos) = 0xFFFFFFFDUL; /* EXC_RETURN (Thread mode, Thread use PSP) */ 62 | #if (NOS_CONFIG_DEBUG > 0) 63 | *(--tos) = 0x11111111UL; /* R11 */ 64 | *(--tos) = 0x10101010UL; /* R10 */ 65 | *(--tos) = 0x09090909UL; /* R9 */ 66 | *(--tos) = 0x08080808UL; /* R8 */ 67 | *(--tos) = 0x07070707UL; /* R7 */ 68 | *(--tos) = 0x06060606UL; /* R6 */ 69 | *(--tos) = 0x05050505UL; /* R5 */ 70 | *(--tos) = 0x04040404UL; /* R4 */ 71 | #else 72 | tos -= 8; /* R11, R10, R9, R8, R7, R6, R5 and R4 */ 73 | #endif 74 | 75 | thread->stackPtr = tos; 76 | } 77 | 78 | void nOS_SwitchContext (void) 79 | { 80 | /* Request context switch */ 81 | *(volatile uint32_t *)0xE000ED04UL = 0x10000000UL; 82 | nOS_PeekCritical(); 83 | } 84 | 85 | void nOS_EnterISR (void) 86 | { 87 | nOS_StatusReg sr; 88 | 89 | #if (NOS_CONFIG_SAFE > 0) 90 | if (nOS_running) 91 | #endif 92 | { 93 | nOS_EnterCritical(sr); 94 | nOS_isrNestingCounter++; 95 | nOS_LeaveCritical(sr); 96 | } 97 | } 98 | 99 | void nOS_LeaveISR (void) 100 | { 101 | nOS_StatusReg sr; 102 | nOS_Thread *highPrioThread; 103 | 104 | #if (NOS_CONFIG_SAFE > 0) 105 | if (nOS_running) 106 | #endif 107 | { 108 | nOS_EnterCritical(sr); 109 | nOS_isrNestingCounter--; 110 | if (nOS_isrNestingCounter == 0) { 111 | #if (NOS_CONFIG_SCHED_LOCK_ENABLE > 0) 112 | if (nOS_lockNestingCounter == 0) 113 | #endif 114 | { 115 | highPrioThread = nOS_FindHighPrioThread(); 116 | if (highPrioThread != NULL) { 117 | #if (NOS_CONFIG_SCHED_PREEMPTIVE_ENABLE > 0) || (NOS_CONFIG_SCHED_ROUND_ROBIN_ENABLE > 0) 118 | nOS_highPrioThread = highPrioThread; 119 | if (nOS_runningThread != nOS_highPrioThread) { 120 | *(volatile uint32_t *)0xE000ED04UL = 0x10000000UL; 121 | } 122 | #endif 123 | } else if (nOS_runningThread != &nOS_mainHandle) { 124 | nOS_highPrioThread = &nOS_mainHandle; 125 | *(volatile uint32_t *)0xE000ED04UL = 0x10000000UL; 126 | } 127 | } 128 | } 129 | nOS_LeaveCritical(sr); 130 | } 131 | } 132 | 133 | #ifdef __cplusplus 134 | } 135 | #endif 136 | -------------------------------------------------------------------------------- /src/port/IAR/ARM_Cortex_M7/nOSPortASM.s: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2019 Jim Tremblay 3 | * 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | */ 8 | 9 | RSEG CODE:CODE(2) 10 | thumb 11 | 12 | EXTERN nOS_runningThread 13 | EXTERN nOS_highPrioThread 14 | 15 | PUBLIC PendSV_Handler 16 | 17 | PendSV_Handler: 18 | /* Disable interrupts */ 19 | CPSID I 20 | ISB 21 | 22 | /* Save PSP before doing anything, PendSV_Handler already running on MSP */ 23 | MRS R0, PSP 24 | 25 | /* Get the location of nOS_runningThread */ 26 | LDR R3, =nOS_runningThread 27 | LDR R2, [R3] 28 | 29 | #ifdef __ARMVFP__ 30 | /* Is thread using FPU? Yes, push high VFP registers to stack */ 31 | TST LR, #0x10 32 | IT EQ 33 | VSTMDBEQ R0!, {S16-S31} 34 | #endif 35 | 36 | /* Push remaining registers on thread stack */ 37 | STMDB R0!, {R4-R11, LR} 38 | 39 | /* Save PSP to nOS_Thread object of current running thread */ 40 | STR R0, [R2] 41 | 42 | /* Get the location of nOS_highPrioThread */ 43 | LDR R1, =nOS_highPrioThread 44 | LDR R2, [R1] 45 | 46 | /* Copy nOS_highPrioThread to nOS_runningThread */ 47 | STR R2, [R3] 48 | 49 | /* Restore PSP from nOS_Thread object of high prio thread */ 50 | LDR R0, [R2] 51 | 52 | /* Pop registers from thread stack */ 53 | LDMIA R0!, {R4-R11, LR} 54 | 55 | #ifdef __ARMVFP__ 56 | /* Is thread using FPU? Yes, pop high VFP registers from stack */ 57 | TST LR, #0x10 58 | IT EQ 59 | VLDMIAEQ R0!, {S16-S31} 60 | #endif 61 | 62 | /* Restore PSP to high prio thread stack */ 63 | MSR PSP, R0 64 | 65 | /* Enable interrupts */ 66 | CPSIE I 67 | ISB 68 | 69 | /* Return */ 70 | BX LR 71 | 72 | END 73 | -------------------------------------------------------------------------------- /src/port/IAR/AVR/nOSPort.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2019 Jim Tremblay 3 | * 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | */ 8 | 9 | #define NOS_PRIVATE 10 | #include "nOS.h" 11 | 12 | #ifdef __cplusplus 13 | extern "C" { 14 | #endif 15 | 16 | void nOS_InitContext (nOS_Thread *thread, nOS_Stack *stack, size_t ssize, size_t cssize, nOS_ThreadEntry entry, void *arg) 17 | { 18 | /* Stack grow from high to low address */ 19 | nOS_Stack *tocs = stack + (ssize - 1); 20 | nOS_Stack *tos; 21 | #if (NOS_CONFIG_DEBUG > 0) 22 | size_t i; 23 | 24 | for (i = 0; i < ssize; i++) { 25 | stack[i] = 0xFF; 26 | } 27 | #endif 28 | 29 | #if defined(__ATmega2560__) || defined(__ATmega2561__) 30 | tos = tocs - (cssize * 3); 31 | #else 32 | tos = tocs - (cssize * 2); 33 | #endif 34 | 35 | /* Simulate a call to thread function */ 36 | #if defined(__ATmega2560__) || defined(__ATmega2561__) 37 | *tocs-- = (nOS_Stack)((uint32_t)entry); 38 | *tocs-- = (nOS_Stack)((uint32_t)entry >> 8); 39 | *tocs-- = (nOS_Stack)((uint32_t)entry >> 16); 40 | #else 41 | *tocs-- = (nOS_Stack)((uint16_t)entry); 42 | *tocs-- = (nOS_Stack)((uint16_t)entry >> 8); 43 | #endif 44 | 45 | /* Simulate a call of nOS_PushContext */ 46 | #if (NOS_CONFIG_DEBUG > 0) 47 | *tos-- = 0x00; /* R0 */ 48 | #else 49 | tos -= 1; /* R0 */ 50 | #endif 51 | *tos-- = 0x80; /* SREG: Interrupts enabled */ 52 | *tos-- = (nOS_Stack)((uint16_t)tocs); /* R28 */ 53 | *tos-- = (nOS_Stack)((uint16_t)tocs >> 8); /* R29 */ 54 | #ifdef __HAS_RAMPZ__ 55 | tos -= 1; /* RAMPZ */ 56 | #endif 57 | #if defined(__ATmega2560__) || defined(__ATmega2561__) 58 | tos -= 1; /* EIND */ 59 | #endif 60 | #if (NOS_CONFIG_DEBUG > 0) 61 | *tos-- = 0x01; /* R1 */ 62 | *tos-- = 0x02; /* R2 */ 63 | *tos-- = 0x03; /* R3 */ 64 | *tos-- = 0x04; /* R4 */ 65 | *tos-- = 0x05; /* R5 */ 66 | *tos-- = 0x06; /* R6 */ 67 | *tos-- = 0x07; /* R7 */ 68 | *tos-- = 0x08; /* R8 */ 69 | *tos-- = 0x09; /* R9 */ 70 | *tos-- = 0x10; /* R10 */ 71 | *tos-- = 0x11; /* R11 */ 72 | *tos-- = 0x12; /* R12 */ 73 | *tos-- = 0x13; /* R13 */ 74 | *tos-- = 0x14; /* R14 */ 75 | *tos-- = 0x15; /* R15 */ 76 | #else 77 | tos -= 15; /* R1 to R15 */ 78 | #endif 79 | *tos-- = (nOS_Stack)((uint16_t)arg); /* R16: arg LSB */ 80 | *tos-- = (nOS_Stack)((uint16_t)arg >> 8); /* R17: arg MSB */ 81 | #if (NOS_CONFIG_DEBUG > 0) 82 | *tos-- = 0x18; /* R18 */ 83 | *tos-- = 0x19; /* R19 */ 84 | *tos-- = 0x20; /* R20 */ 85 | *tos-- = 0x21; /* R21 */ 86 | *tos-- = 0x22; /* R22 */ 87 | *tos-- = 0x23; /* R23 */ 88 | *tos-- = 0x24; /* R24 */ 89 | *tos-- = 0x25; /* R25 */ 90 | *tos-- = 0x26; /* R26 */ 91 | *tos-- = 0x27; /* R27 */ 92 | *tos-- = 0x30; /* R30 */ 93 | *tos = 0x31; /* R31 */ 94 | #else 95 | tos -= 11; /* R18 to R27, R30, R31 */ 96 | #endif 97 | 98 | thread->stackPtr = tos; 99 | } 100 | 101 | /* Absolutely need a naked function because function call push the return address on the stack */ 102 | __task void nOS_SwitchContext (void) 103 | { 104 | PUSH_CONTEXT(); 105 | __asm ( 106 | "lds r26, nOS_runningThread \n" 107 | "lds r27, nOS_runningThread + 1 \n" 108 | "st x+, r28 \n" 109 | "st x+, r29 \n" 110 | ); 111 | nOS_runningThread = nOS_highPrioThread; 112 | __asm ( 113 | "lds r26, nOS_highPrioThread \n" 114 | "lds r27, nOS_highPrioThread + 1 \n" 115 | "ld r28, x+ \n" 116 | "ld r29, x+ \n" 117 | ); 118 | POP_CONTEXT(); 119 | } 120 | 121 | void nOS_EnterISR (nOS_Stack *sp) 122 | { 123 | #if (NOS_CONFIG_SAFE > 0) 124 | if (nOS_running) 125 | #endif 126 | { 127 | /* Interrupts already disabled when entering in ISR */ 128 | if (nOS_isrNestingCounter == 0) { 129 | nOS_runningThread->stackPtr = sp; 130 | } 131 | nOS_isrNestingCounter++; 132 | } 133 | } 134 | 135 | nOS_Stack *nOS_LeaveISR (nOS_Stack *sp) 136 | { 137 | #if (NOS_CONFIG_SAFE > 0) 138 | if (nOS_running) 139 | #endif 140 | { 141 | /* Interrupts already disabled before leaving ISR */ 142 | nOS_isrNestingCounter--; 143 | if (nOS_isrNestingCounter == 0) { 144 | #if (NOS_CONFIG_SCHED_LOCK_ENABLE > 0) 145 | if (nOS_lockNestingCounter == 0) 146 | #endif 147 | { 148 | highPrioThread = nOS_FindHighPrioThread(); 149 | if (highPrioThread != NULL) { 150 | #if (NOS_CONFIG_SCHED_PREEMPTIVE_ENABLE > 0) || (NOS_CONFIG_SCHED_ROUND_ROBIN_ENABLE > 0) 151 | nOS_highPrioThread = highPrioThread; 152 | nOS_runningThread = nOS_highPrioThread; 153 | #endif 154 | } else { 155 | nOS_highPrioThread = &nOS_mainHandle; 156 | nOS_runningThread = nOS_highPrioThread; 157 | } 158 | } 159 | sp = nOS_runningThread->stackPtr; 160 | } 161 | } 162 | return sp; 163 | } 164 | 165 | #ifdef __cplusplus 166 | } 167 | #endif 168 | -------------------------------------------------------------------------------- /src/port/IAR/M16C_R8C/nOSPort.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2019 Jim Tremblay 3 | * 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | */ 8 | 9 | #define NOS_PRIVATE 10 | #include "nOS.h" 11 | 12 | #ifdef __cplusplus 13 | extern "C" { 14 | #endif 15 | 16 | void nOS_InitContext (nOS_Thread *thread, nOS_Stack *stack, size_t ssize, nOS_ThreadEntry entry, void *arg) 17 | { 18 | nOS_Stack *tos = (nOS_Stack*)((uint16_t)(stack + ssize) & 0xFFFE); 19 | #if (NOS_CONFIG_DEBUG > 0) 20 | size_t i; 21 | 22 | for (i = 0; i < ssize; i++) { 23 | stack[i] = 0xFFFF; 24 | } 25 | #endif 26 | 27 | /* FLG = 0x0C0 = interrupts enabled, USP stack pointer */ 28 | *(--tos) = (((uint32_t)entry >> 8) & 0x0F00) | 0x00C0; 29 | *(--tos) = (nOS_Stack)((uint32_t)entry); 30 | 31 | #if (NOS_CONFIG_DEBUG > 0) 32 | *(--tos) = 0xFFFF; /* FB */ 33 | *(--tos) = 0xCCCC; /* SB */ 34 | *(--tos) = 0xBBBB; /* A1 */ 35 | #else 36 | tos -= 3; /* FB, SB, A1 */ 37 | #endif 38 | *(--tos) = (nOS_Stack)arg; /* A0 */ 39 | #if (NOS_CONFIG_DEBUG > 0) 40 | *(--tos) = 0x4444; /* R3 */ 41 | *(--tos) = 0x3333; /* R2 */ 42 | *(--tos) = 0x2222; /* R1 */ 43 | *(--tos) = 0x1111; /* R0 */ 44 | #else 45 | tos -= 4; /* R3, R2, R1, R0 */ 46 | #endif 47 | 48 | thread->stackPtr = tos; 49 | } 50 | 51 | void nOS_EnterISR (void) 52 | { 53 | nOS_StatusReg sr; 54 | 55 | #if (NOS_CONFIG_SAFE > 0) 56 | if (nOS_running) 57 | #endif 58 | { 59 | nOS_EnterCritical(sr); 60 | nOS_isrNestingCounter++; 61 | nOS_LeaveCritical(sr); 62 | } 63 | } 64 | 65 | bool nOS_LeaveISR (void) 66 | { 67 | nOS_StatusReg sr; 68 | bool swctx = false; 69 | nOS_Thread *highPrioThread; 70 | 71 | #if (NOS_CONFIG_SAFE > 0) 72 | if (nOS_running) 73 | #endif 74 | { 75 | nOS_EnterCritical(sr); 76 | nOS_isrNestingCounter--; 77 | if (nOS_isrNestingCounter == 0) { 78 | #if (NOS_CONFIG_SCHED_LOCK_ENABLE > 0) 79 | if (nOS_lockNestingCounter == 0) 80 | #endif 81 | { 82 | highPrioThread = nOS_FindHighPrioThread(); 83 | if (highPrioThread != NULL) { 84 | #if (NOS_CONFIG_SCHED_PREEMPTIVE_ENABLE > 0) || (NOS_CONFIG_SCHED_ROUND_ROBIN_ENABLE > 0) 85 | nOS_highPrioThread = highPrioThread; 86 | if (nOS_runningThread != nOS_highPrioThread) { 87 | swctx = true; 88 | } 89 | #endif 90 | } else if (nOS_runningThread != &nOS_mainHandle) { 91 | nOS_highPrioThread = &nOS_mainHandle; 92 | swctx = true; 93 | } 94 | } 95 | } 96 | nOS_LeaveCritical(sr); 97 | } 98 | return swctx; 99 | } 100 | 101 | #pragma vector = 0x20 102 | __interrupt void nOS_SwitchContextHandler (void) 103 | { 104 | __asm ( 105 | /* Push all registers on thread stack */ 106 | "PUSHM R0,R1,R2,R3,A0,A1,SB,FB \n" 107 | 108 | /* Save SP to nOS_Thread object of current running thread */ 109 | "MOV.W nOS_runningThread, A0 \n" 110 | "STC SP, [A0] \n" 111 | 112 | /* Copy nOS_highPrioThread to nOS_runningThread */ 113 | "MOV.W nOS_highPrioThread, nOS_runningThread \n" 114 | 115 | /* Restore SP from nOS_Thread object of high prio thread */ 116 | "MOV.W nOS_highPrioThread, A0 \n" 117 | "LDC [A0], SP \n" 118 | 119 | /* Pop all registers from thread stack */ 120 | "POPM R0,R1,R2,R3,A0,A1,SB,FB \n" 121 | ); 122 | } 123 | 124 | #pragma vector = 0x21 125 | __interrupt void nOS_SwitchContextFromIsrHandler (void) 126 | { 127 | __asm ( 128 | /* Push all registers on thread stack */ 129 | "PUSHM R0,R1,R2,R3,A0,A1,SB,FB \n" 130 | 131 | /* Move PC and FLG from ISTACK to USTACK */ 132 | "STC ISP, A0 \n" 133 | "MOV.W 0[A0], 16[SP] \n" 134 | "MOV.W 2[A0], 18[SP] \n" 135 | 136 | /* Adjust ISTACK (remove PC and FLG) */ 137 | "ADD.W #4, A0 \n" 138 | "LDC A0, ISP \n" 139 | 140 | /* Save SP to nOS_Thread object of current running thread */ 141 | "MOV.W nOS_runningThread, A0 \n" 142 | "STC SP, [A0] \n" 143 | 144 | /* Copy nOS_highPrioThread to nOS_runningThread */ 145 | "MOV.W nOS_highPrioThread, nOS_runningThread \n" 146 | 147 | /* Restore SP from nOS_Thread object of high prio thread */ 148 | "MOV.W nOS_highPrioThread, A0 \n" 149 | "LDC [A0], SP \n" 150 | 151 | /* Pop all registers from thread stack */ 152 | "POPM R0,R1,R2,R3,A0,A1,SB,FB \n" 153 | ); 154 | } 155 | 156 | #ifdef __cplusplus 157 | } 158 | #endif 159 | -------------------------------------------------------------------------------- /src/port/IAR/MSP430/nOSPort.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2019 Jim Tremblay 3 | * 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | */ 8 | 9 | #define NOS_PRIVATE 10 | #include "nOS.h" 11 | 12 | #ifdef __cplusplus 13 | extern "C" { 14 | #endif 15 | 16 | #ifdef NOS_CONFIG_ISR_STACK_SIZE 17 | static nOS_Stack _isrStack[NOS_CONFIG_ISR_STACK_SIZE]; 18 | #endif 19 | 20 | void nOS_InitContext (nOS_Thread *thread, nOS_Stack *stack, size_t ssize, nOS_ThreadEntry entry, void *arg) 21 | { 22 | /* Stack grow from high to low address */ 23 | nOS_Stack *tos = stack + (ssize - 1); 24 | uint16_t *tos16; 25 | #if (NOS_CONFIG_DEBUG > 0) 26 | size_t i; 27 | 28 | for (i = 0; i < ssize; i++) { 29 | stack[i] = 0xFFFFFFFF; 30 | } 31 | #endif 32 | 33 | tos16 = (uint16_t*)tos; 34 | #if (__CORE__ == __430X__) 35 | *tos16-- = (uint16_t)((uint32_t)entry >> 16); /* PC MSB */ 36 | #endif 37 | *tos16-- = (uint16_t)((uint32_t)entry); /* PC LSB */ 38 | *tos16-- = 0x0008; /* SR */ 39 | #if (__CORE__ == __430X__) && ((__DATA_MODEL__ == __DATA_MODEL_MEDIUM__) || (__DATA_MODEL__ == __DATA_MODEL_LARGE__)) 40 | tos16 -= 1; 41 | #endif 42 | tos = (nOS_Stack*)tos16; 43 | 44 | #if (NOS_CONFIG_DEBUG > 0) 45 | *tos-- = (nOS_Stack)0x15151515; /* R15 */ 46 | *tos-- = (nOS_Stack)0x14141414; /* R14 */ 47 | *tos-- = (nOS_Stack)0x13131313; /* R13 */ 48 | #else 49 | tos -= 3; /* R15 to R13 */ 50 | #endif 51 | *tos-- = (nOS_Stack)arg; /* R12 */ 52 | #if (NOS_CONFIG_DEBUG > 0) 53 | *tos-- = (nOS_Stack)0x11111111; /* R11 */ 54 | *tos-- = (nOS_Stack)0x10101010; /* R10 */ 55 | *tos-- = (nOS_Stack)0x09090909; /* R9 */ 56 | *tos-- = (nOS_Stack)0x08080808; /* R8 */ 57 | *tos-- = (nOS_Stack)0x07070707; /* R7 */ 58 | *tos-- = (nOS_Stack)0x06060606; /* R6 */ 59 | *tos-- = (nOS_Stack)0x05050505; /* R5 */ 60 | *tos = (nOS_Stack)0x04040404; /* R4 */ 61 | #else 62 | tos -= 7; /* R11 to R4 */ 63 | #endif 64 | 65 | thread->stackPtr = tos; 66 | } 67 | 68 | __task void nOS_SwitchContext (void) 69 | { 70 | __asm ( 71 | /* Simulate an interrupt by pushing SR */ 72 | PUSH_SR 73 | " \n" 74 | /* Save all registers to running thread stack */ 75 | PUSH_CONTEXT 76 | " \n" 77 | /* Save stack pointer to running thread structure */ 78 | MOV_X" &nOS_runningThread, R12 \n" 79 | MOV_X" SP, 0(R12) \n" 80 | " \n" 81 | /* Copy nOS_highPrioThread to nOS_runningThread */ 82 | MOV_X" &nOS_highPrioThread, R12 \n" 83 | MOV_X" #nOS_runningThread, R11 \n" 84 | MOV_X" R12, 0(R11) \n" 85 | " \n" 86 | /* Restore stack pointer from high prio thread structure */ 87 | MOV_X" @R12, SP \n" 88 | " \n" 89 | /* Pop all registers from high prio thread stack */ 90 | POP_CONTEXT 91 | " \n" 92 | POP_SR 93 | RET_X 94 | ); 95 | } 96 | 97 | nOS_Stack* nOS_EnterISR (nOS_Stack *sp) 98 | { 99 | nOS_StatusReg sr; 100 | 101 | #if (NOS_CONFIG_SAFE > 0) 102 | if (nOS_running) 103 | #endif 104 | { 105 | nOS_EnterCritical(sr); 106 | if (nOS_isrNestingCounter == 0) { 107 | nOS_runningThread->stackPtr = sp; 108 | #ifdef NOS_CONFIG_ISR_STACK_SIZE 109 | sp = &_isrStack[NOS_CONFIG_ISR_STACK_SIZE-1]; 110 | #else 111 | sp = nOS_mainHandle.stackPtr; 112 | #endif 113 | } 114 | nOS_isrNestingCounter++; 115 | nOS_LeaveCritical(sr); 116 | } 117 | 118 | return sp; 119 | } 120 | 121 | nOS_Stack* nOS_LeaveISR (nOS_Stack *sp) 122 | { 123 | nOS_StatusReg sr; 124 | nOS_Thread *highPrioThread; 125 | 126 | #if (NOS_CONFIG_SAFE > 0) 127 | if (nOS_running) 128 | #endif 129 | { 130 | nOS_EnterCritical(sr); 131 | nOS_isrNestingCounter--; 132 | if (nOS_isrNestingCounter == 0) { 133 | #if (NOS_CONFIG_SCHED_LOCK_ENABLE > 0) 134 | if (nOS_lockNestingCounter == 0) 135 | #endif 136 | { 137 | highPrioThread = nOS_FindHighPrioThread(); 138 | if (highPrioThread != NULL) { 139 | #if (NOS_CONFIG_SCHED_PREEMPTIVE_ENABLE > 0) || (NOS_CONFIG_SCHED_ROUND_ROBIN_ENABLE > 0) 140 | nOS_highPrioThread = highPrioThread; 141 | #endif 142 | } else if (nOS_runningThread != &nOS_mainHandle) { 143 | nOS_highPrioThread = &nOS_mainHandle; 144 | } 145 | nOS_runningThread = nOS_highPrioThread; 146 | } 147 | sp = nOS_runningThread->stackPtr; 148 | } 149 | nOS_LeaveCritical(sr); 150 | } 151 | return sp; 152 | } 153 | 154 | #ifdef __cplusplus 155 | } 156 | #endif 157 | -------------------------------------------------------------------------------- /src/port/IAR/RX600/nOSPort.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2019 Jim Tremblay 3 | * 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | */ 8 | 9 | #define NOS_PRIVATE 10 | #include "nOS.h" 11 | 12 | #ifdef __cplusplus 13 | extern "C" { 14 | #endif 15 | 16 | static nOS_Stack _isrStack[NOS_CONFIG_ISR_STACK_SIZE]; 17 | 18 | void nOS_InitSpecific (void) 19 | { 20 | nOS_Stack *sp = &_isrStack[NOS_CONFIG_ISR_STACK_SIZE-1]; 21 | uint32_t reg; 22 | #if (NOS_CONFIG_DEBUG > 0) 23 | size_t i; 24 | 25 | for (i = 0; i < NOS_CONFIG_ISR_STACK_SIZE; i++) { 26 | _isrStack[i] = 0xFFFFFFFFUL; 27 | } 28 | #endif 29 | 30 | __asm volatile ( 31 | /* Set USP to current value of ISP */ 32 | "MVFC ISP, %[reg] \n" 33 | "MVTC %[reg], USP \n" 34 | /* Set ISP to local ISR stack */ 35 | "MVTC %[sp], ISP \n" 36 | /* Set current stack used to USP */ 37 | "SETPSW U \n" 38 | : [reg] "=r" (reg) 39 | : [reg] "r" (reg), [sp] "r" ((uint32_t)sp) 40 | ); 41 | 42 | /* Enable software interrupt */ 43 | *(uint8_t*)0x00087203UL |= (uint8_t)0x08; 44 | /* Clear software interrupt */ 45 | *(uint8_t*)0x00087003UL &=~ (uint8_t)0x08; 46 | /* Set software interrupt to lowest priority level */ 47 | *(uint8_t*)0x00087303UL = (uint8_t)1; 48 | } 49 | 50 | void nOS_InitContext (nOS_Thread *thread, nOS_Stack *stack, size_t ssize, nOS_ThreadEntry entry, void *arg) 51 | { 52 | nOS_Stack *tos = (stack + (ssize - 1)); 53 | #if (NOS_CONFIG_DEBUG > 0) 54 | size_t i; 55 | 56 | for (i = 0; i < ssize; i++) { 57 | stack[i] = 0xFFFFFFFFUL; 58 | } 59 | #endif 60 | 61 | *tos-- = 0x00030000UL; /* Interrupts enabled, User stack selected, Supervisor mode */ 62 | *tos-- = (nOS_Stack)entry; 63 | #if (NOS_CONFIG_DEBUG > 0) 64 | *tos-- = 0x15151515UL; 65 | *tos-- = 0x14141414UL; 66 | *tos-- = 0x13131313UL; 67 | *tos-- = 0x12121212UL; 68 | *tos-- = 0x11111111UL; 69 | *tos-- = 0x10101010UL; 70 | *tos-- = 0x09090909UL; 71 | *tos-- = 0x08080808UL; 72 | *tos-- = 0x07070707UL; 73 | *tos-- = 0x06060606UL; 74 | *tos-- = 0x05050505UL; 75 | *tos-- = 0x04040404UL; 76 | *tos-- = 0x03030303UL; 77 | *tos-- = 0x02020202UL; 78 | #else 79 | tos -= 14; 80 | #endif 81 | *tos-- = (nOS_Stack)arg; 82 | *tos-- = 0x00000100UL; /* Floating-point status word (default) */ 83 | #if (NOS_CONFIG_DEBUG > 0) 84 | *tos-- = 0x01234567UL; /* Accumulator high */ 85 | *tos = 0x89abcdefUL; /* Accumulator low */ 86 | #else 87 | tos -= 1; 88 | #endif 89 | 90 | thread->stackPtr = tos; 91 | } 92 | 93 | void nOS_EnterISR (void) 94 | { 95 | nOS_StatusReg sr; 96 | 97 | #if (NOS_CONFIG_SAFE > 0) 98 | if (nOS_running) 99 | #endif 100 | { 101 | nOS_EnterCritical(sr); 102 | nOS_isrNestingCounter++; 103 | nOS_LeaveCritical(sr); 104 | } 105 | } 106 | 107 | void nOS_LeaveISR (void) 108 | { 109 | nOS_StatusReg sr; 110 | nOS_Thread *highPrioThread; 111 | 112 | #if (NOS_CONFIG_SAFE > 0) 113 | if (nOS_running) 114 | #endif 115 | { 116 | nOS_EnterCritical(sr); 117 | nOS_isrNestingCounter--; 118 | if (nOS_isrNestingCounter == 0) { 119 | #if (NOS_CONFIG_SCHED_LOCK_ENABLE > 0) 120 | if (nOS_lockNestingCounter == 0) 121 | #endif 122 | { 123 | highPrioThread = nOS_FindHighPrioThread(); 124 | if (highPrioThread != NULL) { 125 | #if (NOS_CONFIG_SCHED_PREEMPTIVE_ENABLE > 0) || (NOS_CONFIG_SCHED_ROUND_ROBIN_ENABLE > 0) 126 | nOS_highPrioThread = highPrioThread; 127 | if (nOS_runningThread != nOS_highPrioThread) { 128 | /* Request a software interrupt when going out of ISR */ 129 | *(uint8_t*)0x000872E0UL = (uint8_t)1; 130 | } 131 | #endif 132 | } else if (nOS_runningThread != &nOS_mainHandle) { 133 | nOS_highPrioThread = &nOS_mainHandle; 134 | /* Return to main thread when going out of ISR */ 135 | *(uint8_t*)0x000872E0UL = (uint8_t)1; 136 | } 137 | } 138 | } 139 | nOS_LeaveCritical(sr); 140 | } 141 | } 142 | 143 | #ifdef __cplusplus 144 | } 145 | #endif 146 | -------------------------------------------------------------------------------- /src/port/IAR/RX600/nOSPortASM.s: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2019 Jim Tremblay 3 | * 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | */ 8 | 9 | PUBLIC ___interrupt_27 10 | 11 | EXTERN _nOS_runningThread 12 | EXTERN _nOS_highPrioThread 13 | 14 | RSEG CODE:CODE(4) 15 | 16 | ___interrupt_27: 17 | /* Push R15 on ISP (we will use it) */ 18 | PUSH.L R15 19 | 20 | /* Get running thread stack and adjust it to contains PSW, PC and R15 */ 21 | MVFC USP, R15 22 | SUB #12, R15 23 | 24 | /* Set USP to adjusted value */ 25 | MVTC R15, USP 26 | 27 | /* Moved pushed registers from ISP to running thread stack */ 28 | MOV.L [SP], [R15] 29 | MOV.L 4[SP], 4[R15] 30 | MOV.L 8[SP], 8[R15] 31 | 32 | /* Adjust ISP (Remove R15, PC and PSW from the stack) */ 33 | ADD #12, SP 34 | 35 | /* At this point, we can continue on USP */ 36 | SETPSW U 37 | 38 | /* Push all remaining registers to running thread stack */ 39 | PUSHM R1-R14 40 | 41 | /* Push floating-point status register to running thread stack */ 42 | PUSHC FPSW 43 | 44 | /* Push accumulator register to running thread stack */ 45 | MVFACHI R15 46 | MVFACMI R14 47 | SHLL #16, R14 48 | PUSHM R14-R15 49 | 50 | /* Save SP in nOS_runningThread object */ 51 | MOV.L #_nOS_runningThread, R15 52 | MOV.L [R15], R14 53 | MOV.L SP, [R14] 54 | 55 | /* nOS_runningThread = nOS_highPrioThread */ 56 | MOV.L #_nOS_highPrioThread, R14 57 | MOV.L [R14], [R15] 58 | 59 | /* Restore SP from nOS_highPrioThread object */ 60 | MOV.L [R14], R15 61 | MOV.L [R15], SP 62 | 63 | /* Pop accumulator register from high prio thread stack */ 64 | POPM R14-R15 65 | MVTACLO R14 66 | MVTACHI R15 67 | 68 | /* Pop floating-point status register from high prio thread stack */ 69 | POPC FPSW 70 | 71 | /* Pop all registers from high prio thread stack */ 72 | POPM R1-R15 73 | 74 | /* Return from interrupt (will pop PC and PSW) */ 75 | RTE 76 | NOP 77 | NOP 78 | 79 | END 80 | -------------------------------------------------------------------------------- /src/port/IAR/STM8/nOSPort.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2019 Jim Tremblay 3 | * 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | */ 8 | 9 | #define NOS_PRIVATE 10 | #include "nOS.h" 11 | 12 | #ifdef __cplusplus 13 | extern "C" { 14 | #endif 15 | 16 | #ifdef NOS_CONFIG_ISR_STACK_SIZE 17 | static nOS_Stack _isrStack[NOS_CONFIG_ISR_STACK_SIZE]; 18 | #endif 19 | 20 | void nOS_InitSpecific (void) 21 | { 22 | #ifdef NOS_CONFIG_ISR_STACK_SIZE 23 | #if (NOS_CONFIG_DEBUG > 0) 24 | size_t i; 25 | 26 | for (i = 0; i < NOS_CONFIG_ISR_STACK_SIZE; i++) { 27 | _isrStack[i] = 0xFF; 28 | } 29 | #endif 30 | #endif 31 | } 32 | 33 | void nOS_InitContext (nOS_Thread *thread, nOS_Stack *stack, size_t ssize, nOS_ThreadEntry entry, void *arg) 34 | { 35 | /* Stack grow from high to low address */ 36 | nOS_Stack *tos = stack + (ssize - 1); 37 | #if (NOS_CONFIG_DEBUG > 0) 38 | size_t i; 39 | 40 | for (i = 0; i < ssize; i++) { 41 | stack[i] = 0xFF; 42 | } 43 | #endif 44 | 45 | /* Simulate a call to thread function */ 46 | #if (__CODE_MODEL__ != __SMALL_CODE_MODEL__) 47 | /* Function pointers size is 3 bytes */ 48 | *tos-- = (nOS_Stack)((uint32_t)entry); 49 | *tos-- = (nOS_Stack)((uint32_t)entry >> 8); 50 | *tos-- = (nOS_Stack)((uint32_t)entry >> 16); 51 | #else 52 | /* Function pointers size is 2 bytes */ 53 | *tos-- = (nOS_Stack)((uint16_t)entry); 54 | *tos-- = (nOS_Stack)((uint16_t)entry >> 8); 55 | #endif 56 | 57 | /* Simulate a call of nOS_PushContext */ 58 | #if (NOS_CONFIG_DEBUG > 0) 59 | *tos-- = 'y'; /* YL */ 60 | *tos-- = 'Y'; /* YH */ 61 | #else 62 | tos -= 2; /* Y */ 63 | #endif 64 | #if (__DATA_MODEL__ == __MEDIUM_DATA_MODEL__) 65 | /* Pointers size is 2 bytes */ 66 | *tos-- = (nOS_Stack)((uint16_t)arg); /* XL: arg LSB */ 67 | *tos-- = (nOS_Stack)((uint16_t)arg >> 8); /* XH: arg MSB */ 68 | #else 69 | #if (NOS_CONFIG_DEBUG > 0) 70 | *tos-- = 'x'; /* XL */ 71 | *tos-- = 'X'; /* XH */ 72 | #else 73 | tos -= 2; /* X */ 74 | #endif 75 | #endif 76 | #if (NOS_CONFIG_DEBUG > 0) 77 | *tos-- = 'A'; /* A */ 78 | #else 79 | tos -= 1; /* A */ 80 | #endif 81 | *tos-- = 0x20; /* CC: Interrupt enabled */ 82 | #if (NOS_CONFIG_DEBUG > 0) 83 | *tos-- = 0x00; /* ?b0 */ 84 | #else 85 | tos -= 1; /* ?b0 */ 86 | #endif 87 | #if (__DATA_MODEL__ == __LARGE_DATA_MODEL__) 88 | /* Pointers size is 3 bytes */ 89 | *tos-- = (nOS_Stack)((uint32_t)arg >> 16); /* ?b1 arg MSB */ 90 | *tos-- = (nOS_Stack)((uint32_t)arg >> 8); /* ?b2 ... */ 91 | *tos-- = (nOS_Stack)((uint32_t)arg); /* ?b3 arg LSB */ 92 | #else 93 | #if (NOS_CONFIG_DEBUG > 0) 94 | *tos-- = 0x01; /* ?b1 */ 95 | *tos-- = 0x02; /* ?b2 */ 96 | *tos-- = 0x03; /* ?b3 */ 97 | #else 98 | tos -= 3; /* ?b1 to ?b3 */ 99 | #endif 100 | #endif 101 | #if (NOS_CONFIG_DEBUG > 0) 102 | *tos-- = 0x04; /* ?b4 */ 103 | *tos-- = 0x05; /* ?b5 */ 104 | *tos-- = 0x06; /* ?b6 */ 105 | *tos-- = 0x07; /* ?b7 */ 106 | *tos-- = 0x08; /* ?b8 */ 107 | *tos-- = 0x09; /* ?b9 */ 108 | *tos-- = 0x10; /* ?b10 */ 109 | *tos-- = 0x11; /* ?b11 */ 110 | *tos-- = 0x12; /* ?b12 */ 111 | *tos-- = 0x13; /* ?b13 */ 112 | *tos-- = 0x14; /* ?b14 */ 113 | *tos-- = 0x15; /* ?b15 */ 114 | #else 115 | tos -= 12; /* ?b4 to ?b15 */ 116 | #endif 117 | 118 | thread->stackPtr = tos; 119 | } 120 | 121 | /* Declare this function as __task; we don't need the compiler to push registers on the stack since we do it manually */ 122 | __task void nOS_SwitchContext (void) 123 | { 124 | PUSH_CONTEXT(); 125 | nOS_runningThread->stackPtr = (nOS_Stack*)__get_cpu_sp(); 126 | nOS_runningThread = nOS_highPrioThread; 127 | #if (__DATA_MODEL__ == __MEDIUM_DATA_MODEL__) 128 | __set_cpu_sp((int)nOS_highPrioThread->stackPtr); 129 | #elif (__DATA_MODEL__ == __LARGE_DATA_MODEL__) 130 | __set_cpu_sp((int)((long)nOS_highPrioThread->stackPtr)); 131 | #endif 132 | POP_CONTEXT(); 133 | } 134 | 135 | nOS_Stack *nOS_EnterISR (nOS_Stack *sp) 136 | { 137 | #if (NOS_CONFIG_SAFE > 0) 138 | if (nOS_running) 139 | #endif 140 | { 141 | /* Interrupts already disabled when entering in ISR */ 142 | if (nOS_isrNestingCounter == 0) { 143 | nOS_runningThread->stackPtr = sp; 144 | #ifdef NOS_CONFIG_ISR_STACK_SIZE 145 | sp = &_isrStack[NOS_CONFIG_ISR_STACK_SIZE-1]; 146 | #else 147 | sp = nOS_mainHandle.stackPtr; 148 | #endif 149 | } 150 | nOS_isrNestingCounter++; 151 | } 152 | 153 | return sp; 154 | } 155 | 156 | nOS_Stack *nOS_LeaveISR (nOS_Stack *sp) 157 | { 158 | #if (NOS_CONFIG_SAFE > 0) 159 | if (nOS_running) 160 | #endif 161 | { 162 | /* Interrupts already disabled before leaving ISR */ 163 | nOS_isrNestingCounter--; 164 | if (nOS_isrNestingCounter == 0) { 165 | #if (NOS_CONFIG_SCHED_LOCK_ENABLE > 0) 166 | if (nOS_lockNestingCounter == 0) 167 | #endif 168 | { 169 | highPrioThread = nOS_FindHighPrioThread(); 170 | if (highPrioThread != NULL) { 171 | #if (NOS_CONFIG_SCHED_PREEMPTIVE_ENABLE > 0) || (NOS_CONFIG_SCHED_ROUND_ROBIN_ENABLE > 0) 172 | nOS_highPrioThread = highPrioThread; 173 | nOS_runningThread = nOS_highPrioThread; 174 | #endif 175 | } else { 176 | nOS_highPrioThread = &nOS_mainHandle; 177 | nOS_runningThread = nOS_highPrioThread; 178 | } 179 | } 180 | sp = nOS_runningThread->stackPtr; 181 | } 182 | } 183 | 184 | return sp; 185 | } 186 | 187 | #ifdef __cplusplus 188 | } 189 | #endif 190 | -------------------------------------------------------------------------------- /src/port/IAR/STM8/nOSPortASM.s: -------------------------------------------------------------------------------- 1 | name nOSPortASM 2 | 3 | public __set_cpu_sp 4 | public __get_cpu_sp 5 | 6 | section .near.bss:DATA 7 | 8 | PCL DS8 1 9 | PCH DS8 1 10 | #if (__CODE_MODEL__ != __SMALL_CODE_MODEL__) 11 | PCE DS8 1 12 | #endif 13 | 14 | section .near_func.text:CODE 15 | 16 | pop_pc macro 17 | #if (__CODE_MODEL__ != __SMALL_CODE_MODEL__) 18 | pop PCE 19 | #endif 20 | pop PCH 21 | pop PCL 22 | endm 23 | 24 | push_pc macro 25 | push PCL 26 | push PCH 27 | #if (__CODE_MODEL__ != __SMALL_CODE_MODEL__) 28 | push PCE 29 | #endif 30 | endm 31 | 32 | __set_cpu_sp: 33 | pop_pc 34 | ldw SP, X 35 | push_pc 36 | #if (__CODE_MODEL__ != __SMALL_CODE_MODEL__) 37 | retf 38 | #else 39 | ret 40 | #endif 41 | 42 | __get_cpu_sp: 43 | ldw X, SP 44 | #if (__CODE_MODEL__ != __SMALL_CODE_MODEL__) 45 | addw X, #$3 46 | retf 47 | #else 48 | addw X, #$2 49 | ret 50 | #endif 51 | 52 | end 53 | -------------------------------------------------------------------------------- /src/port/Keil/ARM_Cortex_M0/nOSPort.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2019 Jim Tremblay 3 | * 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | */ 8 | 9 | #define NOS_PRIVATE 10 | #include "nOS.h" 11 | 12 | #ifdef __cplusplus 13 | extern "C" { 14 | #endif 15 | 16 | static nOS_Stack _isrStack[NOS_CONFIG_ISR_STACK_SIZE]; 17 | 18 | void nOS_InitSpecific (void) 19 | { 20 | #if (NOS_CONFIG_DEBUG > 0) 21 | size_t i; 22 | 23 | for (i = 0; i < NOS_CONFIG_ISR_STACK_SIZE; i++) { 24 | _isrStack[i] = 0xFFFFFFFFUL; 25 | } 26 | #endif 27 | 28 | /* Copy MSP to PSP */ 29 | _SetPSP(_GetMSP()); 30 | /* Set MSP to local ISR stack */ 31 | _SetMSP((uint32_t)&_isrStack[NOS_CONFIG_ISR_STACK_SIZE] & 0xFFFFFFF8UL); 32 | /* Set current stack to PSP and privileged mode */ 33 | _SetCONTROL(_GetCONTROL() | 0x00000002UL); 34 | /* Set PendSV exception to lowest priority */ 35 | *(volatile uint32_t *)0xE000ED20UL |= 0x00FF0000UL; 36 | } 37 | 38 | void nOS_InitContext (nOS_Thread *thread, nOS_Stack *stack, size_t ssize, nOS_ThreadEntry entry, void *arg) 39 | { 40 | nOS_Stack *tos = (nOS_Stack*)((uint32_t)(stack + ssize) & 0xFFFFFFF8UL); 41 | #if (NOS_CONFIG_DEBUG > 0) 42 | size_t i; 43 | 44 | for (i = 0; i < ssize; i++) { 45 | stack[i] = 0xFFFFFFFFUL; 46 | } 47 | #endif 48 | 49 | *(--tos) = 0x01000000UL; /* xPSR */ 50 | *(--tos) = (nOS_Stack)entry;/* PC */ 51 | *(--tos) = 0x00000000UL; /* LR */ 52 | #if (NOS_CONFIG_DEBUG > 0) 53 | *(--tos) = 0x12121212UL; /* R12 */ 54 | *(--tos) = 0x03030303UL; /* R3 */ 55 | *(--tos) = 0x02020202UL; /* R2 */ 56 | *(--tos) = 0x01010101UL; /* R1 */ 57 | #else 58 | tos -= 4; /* R12, R3, R2 and R1 */ 59 | #endif 60 | *(--tos) = (nOS_Stack)arg; /* R0 */ 61 | #if (NOS_CONFIG_DEBUG > 0) 62 | *(--tos) = 0x11111111UL; /* R11 */ 63 | *(--tos) = 0x10101010UL; /* R10 */ 64 | *(--tos) = 0x09090909UL; /* R9 */ 65 | *(--tos) = 0x08080808UL; /* R8 */ 66 | *(--tos) = 0x07070707UL; /* R7 */ 67 | *(--tos) = 0x06060606UL; /* R6 */ 68 | *(--tos) = 0x05050505UL; /* R5 */ 69 | *(--tos) = 0x04040404UL; /* R4 */ 70 | #else 71 | tos -= 8; /* R11, R10, R9, R8, R7, R6, R5 and R4 */ 72 | #endif 73 | 74 | thread->stackPtr = tos; 75 | } 76 | 77 | void nOS_SwitchContext (void) 78 | { 79 | /* Request context switch */ 80 | *(volatile uint32_t *)0xE000ED04UL = 0x10000000UL; 81 | nOS_PeekCritical(); 82 | } 83 | 84 | void nOS_EnterISR (void) 85 | { 86 | nOS_StatusReg sr; 87 | 88 | #if (NOS_CONFIG_SAFE > 0) 89 | if (nOS_running) 90 | #endif 91 | { 92 | nOS_EnterCritical(sr); 93 | nOS_isrNestingCounter++; 94 | nOS_LeaveCritical(sr); 95 | } 96 | } 97 | 98 | void nOS_LeaveISR (void) 99 | { 100 | nOS_StatusReg sr; 101 | nOS_Thread *highPrioThread; 102 | 103 | #if (NOS_CONFIG_SAFE > 0) 104 | if (nOS_running) 105 | #endif 106 | { 107 | nOS_EnterCritical(sr); 108 | nOS_isrNestingCounter--; 109 | if (nOS_isrNestingCounter == 0) { 110 | #if (NOS_CONFIG_SCHED_LOCK_ENABLE > 0) 111 | if (nOS_lockNestingCounter == 0) 112 | #endif 113 | { 114 | highPrioThread = nOS_FindHighPrioThread(); 115 | if (highPrioThread != NULL) { 116 | #if (NOS_CONFIG_SCHED_PREEMPTIVE_ENABLE > 0) || (NOS_CONFIG_SCHED_ROUND_ROBIN_ENABLE > 0) 117 | nOS_highPrioThread = highPrioThread; 118 | if (nOS_runningThread != nOS_highPrioThread) { 119 | *(volatile uint32_t *)0xE000ED04UL = 0x10000000UL; 120 | } 121 | #endif 122 | } else if (nOS_runningThread != &nOS_mainHandle) { 123 | nOS_highPrioThread = &nOS_mainHandle; 124 | *(volatile uint32_t *)0xE000ED04UL = 0x10000000UL; 125 | } 126 | } 127 | } 128 | nOS_LeaveCritical(sr); 129 | } 130 | } 131 | 132 | __asm void PendSV_Handler (void) 133 | { 134 | extern nOS_runningThread; 135 | extern nOS_highPrioThread; 136 | 137 | /* Disable interrupts */ 138 | CPSID I 139 | ISB 140 | 141 | /* Save PSP before doing anything, PendSV_Handler already running on MSP */ 142 | MRS R0, PSP 143 | 144 | /* Get the location of nOS_runningThread */ 145 | LDR R3, =nOS_runningThread 146 | LDR R2, [R3] 147 | 148 | /* Make space for the remaining registers */ 149 | SUBS R0, R0, #32 150 | 151 | /* Save PSP to nOS_Thread object of current running thread */ 152 | STR R0, [R2] 153 | 154 | /* Push low registers on thread stack */ 155 | STMIA R0!, {R4-R7} 156 | 157 | /* Copy high registers to low registers */ 158 | MOV R4, R8 159 | MOV R5, R9 160 | MOV R6, R10 161 | MOV R7, R11 162 | /* Push high registers on thread stack */ 163 | STMIA R0!, {R4-R7} 164 | 165 | /* Get the location of nOS_highPrioThread */ 166 | LDR R1, =nOS_highPrioThread 167 | LDR R2, [R1] 168 | 169 | /* Copy nOS_highPrioThread to nOS_runningThread */ 170 | STR R2, [R3] 171 | 172 | /* Restore PSP from nOS_Thread object of high prio thread */ 173 | LDR R0, [R2] 174 | 175 | /* Move to the high registers */ 176 | ADDS R0, R0, #16 177 | 178 | /* Pop high registers from thread stack */ 179 | LDMIA R0!, {R4-R7} 180 | /* Copy low registers to high registers */ 181 | MOV R11, R7 182 | MOV R10, R6 183 | MOV R9, R5 184 | MOV R8, R4 185 | 186 | /* Restore PSP to high prio thread stack */ 187 | MSR PSP, R0 188 | 189 | /* Go back for the low registers */ 190 | SUBS R0, R0, #32 191 | 192 | /* Pop low registers from thread stack */ 193 | LDMIA R0!, {R4-R7} 194 | 195 | /* Enable interrupts */ 196 | CPSIE I 197 | ISB 198 | 199 | /* Return */ 200 | BX LR 201 | } 202 | 203 | #ifdef __cplusplus 204 | } 205 | #endif 206 | -------------------------------------------------------------------------------- /src/port/Keil/ARM_Cortex_M3/nOSPort.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2019 Jim Tremblay 3 | * 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | */ 8 | 9 | #define NOS_PRIVATE 10 | #include "nOS.h" 11 | 12 | #ifdef __cplusplus 13 | extern "C" { 14 | #endif 15 | 16 | static nOS_Stack _isrStack[NOS_CONFIG_ISR_STACK_SIZE]; 17 | 18 | void nOS_InitSpecific (void) 19 | { 20 | #if (NOS_CONFIG_DEBUG > 0) 21 | size_t i; 22 | 23 | for (i = 0; i < NOS_CONFIG_ISR_STACK_SIZE; i++) { 24 | _isrStack[i] = 0xFFFFFFFFUL; 25 | } 26 | #endif 27 | 28 | /* Copy MSP to PSP */ 29 | _SetPSP(_GetMSP()); 30 | /* Set MSP to local ISR stack */ 31 | _SetMSP((uint32_t)&_isrStack[NOS_CONFIG_ISR_STACK_SIZE] & 0xFFFFFFF8UL); 32 | /* Set current stack to PSP and privileged mode */ 33 | _SetCONTROL(_GetCONTROL() | 0x00000002UL); 34 | /* Set PendSV exception to lowest priority */ 35 | *(volatile uint32_t *)0xE000ED20UL |= 0x00FF0000UL; 36 | } 37 | 38 | void nOS_InitContext (nOS_Thread *thread, nOS_Stack *stack, size_t ssize, nOS_ThreadEntry entry, void *arg) 39 | { 40 | nOS_Stack *tos = (nOS_Stack*)((uint32_t)(stack + ssize) & 0xFFFFFFF8UL); 41 | #if (NOS_CONFIG_DEBUG > 0) 42 | size_t i; 43 | 44 | for (i = 0; i < ssize; i++) { 45 | stack[i] = 0xFFFFFFFFUL; 46 | } 47 | #endif 48 | 49 | *(--tos) = 0x01000000UL; /* xPSR */ 50 | *(--tos) = (nOS_Stack)entry;/* PC */ 51 | *(--tos) = 0x00000000UL; /* LR */ 52 | #if (NOS_CONFIG_DEBUG > 0) 53 | *(--tos) = 0x12121212UL; /* R12 */ 54 | *(--tos) = 0x03030303UL; /* R3 */ 55 | *(--tos) = 0x02020202UL; /* R2 */ 56 | *(--tos) = 0x01010101UL; /* R1 */ 57 | #else 58 | tos -= 4; /* R12, R3, R2 and R1 */ 59 | #endif 60 | *(--tos) = (nOS_Stack)arg; /* R0 */ 61 | #if (NOS_CONFIG_DEBUG > 0) 62 | *(--tos) = 0x11111111UL; /* R11 */ 63 | *(--tos) = 0x10101010UL; /* R10 */ 64 | *(--tos) = 0x09090909UL; /* R9 */ 65 | *(--tos) = 0x08080808UL; /* R8 */ 66 | *(--tos) = 0x07070707UL; /* R7 */ 67 | *(--tos) = 0x06060606UL; /* R6 */ 68 | *(--tos) = 0x05050505UL; /* R5 */ 69 | *(--tos) = 0x04040404UL; /* R4 */ 70 | #else 71 | tos -= 8; /* R11, R10, R9, R8, R7, R6, R5 and R4 */ 72 | #endif 73 | 74 | thread->stackPtr = tos; 75 | } 76 | 77 | void nOS_SwitchContext (void) 78 | { 79 | /* Request context switch */ 80 | *(volatile uint32_t *)0xE000ED04UL = 0x10000000UL; 81 | nOS_PeekCritical(); 82 | } 83 | 84 | void nOS_EnterISR (void) 85 | { 86 | nOS_StatusReg sr; 87 | 88 | #if (NOS_CONFIG_SAFE > 0) 89 | if (nOS_running) 90 | #endif 91 | { 92 | nOS_EnterCritical(sr); 93 | nOS_isrNestingCounter++; 94 | nOS_LeaveCritical(sr); 95 | } 96 | } 97 | 98 | void nOS_LeaveISR (void) 99 | { 100 | nOS_StatusReg sr; 101 | nOS_Thread *highPrioThread; 102 | 103 | #if (NOS_CONFIG_SAFE > 0) 104 | if (nOS_running) 105 | #endif 106 | { 107 | nOS_EnterCritical(sr); 108 | nOS_isrNestingCounter--; 109 | if (nOS_isrNestingCounter == 0) { 110 | #if (NOS_CONFIG_SCHED_LOCK_ENABLE > 0) 111 | if (nOS_lockNestingCounter == 0) 112 | #endif 113 | { 114 | highPrioThread = nOS_FindHighPrioThread(); 115 | if (highPrioThread != NULL) { 116 | #if (NOS_CONFIG_SCHED_PREEMPTIVE_ENABLE > 0) || (NOS_CONFIG_SCHED_ROUND_ROBIN_ENABLE > 0) 117 | nOS_highPrioThread = highPrioThread; 118 | if (nOS_runningThread != nOS_highPrioThread) { 119 | *(volatile uint32_t *)0xE000ED04UL = 0x10000000UL; 120 | } 121 | #endif 122 | } else if (nOS_runningThread != &nOS_mainHandle) { 123 | nOS_highPrioThread = &nOS_mainHandle; 124 | *(volatile uint32_t *)0xE000ED04UL = 0x10000000UL; 125 | } 126 | } 127 | } 128 | nOS_LeaveCritical(sr); 129 | } 130 | } 131 | 132 | __asm void PendSV_Handler (void) 133 | { 134 | extern nOS_runningThread; 135 | extern nOS_highPrioThread; 136 | 137 | /* Disable interrupts */ 138 | CPSID I 139 | ISB 140 | 141 | /* Save PSP before doing anything, PendSV_Handler already running on MSP */ 142 | MRS R0, PSP 143 | 144 | /* Get the location of nOS_runningThread */ 145 | LDR R3, =nOS_runningThread 146 | LDR R2, [R3] 147 | 148 | /* Push remaining registers on thread stack */ 149 | STMDB R0!, {R4-R11} 150 | 151 | /* Save PSP to nOS_Thread object of current running thread */ 152 | STR R0, [R2] 153 | 154 | /* Get the location of nOS_highPrioThread */ 155 | LDR R1, =nOS_highPrioThread 156 | LDR R2, [R1] 157 | 158 | /* Copy nOS_highPrioThread to nOS_runningThread */ 159 | STR R2, [R3] 160 | 161 | /* Restore PSP from nOS_Thread object of high prio thread */ 162 | LDR R0, [R2] 163 | 164 | /* Pop registers from thread stack */ 165 | LDMIA R0!, {R4-R11} 166 | 167 | /* Restore PSP to high prio thread stack */ 168 | MSR PSP, R0 169 | 170 | /* Enable interrupts */ 171 | CPSIE I 172 | ISB 173 | 174 | /* Return */ 175 | BX LR 176 | } 177 | 178 | #ifdef __cplusplus 179 | } 180 | #endif 181 | -------------------------------------------------------------------------------- /src/port/Keil/ARM_Cortex_M4/nOSPort.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2019 Jim Tremblay 3 | * 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | */ 8 | 9 | #define NOS_PRIVATE 10 | #include "nOS.h" 11 | 12 | #ifdef __cplusplus 13 | extern "C" { 14 | #endif 15 | 16 | static nOS_Stack _isrStack[NOS_CONFIG_ISR_STACK_SIZE]; 17 | 18 | void nOS_InitSpecific (void) 19 | { 20 | #if (NOS_CONFIG_DEBUG > 0) 21 | size_t i; 22 | 23 | for (i = 0; i < NOS_CONFIG_ISR_STACK_SIZE; i++) { 24 | _isrStack[i] = 0xFFFFFFFFUL; 25 | } 26 | #endif 27 | 28 | /* Copy MSP to PSP */ 29 | _SetPSP(_GetMSP()); 30 | /* Set MSP to local ISR stack */ 31 | _SetMSP((uint32_t)&_isrStack[NOS_CONFIG_ISR_STACK_SIZE] & 0xFFFFFFF8UL); 32 | /* Set current stack to PSP and privileged mode */ 33 | _SetCONTROL(_GetCONTROL() | 0x00000002UL); 34 | /* Set PendSV exception to lowest priority */ 35 | *(volatile uint32_t *)0xE000ED20UL |= 0x00FF0000UL; 36 | } 37 | 38 | void nOS_InitContext (nOS_Thread *thread, nOS_Stack *stack, size_t ssize, nOS_ThreadEntry entry, void *arg) 39 | { 40 | nOS_Stack *tos = (nOS_Stack*)((uint32_t)(stack + ssize) & 0xFFFFFFF8UL); 41 | #if (NOS_CONFIG_DEBUG > 0) 42 | size_t i; 43 | 44 | for (i = 0; i < ssize; i++) { 45 | stack[i] = 0xFFFFFFFFUL; 46 | } 47 | #endif 48 | 49 | *(--tos) = 0x01000000UL; /* xPSR */ 50 | *(--tos) = (nOS_Stack)entry;/* PC */ 51 | *(--tos) = 0x00000000UL; /* LR */ 52 | #if (NOS_CONFIG_DEBUG > 0) 53 | *(--tos) = 0x12121212UL; /* R12 */ 54 | *(--tos) = 0x03030303UL; /* R3 */ 55 | *(--tos) = 0x02020202UL; /* R2 */ 56 | *(--tos) = 0x01010101UL; /* R1 */ 57 | #else 58 | tos -= 4; /* R12, R3, R2 and R1 */ 59 | #endif 60 | *(--tos) = (nOS_Stack)arg; /* R0 */ 61 | *(--tos) = 0xFFFFFFFDUL; /* EXC_RETURN (Thread mode, Thread use PSP) */ 62 | #if (NOS_CONFIG_DEBUG > 0) 63 | *(--tos) = 0x11111111UL; /* R11 */ 64 | *(--tos) = 0x10101010UL; /* R10 */ 65 | *(--tos) = 0x09090909UL; /* R9 */ 66 | *(--tos) = 0x08080808UL; /* R8 */ 67 | *(--tos) = 0x07070707UL; /* R7 */ 68 | *(--tos) = 0x06060606UL; /* R6 */ 69 | *(--tos) = 0x05050505UL; /* R5 */ 70 | *(--tos) = 0x04040404UL; /* R4 */ 71 | #else 72 | tos -= 8; /* R11, R10, R9, R8, R7, R6, R5 and R4 */ 73 | #endif 74 | 75 | thread->stackPtr = tos; 76 | } 77 | 78 | void nOS_SwitchContext (void) 79 | { 80 | /* Request context switch */ 81 | *(volatile uint32_t *)0xE000ED04UL = 0x10000000UL; 82 | nOS_PeekCritical(); 83 | } 84 | 85 | void nOS_EnterISR (void) 86 | { 87 | nOS_StatusReg sr; 88 | 89 | #if (NOS_CONFIG_SAFE > 0) 90 | if (nOS_running) 91 | #endif 92 | { 93 | nOS_EnterCritical(sr); 94 | nOS_isrNestingCounter++; 95 | nOS_LeaveCritical(sr); 96 | } 97 | } 98 | 99 | void nOS_LeaveISR (void) 100 | { 101 | nOS_StatusReg sr; 102 | nOS_Thread *highPrioThread; 103 | 104 | #if (NOS_CONFIG_SAFE > 0) 105 | if (nOS_running) 106 | #endif 107 | { 108 | nOS_EnterCritical(sr); 109 | nOS_isrNestingCounter--; 110 | if (nOS_isrNestingCounter == 0) { 111 | #if (NOS_CONFIG_SCHED_LOCK_ENABLE > 0) 112 | if (nOS_lockNestingCounter == 0) 113 | #endif 114 | { 115 | highPrioThread = nOS_FindHighPrioThread(); 116 | if (highPrioThread != NULL) { 117 | #if (NOS_CONFIG_SCHED_PREEMPTIVE_ENABLE > 0) || (NOS_CONFIG_SCHED_ROUND_ROBIN_ENABLE > 0) 118 | nOS_highPrioThread = highPrioThread; 119 | if (nOS_runningThread != nOS_highPrioThread) { 120 | *(volatile uint32_t *)0xE000ED04UL = 0x10000000UL; 121 | } 122 | #endif 123 | } else if (nOS_runningThread != &nOS_mainHandle) { 124 | nOS_highPrioThread = &nOS_mainHandle; 125 | *(volatile uint32_t *)0xE000ED04UL = 0x10000000UL; 126 | } 127 | } 128 | } 129 | nOS_LeaveCritical(sr); 130 | } 131 | } 132 | 133 | __asm void PendSV_Handler (void) 134 | { 135 | extern nOS_runningThread; 136 | extern nOS_highPrioThread; 137 | 138 | /* Disable interrupts */ 139 | CPSID I 140 | ISB 141 | 142 | /* Save PSP before doing anything, PendSV_Handler already running on MSP */ 143 | MRS R0, PSP 144 | 145 | /* Get the location of nOS_runningThread */ 146 | LDR R3, =nOS_runningThread 147 | LDR R2, [R3] 148 | 149 | #ifdef __TARGET_FPU_VFP 150 | /* Is thread using FPU? Yes, push high VFP registers to stack */ 151 | TST LR, #0x10 152 | IT EQ 153 | VSTMDBEQ R0!, {S16-S31} 154 | #endif 155 | 156 | /* Push remaining registers on thread stack */ 157 | STMDB R0!, {R4-R11, LR} 158 | 159 | /* Save PSP to nOS_Thread object of current running thread */ 160 | STR R0, [R2] 161 | 162 | /* Get the location of nOS_highPrioThread */ 163 | LDR R1, =nOS_highPrioThread 164 | LDR R2, [R1] 165 | 166 | /* Copy nOS_highPrioThread to nOS_runningThread */ 167 | STR R2, [R3] 168 | 169 | /* Restore PSP from nOS_Thread object of high prio thread */ 170 | LDR R0, [R2] 171 | 172 | /* Pop registers from thread stack */ 173 | LDMIA R0!, {R4-R11, LR} 174 | 175 | #ifdef __TARGET_FPU_VFP 176 | /* Is thread using FPU? Yes, pop high VFP registers from stack */ 177 | TST LR, #0x10 178 | IT EQ 179 | VLDMIAEQ R0!, {S16-S31} 180 | #endif 181 | 182 | /* Restore PSP to high prio thread stack */ 183 | MSR PSP, R0 184 | 185 | /* Enable interrupts */ 186 | CPSIE I 187 | ISB 188 | 189 | /* Return */ 190 | BX LR 191 | } 192 | 193 | #ifdef __cplusplus 194 | } 195 | #endif 196 | -------------------------------------------------------------------------------- /src/port/Keil/ARM_Cortex_M7/nOSPort.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2019 Jim Tremblay 3 | * 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | */ 8 | 9 | #define NOS_PRIVATE 10 | #include "nOS.h" 11 | 12 | #ifdef __cplusplus 13 | extern "C" { 14 | #endif 15 | 16 | static nOS_Stack _isrStack[NOS_CONFIG_ISR_STACK_SIZE]; 17 | 18 | void nOS_InitSpecific (void) 19 | { 20 | #if (NOS_CONFIG_DEBUG > 0) 21 | size_t i; 22 | 23 | for (i = 0; i < NOS_CONFIG_ISR_STACK_SIZE; i++) { 24 | _isrStack[i] = 0xFFFFFFFFUL; 25 | } 26 | #endif 27 | 28 | /* Copy MSP to PSP */ 29 | _SetPSP(_GetMSP()); 30 | /* Set MSP to local ISR stack */ 31 | _SetMSP((uint32_t)&_isrStack[NOS_CONFIG_ISR_STACK_SIZE] & 0xFFFFFFF8UL); 32 | /* Set current stack to PSP and privileged mode */ 33 | _SetCONTROL(_GetCONTROL() | 0x00000002UL); 34 | /* Set PendSV exception to lowest priority */ 35 | *(volatile uint32_t *)0xE000ED20UL |= 0x00FF0000UL; 36 | } 37 | 38 | void nOS_InitContext (nOS_Thread *thread, nOS_Stack *stack, size_t ssize, nOS_ThreadEntry entry, void *arg) 39 | { 40 | nOS_Stack *tos = (nOS_Stack*)((uint32_t)(stack + ssize) & 0xFFFFFFF8UL); 41 | #if (NOS_CONFIG_DEBUG > 0) 42 | size_t i; 43 | 44 | for (i = 0; i < ssize; i++) { 45 | stack[i] = 0xFFFFFFFFUL; 46 | } 47 | #endif 48 | 49 | *(--tos) = 0x01000000UL; /* xPSR */ 50 | *(--tos) = (nOS_Stack)entry;/* PC */ 51 | *(--tos) = 0x00000000UL; /* LR */ 52 | #if (NOS_CONFIG_DEBUG > 0) 53 | *(--tos) = 0x12121212UL; /* R12 */ 54 | *(--tos) = 0x03030303UL; /* R3 */ 55 | *(--tos) = 0x02020202UL; /* R2 */ 56 | *(--tos) = 0x01010101UL; /* R1 */ 57 | #else 58 | tos -= 4; /* R12, R3, R2 and R1 */ 59 | #endif 60 | *(--tos) = (nOS_Stack)arg; /* R0 */ 61 | *(--tos) = 0xFFFFFFFDUL; /* EXC_RETURN (Thread mode, Thread use PSP) */ 62 | #if (NOS_CONFIG_DEBUG > 0) 63 | *(--tos) = 0x11111111UL; /* R11 */ 64 | *(--tos) = 0x10101010UL; /* R10 */ 65 | *(--tos) = 0x09090909UL; /* R9 */ 66 | *(--tos) = 0x08080808UL; /* R8 */ 67 | *(--tos) = 0x07070707UL; /* R7 */ 68 | *(--tos) = 0x06060606UL; /* R6 */ 69 | *(--tos) = 0x05050505UL; /* R5 */ 70 | *(--tos) = 0x04040404UL; /* R4 */ 71 | #else 72 | tos -= 8; /* R11, R10, R9, R8, R7, R6, R5 and R4 */ 73 | #endif 74 | 75 | thread->stackPtr = tos; 76 | } 77 | 78 | void nOS_SwitchContext (void) 79 | { 80 | /* Request context switch */ 81 | *(volatile uint32_t *)0xE000ED04UL = 0x10000000UL; 82 | nOS_PeekCritical(); 83 | } 84 | 85 | void nOS_EnterISR (void) 86 | { 87 | nOS_StatusReg sr; 88 | 89 | #if (NOS_CONFIG_SAFE > 0) 90 | if (nOS_running) 91 | #endif 92 | { 93 | nOS_EnterCritical(sr); 94 | nOS_isrNestingCounter++; 95 | nOS_LeaveCritical(sr); 96 | } 97 | } 98 | 99 | void nOS_LeaveISR (void) 100 | { 101 | nOS_StatusReg sr; 102 | nOS_Thread *highPrioThread; 103 | 104 | #if (NOS_CONFIG_SAFE > 0) 105 | if (nOS_running) 106 | #endif 107 | { 108 | nOS_EnterCritical(sr); 109 | nOS_isrNestingCounter--; 110 | if (nOS_isrNestingCounter == 0) { 111 | #if (NOS_CONFIG_SCHED_LOCK_ENABLE > 0) 112 | if (nOS_lockNestingCounter == 0) 113 | #endif 114 | { 115 | highPrioThread = nOS_FindHighPrioThread(); 116 | if (highPrioThread != NULL) { 117 | #if (NOS_CONFIG_SCHED_PREEMPTIVE_ENABLE > 0) || (NOS_CONFIG_SCHED_ROUND_ROBIN_ENABLE > 0) 118 | nOS_highPrioThread = highPrioThread; 119 | if (nOS_runningThread != nOS_highPrioThread) { 120 | *(volatile uint32_t *)0xE000ED04UL = 0x10000000UL; 121 | } 122 | #endif 123 | } else if (nOS_runningThread != &nOS_mainHandle) { 124 | nOS_highPrioThread = &nOS_mainHandle; 125 | *(volatile uint32_t *)0xE000ED04UL = 0x10000000UL; 126 | } 127 | } 128 | } 129 | nOS_LeaveCritical(sr); 130 | } 131 | } 132 | 133 | __asm void PendSV_Handler (void) 134 | { 135 | extern nOS_runningThread; 136 | extern nOS_highPrioThread; 137 | 138 | /* Disable interrupts */ 139 | CPSID I 140 | ISB 141 | 142 | /* Save PSP before doing anything, PendSV_Handler already running on MSP */ 143 | MRS R0, PSP 144 | 145 | /* Get the location of nOS_runningThread */ 146 | LDR R3, =nOS_runningThread 147 | LDR R2, [R3] 148 | 149 | #ifdef __TARGET_FPU_VFP 150 | /* Is thread using FPU? Yes, push high VFP registers to stack */ 151 | TST LR, #0x10 152 | IT EQ 153 | VSTMDBEQ R0!, {S16-S31} 154 | #endif 155 | 156 | /* Push remaining registers on thread stack */ 157 | STMDB R0!, {R4-R11, LR} 158 | 159 | /* Save PSP to nOS_Thread object of current running thread */ 160 | STR R0, [R2] 161 | 162 | /* Get the location of nOS_highPrioThread */ 163 | LDR R1, =nOS_highPrioThread 164 | LDR R2, [R1] 165 | 166 | /* Copy nOS_highPrioThread to nOS_runningThread */ 167 | STR R2, [R3] 168 | 169 | /* Restore PSP from nOS_Thread object of high prio thread */ 170 | LDR R0, [R2] 171 | 172 | /* Pop registers from thread stack */ 173 | LDMIA R0!, {R4-R11, LR} 174 | 175 | #ifdef __TARGET_FPU_VFP 176 | /* Is thread using FPU? Yes, pop high VFP registers from stack */ 177 | TST LR, #0x10 178 | IT EQ 179 | VLDMIAEQ R0!, {S16-S31} 180 | #endif 181 | 182 | /* Restore PSP to high prio thread stack */ 183 | MSR PSP, R0 184 | 185 | /* Enable interrupts */ 186 | CPSIE I 187 | ISB 188 | 189 | /* Return */ 190 | BX LR 191 | } 192 | 193 | #ifdef __cplusplus 194 | } 195 | #endif 196 | -------------------------------------------------------------------------------- /src/port/NC30/M16C_R8C/nOSPort.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2019 Jim Tremblay 3 | * 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | */ 8 | 9 | #define NOS_PRIVATE 10 | #include "nOS.h" 11 | 12 | #ifdef __cplusplus 13 | extern "C" { 14 | #endif 15 | 16 | void nOS_InitContext (nOS_Thread *thread, nOS_Stack *stack, size_t ssize, nOS_ThreadEntry entry, void *arg) 17 | { 18 | nOS_Stack *tos = (nOS_Stack*)((uint16_t)(stack + ssize) & 0xFFFE); 19 | #if (NOS_CONFIG_DEBUG > 0) 20 | size_t i; 21 | 22 | for (i = 0; i < ssize; i++) { 23 | stack[i] = 0xFFFF; 24 | } 25 | #endif 26 | 27 | /* FLG = 0x0C0 = interrupts enabled, USP stack pointer */ 28 | *(--tos) = (((uint32_t)entry >> 8) & 0x0F00) | 0x00C0; 29 | *(--tos) = (nOS_Stack)entry; 30 | 31 | #if (NOS_CONFIG_DEBUG > 0) 32 | *(--tos) = 0xEEEE; /* FB */ 33 | *(--tos) = 0xCCCC; /* SB */ 34 | *(--tos) = 0xBBBB; /* A1 */ 35 | *(--tos) = 0xAAAA; /* A0 */ 36 | *(--tos) = 0x3333; /* R3 */ 37 | *(--tos) = 0x2222; /* R2 */ 38 | #else 39 | tos -= 6; /* FB, SB, A1, A0, R3, R2 */ 40 | #endif 41 | *(--tos) = (nOS_Stack)arg; /* R1 */ 42 | #if (NOS_CONFIG_DEBUG > 0) 43 | *(--tos) = 0x1111; /* R0 */ 44 | #else 45 | tos -= 1; /* R0 */ 46 | #endif 47 | 48 | thread->stackPtr = tos; 49 | } 50 | 51 | void nOS_EnterISR (void) 52 | { 53 | nOS_StatusReg sr; 54 | 55 | #if (NOS_CONFIG_SAFE > 0) 56 | if (nOS_running) 57 | #endif 58 | { 59 | nOS_EnterCritical(sr); 60 | nOS_isrNestingCounter++; 61 | nOS_LeaveCritical(sr); 62 | } 63 | } 64 | 65 | bool nOS_LeaveISR (void) 66 | { 67 | nOS_StatusReg sr; 68 | nOS_Thread *highPrioThread; 69 | bool swctx = false; 70 | 71 | #if (NOS_CONFIG_SAFE > 0) 72 | if (nOS_running) 73 | #endif 74 | { 75 | nOS_EnterCritical(sr); 76 | nOS_isrNestingCounter--; 77 | if (nOS_isrNestingCounter == 0) { 78 | #if (NOS_CONFIG_SCHED_LOCK_ENABLE > 0) 79 | if (nOS_lockNestingCounter == 0) 80 | #endif 81 | { 82 | highPrioThread = nOS_FindHighPrioThread(); 83 | if (highPrioThread != NULL) { 84 | #if (NOS_CONFIG_SCHED_PREEMPTIVE_ENABLE > 0) || (NOS_CONFIG_SCHED_ROUND_ROBIN_ENABLE > 0) 85 | nOS_highPrioThread = highPrioThread; 86 | if (nOS_runningThread != nOS_highPrioThread) { 87 | swctx = true; 88 | } 89 | #endif 90 | } else if (nOS_runningThread != &nOS_mainHandle) { 91 | nOS_highPrioThread = &nOS_mainHandle; 92 | swctx = true; 93 | } 94 | } 95 | } 96 | nOS_LeaveCritical(sr); 97 | } 98 | 99 | return swctx; 100 | } 101 | 102 | #ifdef __cplusplus 103 | } 104 | #endif 105 | -------------------------------------------------------------------------------- /src/port/NC30/M16C_R8C/nOSPortASM.a30: -------------------------------------------------------------------------------- 1 | ; 2 | ; Copyright (c) 2014-2019 Jim Tremblay 3 | ; 4 | ; This Source Code Form is subject to the terms of the Mozilla Public 5 | ; License, v. 2.0. If a copy of the MPL was not distributed with this 6 | ; file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | ; 8 | 9 | .SECTION program,CODE,ALIGN 10 | 11 | .GLB __GetIPL 12 | .GLB $_SetIPL 13 | .GLB __GetI 14 | .GLB $_SetI 15 | .GLB _nOS_SwitchContextHandler 16 | .GLB _nOS_SwitchContextFromIsrHandler 17 | 18 | .GLB _nOS_runningThread 19 | .GLB _nOS_highPrioThread 20 | 21 | __GetIPL: 22 | ; Copy FLG register into working register 23 | STC FLG, R0 24 | 25 | ; Keep only IPL bits from FLG register 26 | AND.W #0x7000, R0 27 | 28 | ; Return from subroutine 29 | RTS 30 | NOP 31 | 32 | $_SetIPL: 33 | ; Copy FLG register into working register 34 | STC FLG, R0 35 | 36 | ; Clear IPL bits from FLG register 37 | AND.W #0x8FFF, R0 38 | 39 | ; Write IPL into working register 40 | OR.W R1, R0 41 | 42 | ; Copy working register into FLG register 43 | LDC R0, FLG 44 | NOP 45 | 46 | ; Return from subroutine 47 | RTS 48 | NOP 49 | 50 | __GetI: 51 | ; Copy FLG register into working register 52 | STC FLG, R0 53 | 54 | ; Keep only I bit from FLG register 55 | AND.W #0x0040, R0 56 | 57 | ; Return from subroutine 58 | RTS 59 | NOP 60 | 61 | $_SetI: 62 | ; Copy FLG register into working register 63 | STC FLG, R0 64 | 65 | ; Clear I bit from FLG register 66 | AND.W #0xFFBF, R0 67 | 68 | ; Write I into working register 69 | OR.W R1, R0 70 | 71 | ; Copy working register into FLG register 72 | LDC R0, FLG 73 | NOP 74 | 75 | ; Return from subroutine 76 | RTS 77 | NOP 78 | 79 | _nOS_SwitchContextHandler: 80 | ; Push all registers on thread stack 81 | PUSHM R0,R1,R2,R3,A0,A1,SB,FB 82 | 83 | ; Save SP to nOS_Thread object of current running thread 84 | MOV.W _nOS_runningThread, A0 85 | STC SP, [A0] 86 | 87 | ; Copy nOS_highPrioThread to nOS_runningThread 88 | MOV.W _nOS_highPrioThread, _nOS_runningThread 89 | 90 | ; Restore SP from nOS_Thread object of high prio thread 91 | MOV.W _nOS_highPrioThread, A0 92 | LDC [A0], SP 93 | 94 | ; Pop all registers from thread stack 95 | POPM R0,R1,R2,R3,A0,A1,SB,FB 96 | 97 | ; Return from interrupt 98 | REIT 99 | NOP 100 | 101 | _nOS_SwitchContextFromIsrHandler: 102 | ; Push all registers on thread stack 103 | PUSHM R0,R1,R2,R3,A0,A1,SB,FB 104 | 105 | ; Move PC and FLG from ISTACK to USTACK 106 | STC ISP, A0 107 | MOV.W 0[A0], 16[SP] 108 | MOV.W 2[A0], 18[SP] 109 | 110 | ; Adjust ISTACK (remove PC and FLG) 111 | ADD.W #4, A0 112 | LDC A0, ISP 113 | 114 | ; Save SP to nOS_Thread object of current running thread 115 | MOV.W _nOS_runningThread, A0 116 | STC SP, [A0] 117 | 118 | ; Copy nOS_highPrioThread to nOS_runningThread 119 | MOV.W _nOS_highPrioThread, _nOS_runningThread 120 | 121 | ; Restore SP from nOS_Thread object of high prio thread 122 | MOV.W _nOS_highPrioThread, A0 123 | LDC [A0], SP 124 | 125 | ; Pop all registers from thread stack 126 | POPM R0,R1,R2,R3,A0,A1,SB,FB 127 | 128 | ; Return from interrupt 129 | REIT 130 | NOP 131 | 132 | .END 133 | -------------------------------------------------------------------------------- /src/port/POSIX/nOSPort.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2019 Jim Tremblay 3 | * 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | */ 8 | 9 | #define NOS_PRIVATE 10 | #include "nOS.h" 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | #ifdef __cplusplus 21 | extern "C" { 22 | #endif 23 | 24 | volatile uint32_t nOS_criticalNestingCounter; 25 | pthread_mutex_t nOS_criticalSection; 26 | 27 | static pthread_cond_t _schedCond; 28 | volatile bool _schedStarted; 29 | volatile bool _schedRequest; 30 | static nOS_Stack _mainStack; 31 | 32 | static void* _Entry (void *arg) 33 | { 34 | nOS_Thread *thread = (nOS_Thread*)arg; 35 | 36 | pthread_mutex_lock(&nOS_criticalSection); 37 | 38 | /* Signal to creator we're running */ 39 | thread->stackPtr->started = true; 40 | pthread_cond_signal(&thread->stackPtr->cond); 41 | 42 | /* Wait to have the permission to run (given by scheduler) */ 43 | while (!thread->stackPtr->running) { 44 | pthread_cond_wait(&thread->stackPtr->cond, &nOS_criticalSection); 45 | } 46 | 47 | /* Initialize critical section counter */ 48 | nOS_criticalNestingCounter = thread->stackPtr->crit; 49 | 50 | pthread_mutex_unlock(&nOS_criticalSection); 51 | 52 | thread->stackPtr->entry(thread->stackPtr->arg); 53 | 54 | return 0; 55 | } 56 | 57 | static void* _Scheduler (void *arg) 58 | { 59 | pthread_mutex_lock(&nOS_criticalSection); 60 | 61 | /* Signal to init we're running and ready to accept request */ 62 | _schedStarted = true; 63 | pthread_cond_signal(&_schedCond); 64 | 65 | /* Wait until scheduler is started */ 66 | pthread_mutex_unlock(&nOS_criticalSection); 67 | while (!nOS_running) { 68 | usleep(1000); 69 | } 70 | pthread_mutex_lock(&nOS_criticalSection); 71 | 72 | while (true) { 73 | /* Wait until a thread send a scheduling request */ 74 | while (!_schedRequest) { 75 | pthread_cond_wait(&_schedCond, &nOS_criticalSection); 76 | } 77 | _schedRequest = false; 78 | 79 | /* Find next high prio thread and give him permission to run */ 80 | nOS_highPrioThread = nOS_FindHighPrioThread(); 81 | if (nOS_highPrioThread == NULL) { 82 | nOS_highPrioThread = &nOS_mainHandle; 83 | } 84 | nOS_runningThread = nOS_highPrioThread; 85 | nOS_highPrioThread->stackPtr->running = true; 86 | pthread_cond_signal(&nOS_highPrioThread->stackPtr->cond); 87 | } 88 | 89 | pthread_mutex_unlock(&nOS_criticalSection); 90 | 91 | return 0; 92 | } 93 | 94 | static void* _SysTick (void *arg) 95 | { 96 | while (!nOS_running) { 97 | usleep(1000); 98 | } 99 | 100 | while (true) { 101 | usleep(1000000/NOS_CONFIG_TICKS_PER_SECOND); 102 | 103 | pthread_mutex_lock(&nOS_criticalSection); 104 | nOS_criticalNestingCounter = 1; 105 | 106 | /* Simulate entry in interrupt */ 107 | nOS_isrNestingCounter = 1; 108 | 109 | nOS_Tick(1); 110 | 111 | /* Simulate exit of interrupt */ 112 | nOS_isrNestingCounter = 0; 113 | 114 | nOS_criticalNestingCounter = 0; 115 | pthread_mutex_unlock(&nOS_criticalSection); 116 | } 117 | 118 | return 0; 119 | } 120 | 121 | void nOS_InitSpecific (void) 122 | { 123 | pthread_t pthread; 124 | pthread_mutexattr_t attr; 125 | 126 | nOS_criticalNestingCounter = 0; 127 | pthread_mutexattr_init(&attr); 128 | pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); 129 | pthread_mutex_init(&nOS_criticalSection, &attr); 130 | 131 | pthread_cond_init (&_schedCond, NULL); 132 | 133 | nOS_mainHandle.stackPtr = &_mainStack; 134 | _mainStack.entry = NULL; 135 | _mainStack.arg = NULL; 136 | _mainStack.crit = 0; 137 | _mainStack.started = true; 138 | _mainStack.running = true; 139 | pthread_cond_init(&_mainStack.cond, NULL); 140 | 141 | pthread_mutex_lock(&nOS_criticalSection); 142 | 143 | _schedStarted = false; 144 | _schedRequest = false; 145 | pthread_create(&pthread, NULL, _Scheduler, NULL); 146 | 147 | /* Wait until scheduler is running and waiting for request */ 148 | while (!_schedStarted) { 149 | pthread_cond_wait(&_schedCond, &nOS_criticalSection); 150 | } 151 | 152 | /* Create a SysTick thread to allow sleep/timeout */ 153 | pthread_create(&pthread, NULL, _SysTick, NULL); 154 | 155 | pthread_mutex_unlock(&nOS_criticalSection); 156 | } 157 | 158 | /* Called from critical section */ 159 | void nOS_InitContext (nOS_Thread *thread, nOS_Stack *stack, size_t ssize, nOS_ThreadEntry entry, void *arg) 160 | { 161 | thread->stackPtr = stack; 162 | stack->entry = entry; 163 | stack->arg = arg; 164 | stack->crit = 0; 165 | stack->started = false; 166 | stack->running = false; 167 | 168 | pthread_cond_init(&stack->cond, NULL); 169 | 170 | pthread_create(&stack->handle, NULL, _Entry, thread); 171 | 172 | /* Wait until thread is started and waiting to run */ 173 | while (!stack->started) { 174 | pthread_cond_wait(&stack->cond, &nOS_criticalSection); 175 | } 176 | } 177 | 178 | /* Called from critical section */ 179 | void nOS_SwitchContext (void) 180 | { 181 | nOS_Stack *stack = nOS_runningThread->stackPtr; 182 | 183 | /* Backup critical nesting counter and stop running */ 184 | stack->crit = nOS_criticalNestingCounter; 185 | stack->running = false; 186 | 187 | /* Send scheduling request */ 188 | _schedRequest = true; 189 | pthread_cond_signal(&_schedCond); 190 | 191 | /* Wait until we have permission to run */ 192 | while (!stack->running) { 193 | pthread_cond_wait(&stack->cond, &nOS_criticalSection); 194 | } 195 | 196 | /* Restore critical nesting counter */ 197 | nOS_criticalNestingCounter = stack->crit; 198 | } 199 | 200 | int nOS_Print (const char *format, ...) 201 | { 202 | va_list args; 203 | nOS_StatusReg sr; 204 | int ret; 205 | 206 | va_start(args, format); 207 | 208 | nOS_EnterCritical(sr); 209 | ret = vprintf(format, args); 210 | nOS_LeaveCritical(sr); 211 | 212 | va_end(args); 213 | 214 | return ret; 215 | } 216 | 217 | #ifdef __cplusplus 218 | } 219 | #endif 220 | -------------------------------------------------------------------------------- /src/port/XC16/PIC24/nOSPort.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2019 Jim Tremblay 3 | * 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | */ 8 | 9 | #define NOS_PRIVATE 10 | #include "nOS.h" 11 | 12 | #ifdef __cplusplus 13 | extern "C" { 14 | #endif 15 | 16 | #if (NOS_CONFIG_ISR_STACK_SIZE > 0) 17 | static nOS_Stack _isrStack[NOS_CONFIG_ISR_STACK_SIZE]; 18 | #endif 19 | 20 | void nOS_InitContext (nOS_Thread *thread, nOS_Stack *stack, size_t ssize, nOS_ThreadEntry entry, void *arg) 21 | { 22 | nOS_Stack *tos = (nOS_Stack*)((uint16_t)stack & 0xFFFE); 23 | #if (NOS_CONFIG_DEBUG > 0) 24 | size_t i; 25 | 26 | for (i = 0; i < ssize; i++) { 27 | stack[i] = 0xFFFF; 28 | } 29 | #endif 30 | 31 | *tos++ = (nOS_Stack)entry; /* PC LSB */ 32 | *tos++ = 0; /* PC MSB */ 33 | *tos++ = 0; /* SR */ 34 | *tos++ = (nOS_Stack)arg; /* W0 */ 35 | #if (NOS_CONFIG_DEBUG > 0) 36 | *tos++ = 0x1111; /* W1 */ 37 | *tos++ = 0x2222; /* W2 */ 38 | *tos++ = 0x3333; /* W3 */ 39 | *tos++ = 0x4444; /* W4 */ 40 | *tos++ = 0x5555; /* W5 */ 41 | *tos++ = 0x6666; /* W6 */ 42 | *tos++ = 0x7777; /* W7 */ 43 | *tos++ = 0x8888; /* W8 */ 44 | *tos++ = 0x9999; /* W9 */ 45 | *tos++ = 0xaaaa; /* W10 */ 46 | *tos++ = 0xbbbb; /* W11 */ 47 | *tos++ = 0xcccc; /* W12 */ 48 | *tos++ = 0xdddd; /* W13 */ 49 | *tos++ = 0xeeee; /* W14 */ 50 | *tos++ = 0x1234; /* RCOUNT */ 51 | *tos++ = 0x5678; /* TBLPAG */ 52 | #else 53 | tos += 16; /* W1 to W14, RCOUNT, TBLPAG */ 54 | #endif 55 | *tos++ = CORCON; /* CORCON */ 56 | #ifdef __HAS_EDS__ 57 | *tos++ = DSRPAG; /* DSRPAG */ 58 | *tos++ = DSWPAG; /* DSWPAG */ 59 | #else 60 | *tos++ = PSVPAG; /* PSVPAG */ 61 | #endif 62 | 63 | thread->stackPtr = tos; 64 | } 65 | 66 | void __attribute__((naked)) nOS_SwitchContext (void) 67 | { 68 | /* Enter critical is not needed here, interrupts are already disabled */ 69 | __asm volatile ( 70 | /* Push all working registers */ 71 | "PUSH SR \n" 72 | "PUSH.D W0 \n" 73 | "PUSH.D W2 \n" 74 | "PUSH.D W4 \n" 75 | "PUSH.D W6 \n" 76 | "PUSH.D W8 \n" 77 | "PUSH.D W10 \n" 78 | "PUSH.D W12 \n" 79 | "PUSH W14 \n" 80 | "PUSH RCOUNT \n" 81 | "PUSH TBLPAG \n" 82 | "PUSH CORCON \n" 83 | PUSH_PAGE_ADDRESS 84 | 85 | /* Get the location of nOS_runningThread */ 86 | "MOV #_nOS_runningThread, W0 \n" 87 | "MOV [W0], W1 \n" 88 | 89 | /* Save SP to nOS_Thread object of current running thread */ 90 | "MOV W15, [W1] \n" 91 | 92 | /* Get the value of nOS_highPrioThread */ 93 | "MOV _nOS_highPrioThread, W2 \n" 94 | 95 | /* Copy nOS_highPrioThread to nOS_runningThread */ 96 | "MOV W2, [W0] \n" 97 | 98 | /* Restore SP from nOS_Thread object of high prio thread */ 99 | "MOV [W2], W15 \n" 100 | 101 | /* Pop all working registers */ 102 | POP_PAGE_ADDRESS 103 | "POP CORCON \n" 104 | "POP TBLPAG \n" 105 | "POP RCOUNT \n" 106 | "POP W14 \n" 107 | "POP.D W12 \n" 108 | "POP.D W10 \n" 109 | "POP.D W8 \n" 110 | "POP.D W6 \n" 111 | "POP.D W4 \n" 112 | "POP.D W2 \n" 113 | "POP.D W0 \n" 114 | "POP SR \n" 115 | ); 116 | } 117 | 118 | nOS_Stack *nOS_EnterISR (nOS_Stack *sp) 119 | { 120 | #if (NOS_CONFIG_SAFE > 0) 121 | if (nOS_running) 122 | #endif 123 | { 124 | // Enter critical here is not needed, interrupts are already disabled 125 | if (nOS_isrNestingCounter == 0) { 126 | nOS_runningThread->stackPtr = sp; 127 | #if (NOS_CONFIG_ISR_STACK_SIZE > 0) 128 | sp = &_isrStack[0]; 129 | #else 130 | sp = nOS_mainHandle.stackPtr; 131 | #endif 132 | } 133 | nOS_isrNestingCounter++; 134 | } 135 | 136 | return sp; 137 | } 138 | 139 | nOS_Stack *nOS_LeaveISR (nOS_Stack *sp) 140 | { 141 | nOS_Thread *highPrioThread; 142 | 143 | #if (NOS_CONFIG_SAFE > 0) 144 | if (nOS_running) 145 | #endif 146 | { 147 | // Enter critical here is not needed, interrupts are already disabled 148 | nOS_isrNestingCounter--; 149 | if (nOS_isrNestingCounter == 0) { 150 | #if (NOS_CONFIG_SCHED_LOCK_ENABLE > 0) 151 | if (nOS_lockNestingCounter == 0) 152 | #endif 153 | { 154 | highPrioThread = nOS_FindHighPrioThread(); 155 | if (highPrioThread != NULL) { 156 | #if (NOS_CONFIG_SCHED_PREEMPTIVE_ENABLE > 0) || (NOS_CONFIG_SCHED_ROUND_ROBIN_ENABLE > 0) 157 | nOS_highPrioThread = highPrioThread; 158 | nOS_runningThread = nOS_highPrioThread; 159 | #endif 160 | } else { 161 | nOS_highPrioThread = &nOS_mainHandle; 162 | nOS_runningThread = nOS_highPrioThread; 163 | } 164 | } 165 | sp = nOS_runningThread->stackPtr; 166 | } 167 | } 168 | 169 | return sp; 170 | } 171 | 172 | #ifdef __cplusplus 173 | } 174 | #endif 175 | --------------------------------------------------------------------------------