no1wudi commented on code in PR #12554: URL: https://github.com/apache/nuttx/pull/12554#discussion_r1670018089
########## arch/risc-v/src/common/riscv_debug.c: ########## @@ -0,0 +1,381 @@ +/**************************************************************************** + * arch/risc-v/src/common/riscv_debug.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. + * + ****************************************************************************/ + +/**************************************************************************** + * Notice: + * + * This driver is based on the RISC-V Debug Specification, version 0.13.2. + * The latest version of the specification can be found at: + * https://github.com/riscv/riscv-debug-spec + * + * The 1.0 version of the specification is still in RC phase, so there are + * no chips that support it yet. The 0.13.2 version is the latest stable + * version and some chips support it (e.g. QEMU RV, ESP32C3, BL602 etc). + * + * So this driver may needs to be updated when there is a new chip that + * supports the 1.0 version of the specification. + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <nuttx/config.h> +#include <nuttx/arch.h> + +#include <arch/chip/chip.h> +#include <arch/csr.h> + +#include <stdbool.h> + +#include "riscv_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Check the essential definition that must from chip vendor */ + +#ifndef RISCV_DEBUG_NR_TRIGGER +# error "Number of trigger in debug module is missing" +#endif + +/* CSR bits for TCONTROL */ + +#define TCONTROL_MTE (1 << 3) /* M-mode trigger enable */ +#define TCONTROL_MPTE (1 << 7) /* M-mode previous trigger enable */ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* Trigger Match Control, from version 0.13.2. + * Read https://riscv.org/wp-content/uploads/2019/03/riscv-debug-release.pdf + * for more information + */ + +union mcontrol +{ + uintptr_t reg; + struct + { + uintptr_t load : 1; + uintptr_t store : 1; + uintptr_t execute : 1; + uintptr_t u : 1; + uintptr_t s : 1; + uintptr_t reserved0 : 1; + uintptr_t m : 1; + uintptr_t match : 4; + uintptr_t chain : 1; + uintptr_t action : 4; + uintptr_t sizelo : 2; + uintptr_t timing : 1; + uintptr_t select : 1; + uintptr_t hit : 1; +#ifdef CONFIG_ARCH_RV64 + uintptr_t sizehi : 2; + uintptr_t reserved1 : 30; +#endif + uintptr_t maskmax : 6; + uintptr_t dmode : 1; + uintptr_t type : 4; + }; +}; + +struct riscv_debug_trigger +{ + int type; /* Trigger type */ + void *address; /* Trigger address */ + size_t size; /* Trigger region size */ + debug_callback_t callback; /* Debug callback */ + void *arg; /* Debug callback argument */ +}; + +/* Save the trigger address info */ + +static struct riscv_debug_trigger g_trigger_map[RISCV_DEBUG_NR_TRIGGER]; +static bool g_support_napot = false; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: debug_find_slot + * + * Description: + * -1 on fail, if address is NULL then to find a free slot in trigger map + * + ****************************************************************************/ + +static int debug_find_slot(int type, void *address, size_t size) +{ + int slot = -1; + int i; + + for (i = 0; i < RISCV_DEBUG_NR_TRIGGER; i++) + { + if (g_trigger_map[i].type == type && + g_trigger_map[i].address == address && + g_trigger_map[i].size == size) + { + slot = i; + break; + } + } + + return slot; +} + +static int riscv_debug_handler(int irq, FAR void *context, FAR void *arg) +{ + /* Get the trigger index */ + + int slot = READ_CSR(CSR_TSELECT); + + DEBUGASSERT(slot >= 0); + DEBUGASSERT(slot < RISCV_DEBUG_NR_TRIGGER); + + /* Call the trigger callback */ + + if (g_trigger_map[slot].callback) + { + g_trigger_map[slot].callback(g_trigger_map[slot].type, + g_trigger_map[slot].address, + g_trigger_map[slot].size, + g_trigger_map[slot].arg); + } + + return OK; +} + +/**************************************************************************** + * Name: up_debugpoint_add + ****************************************************************************/ + +void riscv_debug_init(void) +{ + union mcontrol mc; + + /* Attach the debug exception handler */ + + irq_attach(RISCV_IRQ_BPOINT, riscv_debug_handler, NULL); + + /* Clear the global trigger info & mark them as free slots */ + + memset(g_trigger_map, 0, sizeof(g_trigger_map)); + + /* Detect the support of NAPOT by trigger 0 */ + + WRITE_CSR(CSR_TSELECT, 0); + + mc.reg = READ_CSR(CSR_TDATA1); + + mc.match = 1; + + /* Write it to tdata1 and read back + * to check if the NAPOT is supported + */ + + WRITE_CSR(CSR_TDATA1, mc.reg); + mc.reg = READ_CSR(CSR_TDATA1); + + if (mc.match == 1) + { + g_support_napot = true; + } +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_debugpoint_add + ****************************************************************************/ + +int up_debugpoint_add(int type, FAR void *addr, size_t size, + debug_callback_t callback, FAR void *arg) +{ + int slot; + union mcontrol mc; + int ret = OK; + uintptr_t addr_napot; + + /* Find a free slot */ + + slot = debug_find_slot(0, 0, 0); + + if (slot >= 0) + { + /* Select the trigger */ + + WRITE_CSR(CSR_TSELECT, slot); + + /* Fetch the current setting from tdata1 */ + + mc.reg = READ_CSR(CSR_TDATA1); + + /* Configure trigger */ + + mc.m = 1; + mc.u = 1; + mc.hit = 0; + mc.dmode = 0; + mc.action = 0; + + mc.execute = 0; + mc.load = 0; + mc.store = 0; + + if (type == DEBUGPOINT_BREAKPOINT) + { + mc.execute = 1; + } + else if (type == DEBUGPOINT_WATCHPOINT_RO) + { + mc.load = 1; + } + else if (type == DEBUGPOINT_WATCHPOINT_WO) + { + mc.store = 1; + } + else if (type == DEBUGPOINT_WATCHPOINT_RW) + { + mc.load = 1; + mc.store = 1; + } + else + { + ret = -EINVAL; + return ret; + } + + /* From RISC-V Debug Specification: + * tdata1(mcontrol) match = 0 : Exact byte match + * + * tdata1(mcontrol) match = 1 : NAPOT (Naturally Aligned Power-Of-Two): + * + * Examples for understanding how to calculate match pattern to tdata2: + * + * nnnn...nnnnn 1-byte Exact byte match + * nnnn...nnnn0 2-byte NAPOT range + * nnnn...nnn01 4-byte NAPOT range + * nnnn...nn011 8-byte NAPOT range + * nnnn...n0111 16-byte NAPOT range + * nnnn...01111 32-byte NAPOT range + * ... + * n011...11111 2^31 byte NAPOT range + * * where n are bits from original address + */ + + if (size > 1 && g_support_napot) Review Comment: sizelo/sizehi are relatively advanced feature, may not be implemented on many SoC -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected]
