-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathavrcontext_impl.h
More file actions
109 lines (95 loc) · 3.51 KB
/
Copy pathavrcontext_impl.h
File metadata and controls
109 lines (95 loc) · 3.51 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
/*
Author: Artem Boldariev <artem@boldariev.com>
The software distributed under the terms of the MIT/Expat license.
See LICENSE.txt for license details.
*/
/*
This file contains definitions of the context manipulation functions.
It meant to be included after 'avrcontext.h'.
In general, you should include it only once across the project.
*/
#ifndef AVRCONTEXT_IMPL_H
#define AVRCONTEXT_IMPL_H
#ifdef __AVR__
void avr_getcontext(avr_context_t *cp) __attribute__ ((naked));
void avr_getcontext(avr_context_t *cp)
{
(void)cp; /* to avoid compiler warnings */
AVR_SAVE_CONTEXT(
"",
"mov r30, r24\n"
"mov r31, r25\n");
__asm__ __volatile__ ("ret\n");
}
void avr_setcontext(const avr_context_t *cp) __attribute__ ((naked));
void avr_setcontext(const avr_context_t *cp)
{
(void)cp; /* to avoid compiler warnings */
AVR_RESTORE_CONTEXT(
"mov r30, r24\n"
"mov r31, r25\n");
__asm__ __volatile__ ("ret\n");
}
void avr_swapcontext(avr_context_t *oucp, const avr_context_t *ucp) __attribute__ ((naked));
void avr_swapcontext(avr_context_t *oucp, const avr_context_t *ucp)
{
(void)oucp; /* to avoid compiler warnings */
(void)ucp;
AVR_SAVE_CONTEXT(
"",
"mov r30, r24\n"
"mov r31, r25\n");
AVR_RESTORE_CONTEXT(
"mov r30, r22\n"
"mov r31, r23\n");
__asm__ __volatile__ ("ret\n");
}
#ifdef __cplusplus
extern "C" {
#endif /*__cplusplus **/
static void avr_makecontext_callfunc(const avr_context_t *successor, void (*func)(void *), void *funcarg);
#ifdef __cplusplus
}
#endif /*__cplusplus */
static void avr_makecontext_callfunc(const avr_context_t *successor, void (*func)(void *), void *funcarg)
{
func(funcarg);
avr_setcontext(successor);
}
void avr_makecontext(avr_context_t *cp, void *stackp, const size_t stack_size, const avr_context_t *successor_cp, void (*funcp)(void *), void *funcargp)
{
uint16_t addr;
uint8_t *p = (uint8_t *)&addr;
/* initialise stack pointer and program counter */
cp->sp.ptr = ((uint8_t *)stackp + stack_size - 1);
cp->pc.ptr = (void *)avr_makecontext_callfunc;
/* initialise registers to pass arguments to avr_makecontext_callfunc */
/* successor: registers 24,25; func registers 23, 22; funcarg: 21, 20. */
addr = (uint16_t)successor_cp;
cp->r[24] = p[0];
cp->r[25] = p[1];
addr = (uint16_t)funcp;
cp->r[22] = p[0];
cp->r[23] = p[1];
addr = (uint16_t)funcargp;
cp->r[20] = p[0];
cp->r[21] = p[1];
}
#if __cplusplus >= 201103L
/*
See bug: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=49171
*/
inline void avr_context_sanity_checks(void)
{
avr_context_t test;
static_assert(reinterpret_cast<uintptr_t>(&test) == reinterpret_cast<uintptr_t>(&test.sreg));
static_assert(sizeof(avr_context_t) == 37);
static_assert(reinterpret_cast<uintptr_t>(&test.sp.part.low) - reinterpret_cast<uintptr_t>(&test) == AVR_CONTEXT_OFFSET_SP_L);
static_assert(reinterpret_cast<uintptr_t>(&test.sp.part.high) - reinterpret_cast<uintptr_t>(&test) == AVR_CONTEXT_OFFSET_SP_H);
static_assert(reinterpret_cast<uintptr_t>(&test.pc.part.low) - reinterpret_cast<uintptr_t>(&test) == AVR_CONTEXT_OFFSET_PC_L);
static_assert(reinterpret_cast<uintptr_t>(&test.pc.part.high) - reinterpret_cast<uintptr_t>(&test) == AVR_CONTEXT_OFFSET_PC_H);
static_assert(reinterpret_cast<uintptr_t>(&test.sp.part.high) - reinterpret_cast<uintptr_t>(&test.r[26]) == AVR_CONTEXT_BACK_OFFSET_R26);
}
#endif /* __cplusplus */
#endif /* __AVR__ */
#endif /* AVRCONTEXT_IMPL_H */