Mark3 Realtime Kernel
threadport.h
Go to the documentation of this file.
1 /*===========================================================================
2  _____ _____ _____ _____
3  ___| _|__ __|_ |__ __|__ |__ __| __ |__ ______
4 | \ / | || \ || | || |/ / ||___ |
5 | \/ | || \ || \ || \ ||___ |
6 |__/\__/|__|_||__|\__\ __||__|\__\ __||__|\__\ __||______|
7  |_____| |_____| |_____| |_____|
8 
9 --[Mark3 Realtime Platform]--------------------------------------------------
10 
11 Copyright (c) 2012 - 2019 m0slevin, all rights reserved.
12 See license.txt for more information
13 =========================================================================== */
20 #pragma once
21 
22 #include "portcfg.h"
23 #include "kerneltypes.h"
24 
25 #include <avr/io.h>
26 #include <avr/interrupt.h>
27 
28 namespace Mark3
29 {
30 // clang-format off
31 //---------------------------------------------------------------------------
32 #define ASM(x) asm volatile(x);
33 
34 //---------------------------------------------------------------------------
36 #define PORT_TOP_OF_STACK(x, y) (reinterpret_cast<K_WORD*>(reinterpret_cast<K_ADDR>(x) + (static_cast<K_ADDR>(y) - 1)))
37 #define PORT_PUSH_TO_STACK(x, y) *x = y; x--;
39 
40 //---------------------------------------------------------------------------
42 #define Thread_SaveContext() \
43 ASM("push r0"); \
44 ASM("in r0, __SREG__"); \
45 ASM("cli"); \
46 ASM("push r0"); \
47 ASM("push r1"); \
48 ASM("clr r1"); \
49 ASM("push r2"); \
50 ASM("push r3"); \
51 ASM("push r4"); \
52 ASM("push r5"); \
53 ASM("push r6"); \
54 ASM("push r7"); \
55 ASM("push r8"); \
56 ASM("push r9"); \
57 ASM("push r10"); \
58 ASM("push r11"); \
59 ASM("push r12"); \
60 ASM("push r13"); \
61 ASM("push r14"); \
62 ASM("push r15"); \
63 ASM("push r16"); \
64 ASM("push r17"); \
65 ASM("push r18"); \
66 ASM("push r19"); \
67 ASM("push r20"); \
68 ASM("push r21"); \
69 ASM("push r22"); \
70 ASM("push r23"); \
71 ASM("push r24"); \
72 ASM("push r25"); \
73 ASM("push r26"); \
74 ASM("push r27"); \
75 ASM("push r28"); \
76 ASM("push r29"); \
77 ASM("push r30"); \
78 ASM("push r31"); \
79 ASM("in r0, 0x3B"); \
80 ASM("push r0"); \
81 ASM("lds r26, g_pclCurrent"); \
82 ASM("lds r27, g_pclCurrent + 1"); \
83 ASM("adiw r26, 4"); \
84 ASM("in r0, 0x3D"); \
85 ASM("st x+, r0"); \
86 ASM("in r0, 0x3E"); \
87 ASM("st x+, r0");
88 
89 //---------------------------------------------------------------------------
91 #define Thread_RestoreContext() \
92 ASM("lds r26, g_pclCurrent"); \
93 ASM("lds r27, g_pclCurrent + 1");\
94 ASM("adiw r26, 4"); \
95 ASM("ld r28, x+"); \
96 ASM("out 0x3D, r28"); \
97 ASM("ld r29, x+"); \
98 ASM("out 0x3E, r29"); \
99 ASM("pop r0"); \
100 ASM("out 0x3B, r0"); \
101 ASM("pop r31"); \
102 ASM("pop r30"); \
103 ASM("pop r29"); \
104 ASM("pop r28"); \
105 ASM("pop r27"); \
106 ASM("pop r26"); \
107 ASM("pop r25"); \
108 ASM("pop r24"); \
109 ASM("pop r23"); \
110 ASM("pop r22"); \
111 ASM("pop r21"); \
112 ASM("pop r20"); \
113 ASM("pop r19"); \
114 ASM("pop r18"); \
115 ASM("pop r17"); \
116 ASM("pop r16"); \
117 ASM("pop r15"); \
118 ASM("pop r14"); \
119 ASM("pop r13"); \
120 ASM("pop r12"); \
121 ASM("pop r11"); \
122 ASM("pop r10"); \
123 ASM("pop r9"); \
124 ASM("pop r8"); \
125 ASM("pop r7"); \
126 ASM("pop r6"); \
127 ASM("pop r5"); \
128 ASM("pop r4"); \
129 ASM("pop r3"); \
130 ASM("pop r2"); \
131 ASM("pop r1"); \
132 ASM("pop r0"); \
133 ASM("out __SREG__, r0"); \
134 ASM("pop r0");
135 
136 //---------------------------------------------------------------------------
137 static constexpr auto SR_ = uint8_t{0x3F};
138 extern "C" {
139  extern K_WORD g_kwSFR;
140  extern K_WORD g_kwCriticalCount;
141 }
142 
143 //---------------------------------------------------------------------------
144 inline uint8_t PORT_CLZ(uint8_t in_)
145 {
146  static const uint8_t u8Lookup[] = {4, 3, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0};
147  uint8_t hi = __builtin_avr_swap(in_) & 0x0F;
148  if (hi) {
149  return u8Lookup[hi];
150  }
151  return 4 + u8Lookup[in_];
152 }
153 
154 //---------------------------------------------------------------------------
155 inline void PORT_IRQ_ENABLE()
156 {
157  ASM("sei");
158 }
159 
160 //---------------------------------------------------------------------------
161 inline void PORT_IRQ_DISABLE()
162 {
163  ASM("cli");
164 }
165 
166 //---------------------------------------------------------------------------
167 inline void PORT_CS_ENTER()
168 {
169  auto u8SFR = _SFR_IO8(SR_);
170  ASM("cli");
171  if (!g_kwCriticalCount) {
172  g_kwSFR = u8SFR;
173  }
175 }
176 
177 //---------------------------------------------------------------------------
178 inline void PORT_CS_EXIT()
179 {
181  if (!g_kwCriticalCount) {
182  _SFR_IO8(SR_) = g_kwSFR;
183  }
184 }
185 
186 //---------------------------------------------------------------------------
188 {
189  return g_kwCriticalCount;
190 }
191 } // namespace Mark3
#define K_WORD
Size of a data word.
Definition: portcfg.h:62
Basic data type primatives used throughout the OS.
static constexpr auto SR_
Definition: threadport.h:137
K_WORD g_kwCriticalCount
Definition: threadport.cpp:36
void PORT_CS_ENTER()
Definition: threadport.h:167
Definition: atomic.cpp:23
K_WORD g_kwSFR
Definition: threadport.cpp:35
uint8_t PORT_CLZ(uint8_t in_)
Definition: threadport.h:144
void PORT_CS_EXIT()
Definition: threadport.h:178
Mark3 Port Configuration.
void PORT_IRQ_ENABLE()
Definition: threadport.h:155
void PORT_IRQ_DISABLE()
Definition: threadport.h:161
#define ASM(x)
Definition: threadport.h:32
K_WORD PORT_CS_NESTING()
Definition: threadport.h:187