From dcbf5b3e2d13135ab02e16ea28306f86ccf0ae58 Mon Sep 17 00:00:00 2001 From: zhuyanlin Date: Wed, 13 Oct 2021 21:15:04 +0800 Subject: [PATCH 1/3] arch:debug: add struct for task aware debug. When enable DEBUG_TCBINFO config, a global struct will provide, then debuggers can aware nuttx task infomation. Signed-off-by: zhuyanlin --- Kconfig | 8 ++ arch/arm/src/arm/arm_tcbinfo.c | 64 ++++++++++++++ arch/arm/src/armv6-m/arm_tcbinfo.c | 71 +++++++++++++++ arch/arm/src/armv7-a/arm_tcbinfo.c | 108 ++++++++++++++++++++++ arch/arm/src/armv7-m/arm_tcbinfo.c | 114 ++++++++++++++++++++++++ arch/arm/src/armv7-r/arm_tcbinfo.c | 108 ++++++++++++++++++++++ arch/arm/src/armv8-m/arm_tcbinfo.c | 114 ++++++++++++++++++++++++ arch/risc-v/src/common/riscv_tcbinfo.c | 118 +++++++++++++++++++++++++ include/nuttx/sched.h | 35 ++++++++ 9 files changed, 740 insertions(+) create mode 100644 arch/arm/src/arm/arm_tcbinfo.c create mode 100644 arch/arm/src/armv6-m/arm_tcbinfo.c create mode 100644 arch/arm/src/armv7-a/arm_tcbinfo.c create mode 100644 arch/arm/src/armv7-m/arm_tcbinfo.c create mode 100644 arch/arm/src/armv7-r/arm_tcbinfo.c create mode 100644 arch/arm/src/armv8-m/arm_tcbinfo.c create mode 100644 arch/risc-v/src/common/riscv_tcbinfo.c diff --git a/Kconfig b/Kconfig index 126139e9801ad..1772e71fb7837 100644 --- a/Kconfig +++ b/Kconfig @@ -546,6 +546,14 @@ endmenu # Customize Header Files menu "Debug Options" +config DEBUG_TCBINFO + bool "Enable TCBinfo struct for debug" + default n + ---help--- + Enables tcbinfo struct for debugger infomation. + Selecting this option will enable g_tcbinfo in arch and + procfs. + config DEBUG_ALERT bool default n diff --git a/arch/arm/src/arm/arm_tcbinfo.c b/arch/arm/src/arm/arm_tcbinfo.c new file mode 100644 index 0000000000000..f2e9745ac78a8 --- /dev/null +++ b/arch/arm/src/arm/arm_tcbinfo.c @@ -0,0 +1,64 @@ +/**************************************************************************** + * arch/arm/src/arm/arm_tcbinfo.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#ifdef CONFIG_DEBUG_TCBINFO + +#include +#include + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +const struct tcbinfo_s g_tcbinfo = +{ + TCB_PID_OFF, + TCB_STATE_OFF, + TCB_PRI_OFF, + TCB_NAME_OFF, + + XCPTCONTEXT_REGS, + + TCB_REG_OFF(REG_R0), + TCB_REG_OFF(REG_R1), + TCB_REG_OFF(REG_R2), + TCB_REG_OFF(REG_R3), + TCB_REG_OFF(REG_R4), + TCB_REG_OFF(REG_R5), + TCB_REG_OFF(REG_R6), + TCB_REG_OFF(REG_R7), + TCB_REG_OFF(REG_R8), + TCB_REG_OFF(REG_R9), + TCB_REG_OFF(REG_R10), + TCB_REG_OFF(REG_R11), + TCB_REG_OFF(REG_R12), + TCB_REG_OFF(REG_R13), + TCB_REG_OFF(REG_R14), + TCB_REG_OFF(REG_R15), + TCB_REG_OFF(REG_CPSR), +}; + +#endif diff --git a/arch/arm/src/armv6-m/arm_tcbinfo.c b/arch/arm/src/armv6-m/arm_tcbinfo.c new file mode 100644 index 0000000000000..45be31703d943 --- /dev/null +++ b/arch/arm/src/armv6-m/arm_tcbinfo.c @@ -0,0 +1,71 @@ +/**************************************************************************** + * arch/arm/src/armv6-m/arm_tcbinfo.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#ifdef CONFIG_DEBUG_TCBINFO + +#include +#include + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +const struct tcbinfo_s g_tcbinfo = +{ + TCB_PID_OFF, + TCB_STATE_OFF, + TCB_PRI_OFF, + TCB_NAME_OFF, + + XCPTCONTEXT_REGS, + + TCB_REG_OFF(REG_R0), + TCB_REG_OFF(REG_R1), + TCB_REG_OFF(REG_R2), + TCB_REG_OFF(REG_R3), + TCB_REG_OFF(REG_R4), + TCB_REG_OFF(REG_R5), + TCB_REG_OFF(REG_R6), + TCB_REG_OFF(REG_R7), + TCB_REG_OFF(REG_R8), + TCB_REG_OFF(REG_R9), + TCB_REG_OFF(REG_R10), + TCB_REG_OFF(REG_R11), + TCB_REG_OFF(REG_R12), + TCB_REG_OFF(REG_R13), + TCB_REG_OFF(REG_R14), + TCB_REG_OFF(REG_R15), + TCB_REG_OFF(REG_XPSR), + + 0, + TCB_REG_OFF(REG_R13), + TCB_REG_OFF(REG_PRIMASK), + 0, + 0, + 0, +}; + +#endif diff --git a/arch/arm/src/armv7-a/arm_tcbinfo.c b/arch/arm/src/armv7-a/arm_tcbinfo.c new file mode 100644 index 0000000000000..814ce321beb31 --- /dev/null +++ b/arch/arm/src/armv7-a/arm_tcbinfo.c @@ -0,0 +1,108 @@ +/**************************************************************************** + * arch/arm/src/armv7-a/arm_tcbinfo.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#ifdef CONFIG_DEBUG_TCBINFO + +#include +#include + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +const struct tcbinfo_s g_tcbinfo = +{ + TCB_PID_OFF, + TCB_STATE_OFF, + TCB_PRI_OFF, + TCB_NAME_OFF, + + XCPTCONTEXT_REGS, + + TCB_REG_OFF(REG_R0), + TCB_REG_OFF(REG_R1), + TCB_REG_OFF(REG_R2), + TCB_REG_OFF(REG_R3), + TCB_REG_OFF(REG_R4), + TCB_REG_OFF(REG_R5), + TCB_REG_OFF(REG_R6), + TCB_REG_OFF(REG_R7), + TCB_REG_OFF(REG_R8), + TCB_REG_OFF(REG_R9), + TCB_REG_OFF(REG_R10), + TCB_REG_OFF(REG_R11), + TCB_REG_OFF(REG_R12), + TCB_REG_OFF(REG_R13), + TCB_REG_OFF(REG_R14), + TCB_REG_OFF(REG_R15), + TCB_REG_OFF(REG_CPSR), + +#ifdef CONFIG_ARCH_FPU + TCB_REG_OFF(REG_D0), + TCB_REG_OFF(REG_D1), + TCB_REG_OFF(REG_D2), + TCB_REG_OFF(REG_D3), + TCB_REG_OFF(REG_D4), + TCB_REG_OFF(REG_D5), + TCB_REG_OFF(REG_D6), + TCB_REG_OFF(REG_D7), + TCB_REG_OFF(REG_D8), + TCB_REG_OFF(REG_D9), + TCB_REG_OFF(REG_D10), + TCB_REG_OFF(REG_D11), + TCB_REG_OFF(REG_D12), + TCB_REG_OFF(REG_D13), + TCB_REG_OFF(REG_D14), + TCB_REG_OFF(REG_D15), +#endif + +#ifdef CONFIG_ARM_HAVE_FPU_D32 + TCB_REG_OFF(REG_D16), + TCB_REG_OFF(REG_D17), + TCB_REG_OFF(REG_D18), + TCB_REG_OFF(REG_D19), + TCB_REG_OFF(REG_D20), + TCB_REG_OFF(REG_D21), + TCB_REG_OFF(REG_D22), + TCB_REG_OFF(REG_D23), + TCB_REG_OFF(REG_D24), + TCB_REG_OFF(REG_D25), + TCB_REG_OFF(REG_D26), + TCB_REG_OFF(REG_D27), + TCB_REG_OFF(REG_D28), + TCB_REG_OFF(REG_D29), + TCB_REG_OFF(REG_D30), + TCB_REG_OFF(REG_D31), +#endif + +#ifdef CONFIG_ARCH_FPU + 0, + TCB_REG_OFF(REG_FPSCR), + 0, +#endif +}; + +#endif diff --git a/arch/arm/src/armv7-m/arm_tcbinfo.c b/arch/arm/src/armv7-m/arm_tcbinfo.c new file mode 100644 index 0000000000000..c679e5a07db52 --- /dev/null +++ b/arch/arm/src/armv7-m/arm_tcbinfo.c @@ -0,0 +1,114 @@ +/**************************************************************************** + * arch/arm/src/armv7-m/arm_tcbinfo.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#ifdef CONFIG_DEBUG_TCBINFO + +#include +#include + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +const struct tcbinfo_s g_tcbinfo = +{ + TCB_PID_OFF, + TCB_STATE_OFF, + TCB_PRI_OFF, + TCB_NAME_OFF, + + XCPTCONTEXT_REGS, + + TCB_REG_OFF(REG_R0), + TCB_REG_OFF(REG_R1), + TCB_REG_OFF(REG_R2), + TCB_REG_OFF(REG_R3), + TCB_REG_OFF(REG_R4), + TCB_REG_OFF(REG_R5), + TCB_REG_OFF(REG_R6), + TCB_REG_OFF(REG_R7), + TCB_REG_OFF(REG_R8), + TCB_REG_OFF(REG_R9), + TCB_REG_OFF(REG_R10), + TCB_REG_OFF(REG_R11), + TCB_REG_OFF(REG_R12), + TCB_REG_OFF(REG_R13), + TCB_REG_OFF(REG_R14), + TCB_REG_OFF(REG_R15), + TCB_REG_OFF(REG_XPSR), + + 0, + TCB_REG_OFF(REG_R13), +#ifdef CONFIG_ARMV7M_USEBASEPRI + 0, + TCB_REG_OFF(REG_BASEPRI), +#else + TCB_REG_OFF(REG_PRIMASK), + 0, +#endif + 0, + 0, + +#ifdef CONFIG_ARCH_FPU + TCB_REG_OFF(REG_S0), + TCB_REG_OFF(REG_S1), + TCB_REG_OFF(REG_S2), + TCB_REG_OFF(REG_S3), + TCB_REG_OFF(REG_S4), + TCB_REG_OFF(REG_S5), + TCB_REG_OFF(REG_S6), + TCB_REG_OFF(REG_S7), + TCB_REG_OFF(REG_S8), + TCB_REG_OFF(REG_S9), + TCB_REG_OFF(REG_S10), + TCB_REG_OFF(REG_S11), + TCB_REG_OFF(REG_S12), + TCB_REG_OFF(REG_S13), + TCB_REG_OFF(REG_S14), + TCB_REG_OFF(REG_S15), + TCB_REG_OFF(REG_S16), + TCB_REG_OFF(REG_S17), + TCB_REG_OFF(REG_S18), + TCB_REG_OFF(REG_S19), + TCB_REG_OFF(REG_S20), + TCB_REG_OFF(REG_S21), + TCB_REG_OFF(REG_S22), + TCB_REG_OFF(REG_S23), + TCB_REG_OFF(REG_S24), + TCB_REG_OFF(REG_S25), + TCB_REG_OFF(REG_S26), + TCB_REG_OFF(REG_S27), + TCB_REG_OFF(REG_S28), + TCB_REG_OFF(REG_S29), + TCB_REG_OFF(REG_S30), + TCB_REG_OFF(REG_S31), + 0, + TCB_REG_OFF(REG_FPSCR), + 0, +#endif +}; + +#endif diff --git a/arch/arm/src/armv7-r/arm_tcbinfo.c b/arch/arm/src/armv7-r/arm_tcbinfo.c new file mode 100644 index 0000000000000..4f732e348d030 --- /dev/null +++ b/arch/arm/src/armv7-r/arm_tcbinfo.c @@ -0,0 +1,108 @@ +/**************************************************************************** + * arch/arm/src/armv7-r/arm_tcbinfo.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#ifdef CONFIG_DEBUG_TCBINFO + +#include +#include + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +const struct tcbinfo_s g_tcbinfo = +{ + TCB_PID_OFF, + TCB_STATE_OFF, + TCB_PRI_OFF, + TCB_NAME_OFF, + + XCPTCONTEXT_REGS, + + TCB_REG_OFF(REG_R0), + TCB_REG_OFF(REG_R1), + TCB_REG_OFF(REG_R2), + TCB_REG_OFF(REG_R3), + TCB_REG_OFF(REG_R4), + TCB_REG_OFF(REG_R5), + TCB_REG_OFF(REG_R6), + TCB_REG_OFF(REG_R7), + TCB_REG_OFF(REG_R8), + TCB_REG_OFF(REG_R9), + TCB_REG_OFF(REG_R10), + TCB_REG_OFF(REG_R11), + TCB_REG_OFF(REG_R12), + TCB_REG_OFF(REG_R13), + TCB_REG_OFF(REG_R14), + TCB_REG_OFF(REG_R15), + TCB_REG_OFF(REG_CPSR), + +#ifdef CONFIG_ARCH_FPU + TCB_REG_OFF(REG_D0), + TCB_REG_OFF(REG_D1), + TCB_REG_OFF(REG_D2), + TCB_REG_OFF(REG_D3), + TCB_REG_OFF(REG_D4), + TCB_REG_OFF(REG_D5), + TCB_REG_OFF(REG_D6), + TCB_REG_OFF(REG_D7), + TCB_REG_OFF(REG_D8), + TCB_REG_OFF(REG_D9), + TCB_REG_OFF(REG_D10), + TCB_REG_OFF(REG_D11), + TCB_REG_OFF(REG_D12), + TCB_REG_OFF(REG_D13), + TCB_REG_OFF(REG_D14), + TCB_REG_OFF(REG_D15), +#endif + +#ifdef CONFIG_ARM_HAVE_FPU_D32 + TCB_REG_OFF(REG_D16), + TCB_REG_OFF(REG_D17), + TCB_REG_OFF(REG_D18), + TCB_REG_OFF(REG_D19), + TCB_REG_OFF(REG_D20), + TCB_REG_OFF(REG_D21), + TCB_REG_OFF(REG_D22), + TCB_REG_OFF(REG_D23), + TCB_REG_OFF(REG_D24), + TCB_REG_OFF(REG_D25), + TCB_REG_OFF(REG_D26), + TCB_REG_OFF(REG_D27), + TCB_REG_OFF(REG_D28), + TCB_REG_OFF(REG_D29), + TCB_REG_OFF(REG_D30), + TCB_REG_OFF(REG_D31), +#endif + +#ifdef CONFIG_ARCH_FPU + 0, + TCB_REG_OFF(REG_FPSCR), + 0, +#endif +}; + +#endif diff --git a/arch/arm/src/armv8-m/arm_tcbinfo.c b/arch/arm/src/armv8-m/arm_tcbinfo.c new file mode 100644 index 0000000000000..96637da08205d --- /dev/null +++ b/arch/arm/src/armv8-m/arm_tcbinfo.c @@ -0,0 +1,114 @@ +/**************************************************************************** + * arch/arm/src/armv8-m/arm_tcbinfo.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#ifdef CONFIG_DEBUG_TCBINFO + +#include +#include + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +const struct tcbinfo_s g_tcbinfo = +{ + TCB_PID_OFF, + TCB_STATE_OFF, + TCB_PRI_OFF, + TCB_NAME_OFF, + + XCPTCONTEXT_REGS, + + TCB_REG_OFF(REG_R0), + TCB_REG_OFF(REG_R1), + TCB_REG_OFF(REG_R2), + TCB_REG_OFF(REG_R3), + TCB_REG_OFF(REG_R4), + TCB_REG_OFF(REG_R5), + TCB_REG_OFF(REG_R6), + TCB_REG_OFF(REG_R7), + TCB_REG_OFF(REG_R8), + TCB_REG_OFF(REG_R9), + TCB_REG_OFF(REG_R10), + TCB_REG_OFF(REG_R11), + TCB_REG_OFF(REG_R12), + TCB_REG_OFF(REG_R13), + TCB_REG_OFF(REG_R14), + TCB_REG_OFF(REG_R15), + TCB_REG_OFF(REG_XPSR), + + 0, + TCB_REG_OFF(REG_R13), +#ifdef CONFIG_ARMV8M_USEBASEPRI + 0, + TCB_REG_OFF(REG_BASEPRI), +#else + TCB_REG_OFF(REG_PRIMASK), + 0, +#endif + 0, + 0, + +#ifdef CONFIG_ARCH_FPU + TCB_REG_OFF(REG_S0), + TCB_REG_OFF(REG_S1), + TCB_REG_OFF(REG_S2), + TCB_REG_OFF(REG_S3), + TCB_REG_OFF(REG_S4), + TCB_REG_OFF(REG_S5), + TCB_REG_OFF(REG_S6), + TCB_REG_OFF(REG_S7), + TCB_REG_OFF(REG_S8), + TCB_REG_OFF(REG_S9), + TCB_REG_OFF(REG_S10), + TCB_REG_OFF(REG_S11), + TCB_REG_OFF(REG_S12), + TCB_REG_OFF(REG_S13), + TCB_REG_OFF(REG_S14), + TCB_REG_OFF(REG_S15), + TCB_REG_OFF(REG_S16), + TCB_REG_OFF(REG_S17), + TCB_REG_OFF(REG_S18), + TCB_REG_OFF(REG_S19), + TCB_REG_OFF(REG_S20), + TCB_REG_OFF(REG_S21), + TCB_REG_OFF(REG_S22), + TCB_REG_OFF(REG_S23), + TCB_REG_OFF(REG_S24), + TCB_REG_OFF(REG_S25), + TCB_REG_OFF(REG_S26), + TCB_REG_OFF(REG_S27), + TCB_REG_OFF(REG_S28), + TCB_REG_OFF(REG_S29), + TCB_REG_OFF(REG_S30), + TCB_REG_OFF(REG_S31), + 0, + TCB_REG_OFF(REG_FPSCR), + 0, +#endif +}; + +#endif diff --git a/arch/risc-v/src/common/riscv_tcbinfo.c b/arch/risc-v/src/common/riscv_tcbinfo.c new file mode 100644 index 0000000000000..530378b0dbe5f --- /dev/null +++ b/arch/risc-v/src/common/riscv_tcbinfo.c @@ -0,0 +1,118 @@ +/**************************************************************************** + * arch/risc-v/src/common/riscv_tcbinfo.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#ifdef CONFIG_DEBUG_TCBINFO + +#include +#include + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +const struct tcbinfo_s g_tcbinfo = +{ + TCB_PID_OFF, + TCB_STATE_OFF, + TCB_PRI_OFF, + TCB_NAME_OFF, + + XCPTCONTEXT_REGS, + + 0, + TCB_REG_OFF(REG_X1_NDX), + TCB_REG_OFF(REG_X2_NDX), + TCB_REG_OFF(REG_X3_NDX), + TCB_REG_OFF(REG_X4_NDX), + TCB_REG_OFF(REG_X5_NDX), + TCB_REG_OFF(REG_X6_NDX), + TCB_REG_OFF(REG_X7_NDX), + TCB_REG_OFF(REG_X8_NDX), + TCB_REG_OFF(REG_X9_NDX), + TCB_REG_OFF(REG_X10_NDX), + TCB_REG_OFF(REG_X11_NDX), + TCB_REG_OFF(REG_X12_NDX), + TCB_REG_OFF(REG_X13_NDX), + TCB_REG_OFF(REG_X14_NDX), + TCB_REG_OFF(REG_X15_NDX), + TCB_REG_OFF(REG_X16_NDX), + TCB_REG_OFF(REG_X17_NDX), + TCB_REG_OFF(REG_X18_NDX), + TCB_REG_OFF(REG_X19_NDX), + TCB_REG_OFF(REG_X20_NDX), + TCB_REG_OFF(REG_X21_NDX), + TCB_REG_OFF(REG_X22_NDX), + TCB_REG_OFF(REG_X23_NDX), + TCB_REG_OFF(REG_X24_NDX), + TCB_REG_OFF(REG_X25_NDX), + TCB_REG_OFF(REG_X26_NDX), + TCB_REG_OFF(REG_X27_NDX), + TCB_REG_OFF(REG_X28_NDX), + TCB_REG_OFF(REG_X29_NDX), + TCB_REG_OFF(REG_X30_NDX), + TCB_REG_OFF(REG_X31_NDX), + TCB_REG_OFF(REG_EPC_NDX), + +#ifdef CONFIG_ARCH_FPU + TCB_REG_OFF(REG_F0_NDX), + TCB_REG_OFF(REG_F1_NDX), + TCB_REG_OFF(REG_F2_NDX), + TCB_REG_OFF(REG_F3_NDX), + TCB_REG_OFF(REG_F4_NDX), + TCB_REG_OFF(REG_F5_NDX), + TCB_REG_OFF(REG_F6_NDX), + TCB_REG_OFF(REG_F7_NDX), + TCB_REG_OFF(REG_F8_NDX), + TCB_REG_OFF(REG_F9_NDX), + TCB_REG_OFF(REG_F10_NDX), + TCB_REG_OFF(REG_F11_NDX), + TCB_REG_OFF(REG_F12_NDX), + TCB_REG_OFF(REG_F13_NDX), + TCB_REG_OFF(REG_F14_NDX), + TCB_REG_OFF(REG_F15_NDX), + TCB_REG_OFF(REG_F16_NDX), + TCB_REG_OFF(REG_F17_NDX), + TCB_REG_OFF(REG_F18_NDX), + TCB_REG_OFF(REG_F19_NDX), + TCB_REG_OFF(REG_F20_NDX), + TCB_REG_OFF(REG_F21_NDX), + TCB_REG_OFF(REG_F22_NDX), + TCB_REG_OFF(REG_F23_NDX), + TCB_REG_OFF(REG_F24_NDX), + TCB_REG_OFF(REG_F25_NDX), + TCB_REG_OFF(REG_F26_NDX), + TCB_REG_OFF(REG_F27_NDX), + TCB_REG_OFF(REG_F28_NDX), + TCB_REG_OFF(REG_F29_NDX), + TCB_REG_OFF(REG_F30_NDX), + TCB_REG_OFF(REG_F31_NDX), + 0, + 0, + TCB_REG_OFF(REG_FCSR_NDX), +#endif +}; + +#endif diff --git a/include/nuttx/sched.h b/include/nuttx/sched.h index 6458afa7ff726..caec63431e672 100644 --- a/include/nuttx/sched.h +++ b/include/nuttx/sched.h @@ -184,6 +184,14 @@ # error "CONFIG_SCHED_EXIT_MAX < 1" #endif +#ifdef CONFIG_DEBUG_TCBINFO +# define TCB_PID_OFF (offsetof(struct tcb_s, pid)) +# define TCB_STATE_OFF (offsetof(struct tcb_s, task_state)) +# define TCB_PRI_OFF (offsetof(struct tcb_s, sched_priority)) +# define TCB_NAME_OFF (offsetof(struct tcb_s, name)) +# define TCB_REG_OFF(reg) (offsetof(struct tcb_s, xcp.regs[reg])) +#endif + /**************************************************************************** * Public Type Definitions ****************************************************************************/ @@ -764,6 +772,33 @@ struct pthread_tcb_s }; #endif /* !CONFIG_DISABLE_PTHREAD */ +/* struct tcbinfo_s *********************************************************/ + +/* The structure save key filed offset of tcb_s while can be used by + * debuggers to parse the tcb information + */ + +#ifdef CONFIG_DEBUG_TCBINFO +struct tcbinfo_s +{ + uint16_t pid_off; /* Offset of tcb.pid */ + uint16_t state_off; /* Offset of tcb.task_state */ + uint16_t pri_off; /* Offset of tcb.sched_priority */ + uint16_t name_off; /* Offset of tcb.name */ + uint16_t reg_num; /* Num of regs in tcbinfo.reg_offs */ + + /* Offsets of xcp.regs, order in GDB org.gnu.gdb.xxx feature. + * Please refer: + * https://sourceware.org/gdb/current/onlinedocs/gdb/ARM-Features.html + * https://sourceware.org/gdb/current/onlinedocs/gdb/RISC_002dV-Features + * -.html + * value 0: This regsiter was not priovided by NuttX + */ + + uint16_t reg_offs[XCPTCONTEXT_REGS]; +}; +#endif + /* This is the callback type used by nxsched_foreach() */ typedef CODE void (*nxsched_foreach_t)(FAR struct tcb_s *tcb, FAR void *arg); From a49b3cc1f571b72afabbdb0639bae9e0f3599acc Mon Sep 17 00:00:00 2001 From: zhuyanlin Date: Thu, 14 Oct 2021 19:39:44 +0800 Subject: [PATCH 2/3] fs:procfs: add tcbinfo procfs interface Add tcbinfo in procfs system. Signed-off-by: zhuyanlin --- fs/procfs/Kconfig | 5 + fs/procfs/Make.defs | 2 +- fs/procfs/fs_procfs.c | 5 + fs/procfs/fs_procfstcbinfo.c | 299 +++++++++++++++++++++++++++++++++++ 4 files changed, 310 insertions(+), 1 deletion(-) create mode 100644 fs/procfs/fs_procfstcbinfo.c diff --git a/fs/procfs/Kconfig b/fs/procfs/Kconfig index f0bd7a6085103..6d28080119601 100644 --- a/fs/procfs/Kconfig +++ b/fs/procfs/Kconfig @@ -131,5 +131,10 @@ config FS_PROCFS_EXCLUDE_SMARTFS depends on FS_SMARTFS default n +config FS_PROCFS_EXCLUDE_TCBINFO + bool "Exclude tcbinfo procfs" + depends on DEBUG_TCBINFO + default n + endmenu # Exclude individual procfs entries endif # FS_PROCFS diff --git a/fs/procfs/Make.defs b/fs/procfs/Make.defs index 8145c16351bc8..c7104eb12bf81 100644 --- a/fs/procfs/Make.defs +++ b/fs/procfs/Make.defs @@ -23,7 +23,7 @@ ifeq ($(CONFIG_FS_PROCFS),y) CSRCS += fs_procfs.c fs_procfsutil.c fs_procfsproc.c fs_procfsuptime.c CSRCS += fs_procfscpuload.c fs_procfsmeminfo.c fs_procfsiobinfo.c -CSRCS += fs_procfsversion.c +CSRCS += fs_procfsversion.c fs_procfstcbinfo.c ifeq ($(CONFIG_SCHED_CRITMONITOR),y) CSRCS += fs_procfscritmon.c diff --git a/fs/procfs/fs_procfs.c b/fs/procfs/fs_procfs.c index e0a41c7a1d918..85a53e4361f9c 100644 --- a/fs/procfs/fs_procfs.c +++ b/fs/procfs/fs_procfs.c @@ -70,6 +70,7 @@ extern const struct procfs_operations iobinfo_operations; extern const struct procfs_operations module_operations; extern const struct procfs_operations uptime_operations; extern const struct procfs_operations version_operations; +extern const struct procfs_operations tcbinfo_operations; /* This is not good. These are implemented in other sub-systems. Having to * deal with them here is not a good coupling. What is really needed is a @@ -165,6 +166,10 @@ static const struct procfs_entry_s g_procfs_entries[] = #if !defined(CONFIG_FS_PROCFS_EXCLUDE_VERSION) { "version", &version_operations, PROCFS_FILE_TYPE }, #endif + +#if defined(CONFIG_DEBUG_TCBINFO) && !defined(CONFIG_FS_PROCFS_EXCLUDE_TCBINFO) + { "tcbinfo", &tcbinfo_operations, PROCFS_FILE_TYPE }, +#endif }; #ifdef CONFIG_FS_PROCFS_REGISTER diff --git a/fs/procfs/fs_procfstcbinfo.c b/fs/procfs/fs_procfstcbinfo.c new file mode 100644 index 0000000000000..8551b666eba31 --- /dev/null +++ b/fs/procfs/fs_procfstcbinfo.c @@ -0,0 +1,299 @@ +/**************************************************************************** + * fs/procfs/fs_procfstcbinfo.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#if !defined(CONFIG_DISABLE_MOUNTPOINT) && defined(CONFIG_FS_PROCFS) +#ifdef CONFIG_DEBUG_TCBINFO + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Determines the size of an intermediate buffer that must be large enough + * to handle the longest line generated by this logic. + */ + +#define TCBINFO_LINELEN 128 + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/* This structure describes one open "file" */ + +struct tcbinfo_file_s +{ + struct procfs_file_s base; /* Base open file structure */ + unsigned int linesize; /* Number of valid characters in line[] */ + char line[TCBINFO_LINELEN]; /* Pre-allocated buffer for formatted lines */ +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/* File system methods */ + +static int tcbinfo_open(FAR struct file *filep, FAR const char *relpath, + int oflags, mode_t mode); +static int tcbinfo_close(FAR struct file *filep); +static ssize_t tcbinfo_read(FAR struct file *filep, FAR char *buffer, + size_t buflen); + +static int tcbinfo_dup(FAR const struct file *oldp, + FAR struct file *newp); + +static int tcbinfo_stat(FAR const char *relpath, FAR struct stat *buf); + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +extern struct tcbinfo_s g_tcbinfo; + +/* See fs_mount.c -- this structure is explicitly externed there. + * We use the old-fashioned kind of initializers so that this will compile + * with any compiler. + */ + +const struct procfs_operations tcbinfo_operations = +{ + tcbinfo_open, /* open */ + tcbinfo_close, /* close */ + tcbinfo_read, /* read */ + NULL, /* write */ + + tcbinfo_dup, /* dup */ + + NULL, /* opendir */ + NULL, /* closedir */ + NULL, /* readdir */ + NULL, /* rewinddir */ + + tcbinfo_stat /* stat */ +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: tcbinfo_open + ****************************************************************************/ + +static int tcbinfo_open(FAR struct file *filep, FAR const char *relpath, + int oflags, mode_t mode) +{ + FAR struct tcbinfo_file_s *attr; + + finfo("Open '%s'\n", relpath); + + /* PROCFS is read-only. Any attempt to open with any kind of write + * access is not permitted. + * + * REVISIT: Write-able proc files could be quite useful. + */ + + if ((oflags & O_WRONLY) != 0 || (oflags & O_RDONLY) == 0) + { + ferr("ERROR: Only O_RDONLY supported\n"); + return -EACCES; + } + + /* "tcbinfo" is the only acceptable value for the relpath */ + + if (strcmp(relpath, "tcbinfo") != 0) + { + ferr("ERROR: relpath is '%s'\n", relpath); + return -ENOENT; + } + + /* Allocate a container to hold the file attributes */ + + attr = (FAR struct tcbinfo_file_s *) + kmm_zalloc(sizeof(struct tcbinfo_file_s)); + + if (attr == NULL) + { + ferr("ERROR: Failed to allocate file attributes\n"); + return -ENOMEM; + } + + /* Save the attributes as the open-specific state in filep->f_priv */ + + filep->f_priv = (FAR void *)attr; + return OK; +} + +/**************************************************************************** + * Name: tcbinfo_close + ****************************************************************************/ + +static int tcbinfo_close(FAR struct file *filep) +{ + FAR struct tcbinfo_file_s *attr; + + /* Recover our private data from the struct file instance */ + + attr = (FAR struct tcbinfo_file_s *)filep->f_priv; + DEBUGASSERT(attr); + + /* Release the file attributes structure */ + + kmm_free(attr); + filep->f_priv = NULL; + return OK; +} + +/**************************************************************************** + * Name: tcbinfo_read + ****************************************************************************/ + +static ssize_t tcbinfo_read(FAR struct file *filep, FAR char *buffer, + size_t buflen) +{ + FAR struct tcbinfo_file_s *attr; + size_t linesize; + off_t offset; + ssize_t ret; + + finfo("buffer=%p buflen=%d\n", buffer, (int)buflen); + + /* Recover our private data from the struct file instance */ + + attr = (FAR struct tcbinfo_file_s *)filep->f_priv; + DEBUGASSERT(attr); + + if (filep->f_pos == 0) + { + linesize = procfs_snprintf(attr->line, TCBINFO_LINELEN, + "pointer %p size %d\n", g_tcbinfo, + sizeof(struct tcbinfo_s)); + + /* Save the linesize in case we are re-entered with f_pos > 0 */ + + attr->linesize = linesize; + } + + offset = filep->f_pos; + ret = procfs_memcpy(attr->line, attr->linesize, buffer, buflen, &offset); + + /* Update the file offset */ + + if (ret > 0) + { + filep->f_pos += ret; + } + + return ret; +} + +/**************************************************************************** + * Name: tcbinfo_dup + * + * Description: + * Duplicate open file data in the new file structure. + * + ****************************************************************************/ + +static int tcbinfo_dup(FAR const struct file *oldp, FAR struct file *newp) +{ + FAR struct tcbinfo_file_s *oldattr; + FAR struct tcbinfo_file_s *newattr; + + finfo("Dup %p->%p\n", oldp, newp); + + /* Recover our private data from the old struct file instance */ + + oldattr = (FAR struct tcbinfo_file_s *)oldp->f_priv; + DEBUGASSERT(oldattr); + + /* Allocate a new container to hold the task and attribute selection */ + + newattr = (FAR struct tcbinfo_file_s *) + kmm_malloc(sizeof(struct tcbinfo_file_s)); + + if (!newattr) + { + ferr("ERROR: Failed to allocate file attributes\n"); + return -ENOMEM; + } + + /* The copy the file attributes from the old attributes to the new */ + + memcpy(newattr, oldattr, sizeof(struct tcbinfo_file_s)); + + /* Save the new attributes in the new file structure */ + + newp->f_priv = (FAR void *)newattr; + return OK; +} + +/**************************************************************************** + * Name: tcbinfo_stat + * + * Description: Return information about a file or directory + * + ****************************************************************************/ + +static int tcbinfo_stat(FAR const char *relpath, FAR struct stat *buf) +{ + /* "tcbinfo" is the only acceptable value for the relpath */ + + if (strcmp(relpath, "tcbinfo") != 0) + { + ferr("ERROR: relpath is '%s'\n", relpath); + return -ENOENT; + } + + /* "tcbinfo" is the name for a read-only file */ + + memset(buf, 0, sizeof(struct stat)); + buf->st_mode = S_IFREG | S_IROTH | S_IRGRP | S_IRUSR; + return OK; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +#endif /* CONFIG_DEBUG_TCBINFO */ +#endif /* !CONFIG_DISABLE_MOUNTPOINT && CONFIG_FS_PROCFS */ From 2bf4e5b1c1616072d6117db8c4a5244e366dd1d8 Mon Sep 17 00:00:00 2001 From: zhuyanlin Date: Mon, 11 Oct 2021 21:38:51 +0800 Subject: [PATCH 3/3] tools: add gdbplugin for JLinkGDBServer nuttx thread aware Use `JLinkGDBServer -rtos libnuttxplugin` to add this plugin. Then in gdb can use command: - `info threads` to show all threads infos - `thread (id) ` to switch thread. - `bt` to show thread backtrace. Signed-off-by: zhuyanlin --- tools/Config.mk | 3 + tools/Makefile.host | 20 +- tools/jlink-nuttx.c | 643 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 663 insertions(+), 3 deletions(-) create mode 100644 tools/jlink-nuttx.c diff --git a/tools/Config.mk b/tools/Config.mk index 770950a6c138a..b200e6a337bcf 100644 --- a/tools/Config.mk +++ b/tools/Config.mk @@ -92,6 +92,9 @@ endif ifeq ($(CONFIG_HOST_WINDOWS),y) HOSTEXEEXT ?= .exe + HOSTDYNEXT ?= .dll +else ifeq ($(CONFIG_HOST_LINUX),y) + HOSTDYNEXT ?= .so endif # This define is passed as EXTRAFLAGS for kernel-mode builds. It is also passed diff --git a/tools/Makefile.host b/tools/Makefile.host index a49b3977916a0..fdc06a4606ec5 100644 --- a/tools/Makefile.host +++ b/tools/Makefile.host @@ -35,7 +35,8 @@ all: b16$(HOSTEXEEXT) bdf-converter$(HOSTEXEEXT) cmpconfig$(HOSTEXEEXT) \ mksymtab$(HOSTEXEEXT) mksyscall$(HOSTEXEEXT) mkversion$(HOSTEXEEXT) \ cnvwindeps$(HOSTEXEEXT) nxstyle$(HOSTEXEEXT) initialconfig$(HOSTEXEEXT) \ gencromfs$(HOSTEXEEXT) convert-comments$(HOSTEXEEXT) lowhex$(HOSTEXEEXT) \ - detab$(HOSTEXEEXT) rmcr$(HOSTEXEEXT) incdir$(HOSTEXEEXT) + detab$(HOSTEXEEXT) rmcr$(HOSTEXEEXT) incdir$(HOSTEXEEXT) \ + jlink-nuttx$(HOSTDYNEXT) default: mkconfig$(HOSTEXEEXT) mksyscall$(HOSTEXEEXT) mkdeps$(HOSTEXEEXT) \ cnvwindeps$(HOSTEXEEXT) incdir$(HOSTEXEEXT) @@ -43,9 +44,11 @@ ifdef HOSTEXEEXT .PHONY: b16 bdf-converter cmpconfig clean configure kconfig2html mkconfig \ mkdeps mksymtab mksyscall mkversion cnvwindeps nxstyle initialconfig \ gencromfs convert-comments lowhex detab rmcr incdir -else -.PHONY: clean endif +ifdef HOSTDYNEXT +.PHONY: jlink-nuttx +endif +.PHONY: clean # b16 - Fixed precision math conversion tool @@ -222,6 +225,15 @@ ifdef HOSTEXEEXT mkdeps: mkdeps$(HOSTEXEEXT) endif +# jlink-nuttx - Create jlink GDBServer nuttx plugin + +jlink-nuttx$(HOSTDYNEXT): jlink-nuttx.c + $(Q) $(HOSTCC) $(HOSTCFLAGS) -shared jlink-nuttx.c -o jlink-nuttx$(HOSTDYNEXT) + +ifdef HOSTDYNEXT +jlink-nuttx: jlink-nuttx$(HOSTDYNEXT) +endif + clean: $(call DELFILE, b16) $(call DELFILE, b16.exe) @@ -258,6 +270,8 @@ clean: $(call DELFILE, nxstyle.exe) $(call DELFILE, rmcr) $(call DELFILE, rmcr.exe) + $(call DELFILE, jlink-nuttx.so) + $(call DELFILE, jlink-nuttx.dll) ifneq ($(CONFIG_WINDOWS_NATIVE),y) $(Q) rm -rf *.dSYM endif diff --git a/tools/jlink-nuttx.c b/tools/jlink-nuttx.c new file mode 100644 index 0000000000000..ee20c940f1bab --- /dev/null +++ b/tools/jlink-nuttx.c @@ -0,0 +1,643 @@ +/**************************************************************************** + * tools/jlink-nuttx.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include +#include +#include +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Marcos for J-Link plugin API */ + +#define PLUGIN_VER 100 +#define DISPLAY_LENGTH 256 +#define THREADID_BASE 1 + +/* Marco for TCB struct size */ + +#define TCB_NAMESIZE 256 + +/* Marcos for J-Link API ops */ + +#define REALLOC(ptr, size) g_plugin_priv.jops->realloc(ptr, size) +#define ALLOC(size) g_plugin_priv.jops->alloc(size) +#define FREE(ptr) g_plugin_priv.jops->free(ptr) + +#define READMEM(addr, ptr, size) g_plugin_priv.jops->readmem(addr, ptr, size) +#define READU32(addr, data) g_plugin_priv.jops->readu32(addr, data) +#define READU16(addr, data) g_plugin_priv.jops->readu16(addr, data) +#define READU8(addr, data) g_plugin_priv.jops->readu8(addr, data) + +#define WRITEU32(addr, data) g_plugin_priv.jops->writeu32(addr, data) + +#define PERROR g_plugin_priv.jops->erroroutf +#define PLOG g_plugin_priv.jops->logoutf + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +enum symbol_e +{ + PIDHASH = 0, + NPIDHASH, + TCBINFO, + READYTORUN, + NSYMBOLS +}; + +struct tcbinfo_s +{ + uint16_t pid_off; + uint16_t state_off; + uint16_t pri_off; + uint16_t name_off; + uint16_t reg_num; + uint16_t reg_offs[0]; +}; + +struct symbols_s +{ + const char *name; + int optional; + uint32_t address; +}; + +/* J-Link server functions that can be called by the plugin */ + +struct jlink_ops_s +{ + /* API version v1.0 and higher */ + + void (*free) (void *p); + void *(*alloc) (unsigned size); + void *(*realloc) (void *p, unsigned size); + void (*logoutf) (const char *sformat, ...); + void (*debugoutf) (const char *sformat, ...); + void (*warnoutf) (const char *sformat, ...); + void (*erroroutf) (const char *sformat, ...); + int (*readmem) (uint32_t addr, char *pdata, + unsigned int numbytes); + char (*readu8) (uint32_t addr, uint8_t *pdata); + char (*readu16) (uint32_t addr, uint16_t *pdata); + char (*readu32) (uint32_t addr, uint32_t *pdata); + int (*writemem) (uint32_t addr, const char *pdata, + unsigned numbytes); + void (*writeu8) (uint32_t addr, uint8_t data); + void (*writeu16) (uint32_t addr, uint16_t data); + void (*writeu32) (uint32_t addr, uint32_t data); + uint32_t (*load16te) (const uint8_t *p); + uint32_t (*load24te) (const uint8_t *p); + uint32_t (*load32te) (const uint8_t *p); + + /* API version v1.1 and higher */ + + uint32_t (*readreg) (uint32_t regindex); + void (*writereg) (uint32_t regindex, uint32_t value); + + /* End marker */ + + void *dummy; +}; + +struct plugin_priv_s +{ + uint32_t *pidhash; + uint32_t npidhash; + struct tcbinfo_s *tcbinfo; + uint16_t running; + uint32_t ntcb; + const struct jlink_ops_s *jops; +}; + +/**************************************************************************** + * Private data + ****************************************************************************/ + +static struct symbols_s g_symbols[] = +{ + {"g_pidhash", 0, 0}, + {"g_npidhash", 0, 0}, + {"g_tcbinfo", 0, 0}, + {"g_readytorun", 0, 0}, + { NULL, 0, 0} +}; + +static struct plugin_priv_s g_plugin_priv; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +static inline int encode_hex(char *line, uint32_t value) +{ + /* output line in intel hex format */ + + return snprintf(line, 9, "%02x%02x%02x%02x", value & 0xff, + (value & 0xff00) >> 8, (value & 0xff0000) >> 16, + (value & 0xff000000) >> 24); +} + +static inline uint32_t decode_hex(const char *line) +{ + /* Get value from hex format line */ + + uint32_t i; + uint32_t value = 0; + + for (i = 7; i >= 0; ) + { + value += (value << 8) + (line[i--] - '0'); + value += (line[i--] - '0') << 4; + } + + return value; +} + +static int get_pid(struct plugin_priv_s *priv, uint32_t idx, + uint16_t *pid) +{ + int ret; + + ret = READU16(priv->pidhash[idx] + priv->tcbinfo->pid_off, pid); + if (ret != 0) + { + PERROR("read %d pid error return %d\n", idx, ret); + return ret; + } + + return 0; +} + +static int get_idx_from_pid(struct plugin_priv_s *priv, + uint32_t pid) +{ + int idx; + + for (idx = 0; idx < priv->ntcb; idx++) + { + uint16_t tmppid; + + if (get_pid(priv, idx, &tmppid)) + { + return -1; + } + + if (tmppid == pid) + { + return idx; + } + } + + return -1; +} + +static int setget_reg(struct plugin_priv_s *priv, uint32_t idx, + uint32_t regidx, uint32_t *regval, bool write) +{ + uint32_t regaddr; + int ret = 0; + + regaddr = priv->pidhash[idx] + priv->tcbinfo->reg_offs[regidx]; + + if (write) + { + WRITEU32(regaddr, *regval); + } + else + { + ret = READU32(regaddr, regval); + if (ret != 0) + { + PERROR("regread %d regidx %d error %d\n", idx, regidx, ret); + return ret; + } + } + + return ret; +} + +static int update_tcbinfo(struct plugin_priv_s *priv) +{ + if (!priv->tcbinfo) + { + uint16_t reg_num; + int ret; + + ret = READU16(g_symbols[TCBINFO].address + + offsetof(struct tcbinfo_s, reg_num), ®_num); + if (ret != 0 || !reg_num) + { + PERROR("error reading regs ret %d\n", ret); + return ret; + } + + priv->tcbinfo = ALLOC(sizeof(struct tcbinfo_s) + + reg_num * sizeof(uint16_t)); + + if (!priv->tcbinfo) + { + PERROR("error in malloc tcbinfo_s\n"); + return -ENOMEM; + } + + ret = READMEM(g_symbols[TCBINFO].address, (char *)priv->tcbinfo, + sizeof(struct tcbinfo_s) + reg_num * sizeof(uint16_t)); + if (ret != sizeof(struct tcbinfo_s) + reg_num * sizeof(uint16_t)) + { + PERROR("error in read tcbinfo_s ret %d\n", ret); + return ret; + } + + PLOG("setup success! regs %d\n", priv->tcbinfo->reg_num); + } + + return 0; +} + +static int update_pidhash(struct plugin_priv_s *priv) +{ + uint32_t npidhash; + uint32_t pidhashaddr; + int ret; + + ret = READU32(g_symbols[NPIDHASH].address, &npidhash); + if (ret != 0 || npidhash == 0) + { + PERROR("error reading npidhash ret %d\n", ret); + return ret; + } + + if (npidhash != priv->npidhash) + { + priv->pidhash = REALLOC(priv->pidhash, + npidhash * sizeof(uint32_t *)); + if (!priv->pidhash) + { + PERROR("error in malloc pidhash\n"); + return -ENOMEM; + } + + PLOG("npidhash change from %d to %d!\n", priv->npidhash, npidhash); + priv->npidhash = npidhash; + } + + ret = READU32(g_symbols[PIDHASH].address, &pidhashaddr); + if (ret != 0 || pidhashaddr == 0) + { + PERROR("error in read pidhashaddr ret %d\n", ret); + return ret; + } + + ret = READMEM(pidhashaddr, (char *)priv->pidhash, + priv->npidhash * sizeof(uint32_t *)); + if (ret != priv->npidhash * sizeof(uint32_t *)) + { + PERROR("error in read pidhash ret %d\n", ret); + return ret; + } + + return 0; +} + +static int normalize_tcb(struct plugin_priv_s *priv) +{ + uint32_t i; + uint32_t tcbaddr; + int ret; + + priv->ntcb = 0; + + for (i = 0; i < priv->npidhash; i++) + { + if (priv->pidhash[i]) + { + priv->pidhash[priv->ntcb++] = priv->pidhash[i]; + } + } + + ret = READU32(g_symbols[READYTORUN].address, &tcbaddr); + if (ret != 0) + { + PERROR("read readytorun error return %d\n", ret); + } + + ret = READU16(tcbaddr + priv->tcbinfo->pid_off, &priv->running); + if (ret != 0) + { + PERROR("read readytorun pid error return %d\n", ret); + return ret; + } + + return 0; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +int RTOS_Init(const struct jlink_ops_s *api, uint32_t core) +{ + g_plugin_priv.jops = api; + + return 1; +} + +uint32_t RTOS_GetVersion(void) +{ + return PLUGIN_VER; +} + +struct symbols_s *RTOS_GetSymbols(void) +{ + return g_symbols; +} + +uint32_t RTOS_GetNumThreads(void) +{ + return g_plugin_priv.ntcb; +} + +uint32_t RTOS_GetCurrentThreadId(void) +{ + return THREADID_BASE + g_plugin_priv.running; +} + +uint32_t RTOS_GetThreadId(uint32_t n) +{ + if (n < g_plugin_priv.ntcb) + { + uint16_t pid; + + if (get_pid(&g_plugin_priv, n, &pid) == 0) + { + return THREADID_BASE + pid; + } + } + + return 0; +} + +int RTOS_GetThreadDisplay(char *display, uint32_t threadid) +{ + int idx; + uint32_t len = 0; + char name[TCB_NAMESIZE]; + uint8_t readval; + int ret; + + threadid -= THREADID_BASE; + + idx = get_idx_from_pid(&g_plugin_priv, threadid); + if (idx < 0) + { + PERROR("error in get_idx_from_pid return %d\n", idx); + return -1; + } + + len += snprintf(display + len, + DISPLAY_LENGTH - len, "[PID:%03d]", threadid); + + ret = READMEM(g_plugin_priv.pidhash[idx] + + g_plugin_priv.tcbinfo->name_off, name, TCB_NAMESIZE); + if (ret != TCB_NAMESIZE) + { + PERROR("error in read tcb name return %d\n", ret); + } + + /* check tcb name is valid or not */ + + if ((name[0] > 'a' && name[0] < 'z') + || (name[0] > 'A' && name[0] < 'Z')) + { + len += snprintf(display + len, DISPLAY_LENGTH - len, + "%s", name); + } + else + { + len += snprintf(display + len, DISPLAY_LENGTH - len, + "thread-%d", threadid); + } + + ret = READU8(g_plugin_priv.pidhash[idx] + + g_plugin_priv.tcbinfo->state_off, &readval); + if (ret != 0) + { + PERROR("error in read tcb state return %d\n", ret); + } + + len += snprintf(display + len, DISPLAY_LENGTH - len, ":%04d", + readval); + + ret = READU8(g_plugin_priv.pidhash[idx] + + g_plugin_priv.tcbinfo->pri_off, &readval); + if (ret != 0) + { + PERROR("error in read tcb pri return %d\n", ret); + } + + len += snprintf(display + len, + DISPLAY_LENGTH - len, "[PRI:%03d]", readval); + + return len; +} + +int RTOS_GetThreadReg(char *hexregval, uint32_t regindex, uint32_t threadid) +{ + int idx; + uint32_t regval = 0; + + threadid -= THREADID_BASE; + + /* current task read by J-Link self */ + + if (threadid == g_plugin_priv.running) + { + return -1; + } + + if (regindex > g_plugin_priv.tcbinfo->reg_num) + { + return -1; + } + + idx = get_idx_from_pid(&g_plugin_priv, threadid); + if (idx < 0) + { + PERROR("error in get_idx_from_pid return %d\n", idx); + return -1; + } + + if (g_plugin_priv.tcbinfo->reg_offs[regindex]) + { + setget_reg(&g_plugin_priv, idx, regindex, ®val, false); + + encode_hex(hexregval, regval); + return 0; + } + + return -1; +} + +int RTOS_GetThreadRegList(char *hexreglist, uint32_t threadid) +{ + int idx; + uint32_t j; + uint32_t regval; + + threadid -= THREADID_BASE; + + /* current task read by J-Link self */ + + if (threadid == g_plugin_priv.running) + { + return -1; + } + + idx = get_idx_from_pid(&g_plugin_priv, threadid); + if (idx < 0) + { + PERROR("error in get_idx_from_pid return %d\n", idx); + return -1; + } + + for (j = 0; j < 17; j++) + { + regval = 0; + + if (g_plugin_priv.tcbinfo->reg_offs[j]) + { + setget_reg(&g_plugin_priv, idx, j, ®val, false); + } + + hexreglist += encode_hex(hexreglist, regval); + } + + return 0; +} + +int RTOS_SetThreadReg(char *hexregval, + uint32_t regindex, uint32_t threadid) +{ + int idx; + uint32_t regval; + + threadid -= THREADID_BASE; + + if (threadid == g_plugin_priv.running) + { + return -1; + } + + if (regindex > g_plugin_priv.tcbinfo->reg_num) + { + return -1; + } + + idx = get_idx_from_pid(&g_plugin_priv, threadid); + if (idx < 0) + { + PERROR("error in get_idx_from_pid return %d\n", idx); + return -1; + } + + if (g_plugin_priv.tcbinfo->reg_offs[regindex]) + { + regval = decode_hex(hexregval); + + setget_reg(&g_plugin_priv, idx, regindex, ®val, true); + return 0; + } + + return -1; +} + +int RTOS_SetThreadRegList(char *hexreglist, uint32_t threadid) +{ + int idx; + uint32_t j; + uint32_t regval; + + threadid -= THREADID_BASE; + + if (threadid == g_plugin_priv.running) + { + return -1; + } + + idx = get_idx_from_pid(&g_plugin_priv, threadid); + if (idx < 0) + { + PERROR("error in get_idx_from_pid return %d\n", idx); + return -1; + } + + for (j = 0; j < 17; j++) + { + if (g_plugin_priv.tcbinfo->reg_offs[j]) + { + regval = decode_hex(hexreglist); + + setget_reg(&g_plugin_priv, idx, j, ®val, true); + + hexreglist += 4; + } + else + { + return -1; + } + } + + return 0; +} + +int RTOS_UpdateThreads(void) +{ + int ret; + + ret = update_tcbinfo(&g_plugin_priv); + if (ret) + { + return ret; + } + + ret = update_pidhash(&g_plugin_priv); + if (ret) + { + return ret; + } + + ret = normalize_tcb(&g_plugin_priv); + if (ret) + { + return ret; + } + + return 0; +}