Skip to content

Commit 52aea31

Browse files
authored
Merge pull request #8702 from SenRamakri/sen_CrashReportingImpl
Crash Reporting implementation
2 parents 7995e8b + f59b99d commit 52aea31

File tree

56 files changed

+1036
-60
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

56 files changed

+1036
-60
lines changed

TESTS/host_tests/crash_reporting.py

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
"""
2+
Copyright (c) 2018 ARM Limited
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
"""
16+
import time
17+
from mbed_host_tests import BaseHostTest
18+
from mbed_host_tests.host_tests_runner.host_test_default import DefaultTestSelector
19+
20+
DEFAULT_CYCLE_PERIOD = 10.0
21+
22+
MSG_VALUE_DUMMY = '0'
23+
24+
MSG_KEY_DEVICE_READY = 'crash_reporting_ready'
25+
MSG_KEY_DEVICE_ERROR = 'crash_reporting_inject_error'
26+
MSG_KEY_SYNC = '__sync'
27+
28+
class CrashReportingTest(BaseHostTest):
29+
"""Test for the crash reporting feature.
30+
"""
31+
32+
def __init__(self):
33+
super(CrashReportingTest, self).__init__()
34+
self.reset = False
35+
self.test_steps_sequence = self.test_steps()
36+
# Advance the coroutine to it's first yield statement.
37+
self.test_steps_sequence.send(None)
38+
39+
def setup(self):
40+
self.register_callback(MSG_KEY_DEVICE_READY, self.cb_device_ready)
41+
42+
def cb_device_ready(self, key, value, timestamp):
43+
"""Acknowledge device rebooted correctly and feed the test execution
44+
"""
45+
self.reset = True
46+
47+
try:
48+
if self.test_steps_sequence.send(value):
49+
self.notify_complete(True)
50+
except (StopIteration, RuntimeError) as exc:
51+
self.notify_complete(False)
52+
53+
def test_steps(self):
54+
"""Reset the device and check the status
55+
"""
56+
system_reset = yield
57+
self.reset = False
58+
59+
wait_after_reset = self.get_config_item('forced_reset_timeout')
60+
wait_after_reset = wait_after_reset if wait_after_reset is not None else DEFAULT_CYCLE_PERIOD
61+
62+
#Wait 2 seconds for system to init
63+
time.sleep(2.0)
64+
#self.send_kv(MSG_KEY_SYNC, MSG_VALUE_DUMMY)
65+
self.send_kv(MSG_KEY_DEVICE_ERROR, MSG_VALUE_DUMMY)
66+
time.sleep(5.0)
67+
68+
system_reset = yield
69+
if self.reset == False:
70+
raise RuntimeError('Platform did not auto-reboot as expected.')
71+
72+
# The sequence is correct -- test passed.
73+
yield True
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
/* mbed Microcontroller Library
2+
* Copyright (c) 2018 ARM Limited
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
#include "mbed.h"
17+
#include "mbed_error.h"
18+
#include "mbed_crash_data_offsets.h"
19+
#include "greentea-client/test_env.h"
20+
#include "unity/unity.h"
21+
22+
#if !MBED_CONF_PLATFORM_CRASH_CAPTURE_ENABLED
23+
#error [NOT_SUPPORTED] crash_reporting test not supported
24+
#endif
25+
26+
#define MSG_VALUE_DUMMY "0"
27+
#define MSG_VALUE_LEN 32
28+
#define MSG_KEY_LEN 64
29+
30+
#define MSG_KEY_DEVICE_READY "crash_reporting_ready"
31+
#define MSG_KEY_DEVICE_ERROR "crash_reporting_inject_error"
32+
33+
static mbed_error_ctx saved_error_ctx = {0};
34+
35+
void mbed_error_reboot_callback(mbed_error_ctx *error_context)
36+
{
37+
38+
TEST_ASSERT_EQUAL_UINT((uint32_t)error_context, ERROR_CONTEXT_LOCATION);
39+
memcpy(&saved_error_ctx, error_context, sizeof(mbed_error_ctx));
40+
mbed_reset_reboot_error_info();
41+
42+
TEST_ASSERT_EQUAL_UINT(MBED_ERROR_OUT_OF_MEMORY, saved_error_ctx.error_status);
43+
TEST_ASSERT_EQUAL_UINT(1, saved_error_ctx.error_reboot_count);
44+
45+
//Send the ready msg to host to indicate test pass
46+
greentea_send_kv(MSG_KEY_DEVICE_READY, MSG_VALUE_DUMMY);
47+
}
48+
49+
void test_crash_reporting()
50+
{
51+
//Clear any previous status
52+
mbed_reset_reboot_error_info();
53+
54+
// Report readiness
55+
greentea_send_kv(MSG_KEY_DEVICE_READY, MSG_VALUE_DUMMY);
56+
57+
static char _key[MSG_KEY_LEN + 1] = { };
58+
static char _value[MSG_VALUE_LEN + 1] = { };
59+
60+
greentea_parse_kv(_key, _value, MSG_KEY_LEN, MSG_VALUE_LEN);
61+
if (strcmp(_key, MSG_KEY_DEVICE_ERROR) == 0) {
62+
MBED_ERROR1(MBED_ERROR_OUT_OF_MEMORY, "Executing crash reporting test.", 0xDEADBAD);
63+
TEST_ASSERT_MESSAGE(0, "crash_reporting() error call failed.");
64+
}
65+
TEST_ASSERT_MESSAGE(0, "Unexpected message received.");
66+
}
67+
68+
int main(void)
69+
{
70+
GREENTEA_SETUP(30, "crash_reporting");
71+
test_crash_reporting();
72+
GREENTEA_TESTSUITE_RESULT(0);
73+
74+
return 0;
75+
}

cmsis/TARGET_CORTEX_M/TOOLCHAIN_ARM/except.S

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,8 @@ Fault_Handler PROC
8080

8181
Fault_Handler_Continue
8282
MOV R12,R3
83-
LDR R1,=mbed_fault_context
83+
LDR R3,=mbed_fault_context
84+
LDR R1,[R3]
8485
LDR R2,[R0] ; Capture R0
8586
STR R2,[R1]
8687
ADDS R1,#4

cmsis/TARGET_CORTEX_M/TOOLCHAIN_GCC/except.S

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,8 @@ Fault_Handler:
113113

114114
Fault_Handler_Continue:
115115
MOV R12,R3
116-
LDR R1,=mbed_fault_context
116+
LDR R3,=mbed_fault_context
117+
LDR R1,[R3]
117118
LDR R2,[R0] // Capture R0
118119
STR R2,[R1]
119120
ADDS R1,#4

cmsis/TARGET_CORTEX_M/TOOLCHAIN_IAR/except.S

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,8 @@ Fault_Handler
7575

7676
Fault_Handler_Continue
7777
MOV R12,R3
78-
LDR R1,=mbed_fault_context
78+
LDR R3,=mbed_fault_context
79+
LDR R1,[R3]
7980
LDR R2,[R0] ; Capture R0
8081
STR R2,[R1]
8182
ADDS R1,#4

cmsis/TARGET_CORTEX_M/mbed_fault_handler.c

Lines changed: 29 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -20,17 +20,23 @@
2020
#include <inttypes.h>
2121

2222
#include "device.h"
23-
#include "platform/mbed_error.h"
24-
#include "platform/mbed_interface.h"
23+
#include "mbed_error.h"
24+
#include "mbed_interface.h"
25+
#include "mbed_crash_data_offsets.h"
2526

2627
#ifndef MBED_FAULT_HANDLER_DISABLED
2728
#include "mbed_fault_handler.h"
2829

2930
//Functions Prototypes
3031
void print_context_info(void);
3132

32-
//Global for populating the context in exception handler
33-
mbed_fault_context_t mbed_fault_context;
33+
#if MBED_CONF_PLATFORM_CRASH_CAPTURE_ENABLED
34+
//Global for populating the context in exception handler
35+
mbed_fault_context_t *const mbed_fault_context=(mbed_fault_context_t *)(FAULT_CONTEXT_LOCATION);
36+
#else
37+
mbed_fault_context_t fault_context;
38+
mbed_fault_context_t *const mbed_fault_context=(mbed_fault_context_t *)&fault_context;
39+
#endif
3440

3541
//This is a handler function called from Fault handler to print the error information out.
3642
//This runs in fault context and uses special functions(defined in mbed_rtx_fault_handler.c) to print the information without using C-lib support.
@@ -69,24 +75,24 @@ void mbed_fault_handler (uint32_t fault_type, void *mbed_fault_context_in)
6975
mbed_error_printf("\n\n-- MbedOS Fault Handler --\n\n");
7076

7177
//Now call mbed_error, to log the error and halt the system
72-
mbed_error( faultStatus, "Fault exception", mbed_fault_context.PC_reg, NULL, 0 );
78+
mbed_error( faultStatus, "Fault exception", mbed_fault_context->PC_reg, NULL, 0 );
7379

7480
}
7581

7682
MBED_NOINLINE void print_context_info(void)
7783
{
7884
//Context Regs
7985
for(int i=0;i<13;i++) {
80-
mbed_error_printf("\nR%-4d: %08" PRIX32, i, ((uint32_t *)&mbed_fault_context)[i]);
86+
mbed_error_printf("\nR%-4d: %08" PRIX32, i, ((uint32_t *)(mbed_fault_context))[i]);
8187
}
8288

8389
mbed_error_printf("\nSP : %08" PRIX32
8490
"\nLR : %08" PRIX32
8591
"\nPC : %08" PRIX32
8692
"\nxPSR : %08" PRIX32
8793
"\nPSP : %08" PRIX32
88-
"\nMSP : %08" PRIX32, mbed_fault_context.SP_reg, mbed_fault_context.LR_reg, mbed_fault_context.PC_reg,
89-
mbed_fault_context.xPSR, mbed_fault_context.PSP, mbed_fault_context.MSP );
94+
"\nMSP : %08" PRIX32, mbed_fault_context->SP_reg, mbed_fault_context->LR_reg, mbed_fault_context->PC_reg,
95+
mbed_fault_context->xPSR, mbed_fault_context->PSP, mbed_fault_context->MSP );
9096

9197
//Capture CPUID to get core/cpu info
9298
mbed_error_printf("\nCPUID: %08" PRIX32, SCB->CPUID);
@@ -112,12 +118,12 @@ MBED_NOINLINE void print_context_info(void)
112118
#endif
113119

114120
//Print Mode
115-
if (mbed_fault_context.EXC_RETURN & 0x8) {
121+
if (mbed_fault_context->EXC_RETURN & 0x8) {
116122
mbed_error_printf("\nMode : Thread");
117123
//Print Priv level in Thread mode - We capture CONTROL reg which reflects the privilege.
118124
//Note that the CONTROL register captured still reflects the privilege status of the
119125
//thread mode eventhough we are in Handler mode by the time we capture it.
120-
if(mbed_fault_context.CONTROL & 0x1) {
126+
if(mbed_fault_context->CONTROL & 0x1) {
121127
mbed_error_printf("\nPriv : User");
122128
} else {
123129
mbed_error_printf("\nPriv : Privileged");
@@ -127,11 +133,23 @@ MBED_NOINLINE void print_context_info(void)
127133
mbed_error_printf("\nPriv : Privileged");
128134
}
129135
//Print Return Stack
130-
if (mbed_fault_context.EXC_RETURN & 0x4) {
136+
if (mbed_fault_context->EXC_RETURN & 0x4) {
131137
mbed_error_printf("\nStack: PSP");
132138
} else {
133139
mbed_error_printf("\nStack: MSP");
134140
}
135141
}
136142

143+
mbed_error_status_t mbed_get_reboot_fault_context (mbed_fault_context_t *fault_context)
144+
{
145+
mbed_error_status_t status = MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, MBED_ERROR_CODE_ITEM_NOT_FOUND);
146+
#if MBED_CONF_PLATFORM_CRASH_CAPTURE_ENABLED
147+
if(fault_context == NULL)
148+
return MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, MBED_ERROR_CODE_INVALID_ARGUMENT);
149+
memcpy(fault_context, mbed_fault_context, sizeof(mbed_fault_context_t));
150+
status = MBED_SUCCESS;
151+
#endif
152+
return status;
153+
}
154+
137155
#endif //MBED_FAULT_HANDLER_SUPPORT

cmsis/TARGET_CORTEX_M/mbed_fault_handler.h

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,11 @@
1515
*/
1616

