agileRTOS (zrtos)  Version 0.8.0 (ghostbuster)
atmega2560.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2024 ykat UG (haftungsbeschraenkt) - All Rights Reserved
3  *
4  * Permission for non-commercial use is hereby granted,
5  * free of charge, without warranty of any kind.
6  */
7 #ifndef ZRTOS_ARCH_ATMEGA2560_H
8 #define ZRTOS_ARCH_ATMEGA2560_H
9 #ifdef __cplusplus
10 extern "C" {
11 #endif
12 
13 
14 #if defined(ZRTOS_ARCH__ATMEGA2560) || defined(__DOXYGEN__)
15 #define ZRTOS_ARCH__FOUND
16 
17 #include <util/delay_basic.h>
18 
23 
24 #define ZRTOS_ARCH__BYTE_ORDER ZRTOS_ARCH__BYTE_ORDER_LITTLE_ENDIAN
25 
26 #define ZRTOS_ARCH__CPU_CLOCK_HZ ( ( uint32_t ) F_CPU ) // thiz F_CPU variable set by the environment
27 
28 #define ZRTOS_ARCH__BYTE_ALIGNMENT (1)
29 
30 #define ZRTOS_ARCH__FATAL() ((void(*)(void))0)();
31 
32 #define ZRTOS_ARCH__SET_STACK_PTR(ptr) \
33  (SP = (uint16_t)(ptr))
34 
35 #define ZRTOS_ARCH__GET_STACK_PTR() \
36  ((void*)SP)
37 
38 #define ZRTOS_ARCH__IS_INTERRUPTS_DISABLED() \
39  ((SREG & 0x80) == 0)
40 
41 #define ZRTOS_ARCH__IS_INTERRUPTS_ENABLED() \
42  ((SREG & 0x80) > 0)
43 
44 #define ZRTOS_ARCH__DISABLE_INTERRUPTS() \
45  asm volatile ( "cli" :: );
46 
47 #define ZRTOS_ARCH__ENABLE_INTERRUPTS() \
48  asm volatile ( "sei" :: );
49 
50 
51 zrtos_arch_stack_t * zrtos_arch__cpu_state_init_helper( zrtos_arch_stack_t * pxTopOfStack,
52  zrtos_arch_callback_t pxCode,
53  void * pvParameters )
54 {
55 uint16_t usAddress;
56 
57  /* Simulate how the stack would look after a call to vPortYield() generated by
58  * the compiler. */
59 
60  /* The start of the task code will be popped off the stack last, so place
61  * it on first. */
62  usAddress = ( uint16_t ) pxCode;
63  *pxTopOfStack = ( zrtos_arch_stack_t ) ( usAddress & ( uint16_t ) 0x00ff );
64  pxTopOfStack--;
65 
66  usAddress >>= 8;
67  *pxTopOfStack = ( zrtos_arch_stack_t ) ( usAddress & ( uint16_t ) 0x00ff );
68  pxTopOfStack--;
69 
70 #if defined(__AVR_3_BYTE_PC__)
71 
72  /* The AVR ATmega2560/ATmega2561 have 256KBytes of program memory and a 17-bit
73  * program counter. When a code address is stored on the stack, it takes 3 bytes
74  * instead of 2 for the other ATmega* chips.
75  *
76  * Store 0 as the top byte since we force all task routines to the bottom 128K
77  * of flash. We do this by using the .lowtext label in the linker script.
78  *
79  * In order to do this properly, we would need to get a full 3-byte pointer to
80  * pxCode. That requires a change to GCC. Not likely to happen any time soon.
81  */
82  *pxTopOfStack = 0;
83  pxTopOfStack--;
84 #endif
85 
86  /* Next simulate the stack as if after a call to portSAVE_CONTEXT().
87  * portSAVE_CONTEXT places the flags on the stack immediately after r0
88  * to ensure the interrupts get disabled as soon as possible, and so ensuring
89  * the stack use is minimal should a context switch interrupt occur. */
90  *pxTopOfStack = ( zrtos_arch_stack_t ) 0x00; /* R0 */
91  pxTopOfStack--;
92  *pxTopOfStack = 0x80;//enable interrupts
93  pxTopOfStack--;
94 
95 #if defined(__AVR_3_BYTE_PC__)
96 
97  /* If we have an ATmega256x, we are also saving the EIND register.
98  * We should default to 0.
99  */
100  *pxTopOfStack = ( zrtos_arch_stack_t ) 0x00; /* EIND */
101  pxTopOfStack--;
102 #endif
103 
104 #if defined(__AVR_HAVE_RAMPZ__)
105 
106  /* We are saving the RAMPZ register.
107  * We should default to 0.
108  */
109  *pxTopOfStack = ( zrtos_arch_stack_t ) 0x00; /* RAMPZ */
110  pxTopOfStack--;
111 #endif
112 
113  /* Now the remaining registers. The compiler expects R1 to be 0. */
114  *pxTopOfStack = ( zrtos_arch_stack_t ) 0x00; /* R1 */
115 
116  /* Leave R2 - R23 untouched */
117  pxTopOfStack -= 23;
118 
119  /* Place the parameter on the stack in the expected location. */
120  usAddress = ( uint16_t ) pvParameters;
121  *pxTopOfStack = ( zrtos_arch_stack_t ) ( usAddress & ( uint16_t ) 0x00ff );
122  pxTopOfStack--;
123 
124  usAddress >>= 8;
125  *pxTopOfStack = ( zrtos_arch_stack_t ) ( usAddress & ( uint16_t ) 0x00ff );
126 
127  /* Leave register R26 - R31 untouched */
128  pxTopOfStack -= 7;
129 
130  return pxTopOfStack;
131 }
132 
133 zrtos_arch_stack_t *zrtos_arch__cpu_state_init_b(
134  zrtos_arch_stack_t *thiz
135  //,size_t length
136  ,zrtos_arch_callback_t callback
137  ,void *args
138 ){
139 /*
140  ZRTOS_DEBUG__CODE(
141  static uint8_t pattern = 0xF0;
142  memset(thiz,(int)(pattern++),length);
143  );
144 */
146  thiz
147  ,callback
148  ,args
149  );
150 }
151 
152 zrtos_arch_stack_t *zrtos_arch__cpu_state_init_a(
153  zrtos_arch_stack_t *thiz
154  //,size_t length
155  ,zrtos_arch_callback_t callback
156  ,void *args
157 ){
158  zrtos_arch_stack_t *pxTopOfStack = thiz;
159  zrtos_arch_stack_t *pxTopOfStackTmp = pxTopOfStack;
160  uint16_t usAddress = (uint16_t)callback;
161  zrtos_arch_stack_signed_t usValue = 0;
162 
163  pxTopOfStack -= 3;
164 
165  for(;usValue < 32;){
166  /*if(usValue == 0x0A
167  || usValue == 0x1A
168  || usValue == 0x2A){
169  usValue+=6;
170  }*/
171  *pxTopOfStack-- = usValue++;
172  }
173 
174  pxTopOfStackTmp[0] = usAddress & 0x00ff;
175  pxTopOfStackTmp[-1] = (usAddress >> 8) & 0x00ff;
176  pxTopOfStackTmp[-2] = 0;
177  pxTopOfStackTmp[-3] = 0x80;//enable interrupts
178  pxTopOfStackTmp[-4] = 0;
179  usAddress = (uint16_t)args;
180  pxTopOfStackTmp[-27] = usAddress & 0x00ff;
181  pxTopOfStackTmp[-28] = (usAddress >> 8) & 0x00ff;
182 
183  return pxTopOfStack;
184 }
185 
186 #if 1
187 # define zrtos_arch__cpu_state_init zrtos_arch__cpu_state_init_a
188 #else
189 # define zrtos_arch__cpu_state_init zrtos_arch__cpu_state_init_b
190 #endif
191 
192 #define ZRTOS_ARCH__GET_CPU_STATE_BUFFER_LENGTH() 33
193 #define ZRTOS_ARCH__GET_FN_CALL_STACK_LENGTH() 20
194 
195 #define ZRTOS_ARCH__SAVE_CPU_STATE() \
196  ;__asm__ __volatile__( \
197  "push __tmp_reg__ \n\t" \
198  "in __tmp_reg__, __SREG__ \n\t" \
199  "cli \n\t" \
200  "push __tmp_reg__ \n\t" \
201  "push __zero_reg__ \n\t" \
202  "clr __zero_reg__ \n\t" \
203  "push r2 \n\t" \
204  "push r3 \n\t" \
205  "push r4 \n\t" \
206  "push r5 \n\t" \
207  "push r6 \n\t" \
208  "push r7 \n\t" \
209  "push r8 \n\t" \
210  "push r9 \n\t" \
211  "push r10 \n\t" \
212  "push r11 \n\t" \
213  "push r12 \n\t" \
214  "push r13 \n\t" \
215  "push r14 \n\t" \
216  "push r15 \n\t" \
217  "push r16 \n\t" \
218  "push r17 \n\t" \
219  "push r18 \n\t" \
220  "push r19 \n\t" \
221  "push r20 \n\t" \
222  "push r21 \n\t" \
223  "push r22 \n\t" \
224  "push r23 \n\t" \
225  "push r24 \n\t" \
226  "push r25 \n\t" \
227  "push r26 \n\t" \
228  "push r27 \n\t" \
229  "push r28 \n\t" \
230  "push r29 \n\t" \
231  "push r30 \n\t" \
232  "push r31 \n\t" \
233  );
234 
235 #define ZRTOS_ARCH__SAVE_CPU_STATE_EX(ptr) \
236  ZRTOS_ARCH__SAVE_CPU_STATE(); \
237  ;__asm__ __volatile__( \
238  "in __tmp_reg__, __SP_L__ \n\t" \
239  "sts %0, __tmp_reg__ \n\t" \
240  "in __tmp_reg__, __SP_H__ \n\t" \
241  "sts %0 + 1, __tmp_reg__ \n\t" \
242  : "=m" (ptr) \
243  );
244 
245 #define ZRTOS_ARCH__LOAD_CPU_STATE() \
246  ;__asm__ __volatile__( \
247  "pop r31 \n\t" \
248  "pop r30 \n\t" \
249  "pop r29 \n\t" \
250  "pop r28 \n\t" \
251  "pop r27 \n\t" \
252  "pop r26 \n\t" \
253  "pop r25 \n\t" \
254  "pop r24 \n\t" \
255  "pop r23 \n\t" \
256  "pop r22 \n\t" \
257  "pop r21 \n\t" \
258  "pop r20 \n\t" \
259  "pop r19 \n\t" \
260  "pop r18 \n\t" \
261  "pop r17 \n\t" \
262  "pop r16 \n\t" \
263  "pop r15 \n\t" \
264  "pop r14 \n\t" \
265  "pop r13 \n\t" \
266  "pop r12 \n\t" \
267  "pop r11 \n\t" \
268  "pop r10 \n\t" \
269  "pop r9 \n\t" \
270  "pop r8 \n\t" \
271  "pop r7 \n\t" \
272  "pop r6 \n\t" \
273  "pop r5 \n\t" \
274  "pop r4 \n\t" \
275  "pop r3 \n\t" \
276  "pop r2 \n\t" \
277  "pop __zero_reg__ \n\t" \
278  "pop __tmp_reg__ \n\t" \
279  "out __SREG__, __tmp_reg__ \n\t" \
280  "pop __tmp_reg__ \n\t" \
281  );
282 
283 #define ZRTOS_ARCH__LOAD_CPU_STATE_EX(ptr) \
284  ;__asm__ __volatile__( \
285  "lds __tmp_reg__, %0 \n\t" \
286  "out __SP_L__, __tmp_reg__ \n\t" \
287  "lds __tmp_reg__, %0 + 1 \n\t" \
288  "out __SP_H__, __tmp_reg__ \n\t" \
289  : : "m" (ptr) \
290  ); \
291  ZRTOS_ARCH__LOAD_CPU_STATE();
292 
293 #define ZRTOS_ARCH__RETURN_FROM_INTERRUPT() \
294  __asm__ __volatile__("reti");
295 
297  _delay_loop_2((ZRTOS_ARCH__CPU_CLOCK_HZ/4000000) * us);
298 }
299 
301  while(ms--){
303  }
304 }
305 
306 #endif
307 
308 #ifdef __cplusplus
309 }
310 #endif
311 #endif
uint8_t zrtos_arch_stack_t
Definition: atmega2560.h:19
zrtos_arch_stack_t * zrtos_arch__cpu_state_init_b(zrtos_arch_stack_t *thiz, zrtos_arch_callback_t callback, void *args)
Definition: atmega2560.h:133
#define ZRTOS_ARCH__CPU_CLOCK_HZ
Definition: atmega2560.h:26
void zrtos_arch__delay_microseconds(uint16_t us)
Definition: atmega2560.h:296
void zrtos_arch__delay_milliseconds(uint16_t ms)
Definition: atmega2560.h:300
zrtos_arch_stack_t * zrtos_arch__cpu_state_init_a(zrtos_arch_stack_t *thiz, zrtos_arch_callback_t callback, void *args)
Definition: atmega2560.h:152
int8_t zrtos_arch_stack_signed_t
Definition: atmega2560.h:20
uint16_t zrtos_arch_gpio_value_analog_t
Definition: atmega2560.h:22
void(* zrtos_arch_callback_t)(void *arg)
Definition: arch.h:17
zrtos_arch_stack_t * zrtos_arch__cpu_state_init_helper(zrtos_arch_stack_t *pxTopOfStack, zrtos_arch_callback_t pxCode, void *pvParameters)
Definition: atmega2560.h:51
static uint8_t
Definition: mcp2515.h:159
uint8_t zrtos_arch_gpio_pin_t
Definition: atmega2560.h:21