-
Notifications
You must be signed in to change notification settings - Fork 11
Expand file tree
/
Copy pathdebug.c
More file actions
119 lines (109 loc) · 2.78 KB
/
Copy pathdebug.c
File metadata and controls
119 lines (109 loc) · 2.78 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
109
110
111
112
113
114
115
116
117
118
119
/*
* Copyright (C) 2019 saybur
*
* This file is part of scuznet.
*
* scuznet is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* scuznet is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with scuznet. If not, see <https://www.gnu.org/licenses/>.
*/
#include <util/delay.h>
#include "config.h"
#include "debug.h"
extern uint8_t _end;
extern uint8_t __stack;
/*
* Fills the stack with 0xC5 to assist with stack usage diagnostics. Both this
* and the subsequent debug_stack_check() are (very slightly) modified from the
* public-domain code here:
*
* https://www.avrfreaks.net/forum/soft-c-avrgcc-monitoring-stack-usage
*/
void stack_paint(void) __attribute__ ((naked)) __attribute__ ((section (".init1")));
void stack_paint(void)
{
__asm__ __volatile__(
"ldi r30, lo8(_end)" "\n\t"
"ldi r31, hi8(_end)" "\n\t"
"ldi r24, lo8(0xC5)" "\n\t"
"ldi r25, hi8(__stack)" "\n\t"
".paint_loop:" "\n\t"
"st Z+,r24" "\n\t"
".paint_cmp:" "\n\t"
"cpi r30, lo8(__stack)" "\n\t"
"cpc r31, r25" "\n\t"
"brlo .paint_loop" "\n\t"
"breq .paint_loop" "\n\t"
);
}
void debug_init(void)
{
DEBUG_PORT.OUTSET |= DEBUG_PIN_TX;
DEBUG_PORT.DIRSET |= DEBUG_PIN_TX;
DEBUG_USART.BAUDCTRLA = 3; // 500kbps
DEBUG_USART.CTRLB |= USART_TXEN_bm;
#if defined(LED_POW_PORT) && defined(LED_POW_PIN)
LED_POW_PORT.DIRSET = LED_POW_PIN;
#endif
LED_PORT.OUT &= ~LED_PIN;
}
uint16_t debug_stack_unused(void)
{
const uint8_t *p = &_end;
uint16_t c = 0;
while (*p == 0xC5 && p <= &__stack)
{
p++; c++;
}
return c;
}
void fatal(uint8_t lflash, uint8_t sflash)
{
// disable all but high-level (/RST) interrupts
PMIC.CTRL = PMIC_HILVLEN_bm;
// disable the watchdog timer
__asm__ __volatile__(
"ldi r24, %0" "\n\t"
"out %1, r24" "\n\t"
"ldi r24, %2" "\n\t"
"sts %3, r24" "\n\t"
:
: "M" (CCP_IOREG_gc), "i" (&CCP),
"M" (WDT_CEN_bm), "i" (&(WDT.CTRL))
: "r24"
);
// report to the debugger
debug(DEBUG_FATAL);
debug_dual(lflash, sflash);
// begin flash pattern
led_off();
_delay_ms(LED_BREAK);
while (1)
{
for (uint8_t i = 0; i < lflash; i++)
{
led_on();
_delay_ms(LED_LONG_FLASH);
led_off();
_delay_ms(LED_LONG_FLASH);
}
_delay_ms(LED_BREAK);
for (uint8_t i = 0; i < sflash; i++)
{
led_on();
_delay_ms(LED_SHORT_FLASH);
led_off();
_delay_ms(LED_SHORT_FLASH);
}
_delay_ms(LED_BREAK);
}
}