1717
#ifndef MBED_FAULT_HANDLER_H
18-
#define MBED_FAULT_HANDLER_H
18+
#define MBED_FAULT_HANDLER_H
19+
20+
#ifdef __cplusplus
21+
extern "C" {
22+
#endif
1923

2024
//Fault context struct
2125
//WARNING: DO NOT CHANGE THIS STRUCT WITHOUT MAKING CORRESPONDING CHANGES in except.S files.
@@ -55,4 +59,18 @@ typedef struct {
5559
//This runs in fault context and uses special functions(defined in mbed_fault_handler.c) to print the information without using C-lib support.
5660
void mbed_fault_handler (uint32_t fault_type, void *mbed_fault_context_in);
5761

62+
/**
63+
* Call this function to retrieve the fault context after a fatal exception which triggered a system reboot. The function retrieves the fault context stored in crash-report ram area which is preserved over reboot.
64+
* @param fault_context Pointer to mbed_fault_context_t struct allocated by the caller. This is the mbed_fault_context_t info captured as part of the fatal exception which triggered the reboot.
65+
* @return 0 or MBED_SUCCESS on success.
66+
* MBED_ERROR_INVALID_ARGUMENT in case of invalid error_info pointer
67+
* MBED_ERROR_ITEM_NOT_FOUND if no reboot context is currently captured by teh system
68+
*
69+
*/
70+
mbed_error_status_t mbed_get_reboot_fault_context (mbed_fault_context_t *fault_context);
71+
72+
#ifdef __cplusplus
73+
}
74+
#endif
75+
5876
#endif

platform/mbed_crash_data_offsets.h

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
/* mbed Microcontroller Library
2+
* Copyright (c) 2006-2013 ARM Limited
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
#ifndef MBED_CRASH_DATA_INFO_H
17+
#define MBED_CRASH_DATA_INFO_H
18+
19+
#include "platform/mbed_retarget.h"
20+
#include "platform/mbed_toolchain.h"
21+
22+
#ifdef __cplusplus
23+
extern "C" {
24+
#endif
25+
26+
#if MBED_CONF_PLATFORM_CRASH_CAPTURE_ENABLED
27+
#if defined(__CC_ARM) || (defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050))
28+
extern uint32_t Image$$RW_m_crash_data$$ZI$$Base[];
29+
extern uint32_t Image$$RW_m_crash_data$$ZI$$Size;
30+
#define __CRASH_DATA_RAM_START__ Image$$RW_m_crash_data$$ZI$$Base
31+
#define __CRASH_DATA_RAM_SIZE__ Image$$RW_m_crash_data$$ZI$$Size
32+
#elif defined(__ICCARM__)
33+
extern uint32_t __CRASH_DATA_RAM_START__[];
34+
extern uint32_t __CRASH_DATA_RAM_END__[];
35+
#define __CRASH_DATA_RAM_SIZE__ (__CRASH_DATA_RAM_END__ - __CRASH_DATA_RAM_START__)
36+
#elif defined(__GNUC__)
37+
extern uint32_t __CRASH_DATA_RAM_START__[];
38+
extern uint32_t __CRASH_DATA_RAM_END__[];
39+
#define __CRASH_DATA_RAM_SIZE__ (__CRASH_DATA_RAM_END__ - __CRASH_DATA_RAM_START__)
40+
#endif /* defined(__CC_ARM) */
41+
42+
/* Offset definitions for context capture */
43+
#define FAULT_CONTEXT_OFFSET (0x0)
44+
#define FAULT_CONTEXT_SIZE (0x80 / 4) //32 words(128 bytes) for Fault Context
45+
#define ERROR_CONTEXT_OFFSET (FAULT_CONTEXT_OFFSET + FAULT_CONTEXT_SIZE)
46+
#define ERROR_CONTEXT_SIZE (0x80 / 4) //32 words(128 bytes) bytes for Error Context
47+
#define FAULT_CONTEXT_LOCATION (__CRASH_DATA_RAM_START__ + FAULT_CONTEXT_OFFSET)
48+
#define ERROR_CONTEXT_LOCATION (__CRASH_DATA_RAM_START__ + ERROR_CONTEXT_OFFSET)
49+
#endif
50+
51+
#ifdef __cplusplus
52+
}
53+
#endif
54+
55+
#endif
56+
57+
58+

0 commit comments

Comments
 (0)