├── LICENSE ├── README.md ├── SConscript ├── docs └── README.md ├── port ├── DebugMon_Handler.c ├── dwt_cfg.h └── dwt_rtt_port.c └── src ├── armv7m_dwt.c └── armv7m_dwt.h /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2021-2022 BalanceTWK (balancetwk@yeah.net) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining 6 | a copy of this software and associated documentation files (the 7 | 'Software'), to deal in the Software without restriction, including 8 | without limitation the rights to use, copy, modify, merge, publish, 9 | distribute, sublicense, and/or sell copies of the Software, and to 10 | permit persons to whom the Software is furnished to do so, subject to 11 | the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be 14 | included in all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 20 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 21 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 22 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # armv7m_DWT 2 | 3 | armv7m_DWT: 基于 ARMV7M 架构设计的数据地址监控组件。 4 | 5 | 利用 CoreSight 的调试功能,实时监控每一次内存读写访问,必要时你可以在 `DebugMon_Handler` 调试中断里将访问内存时的现场打印出来,抓住**踩踏内存**的元凶! 6 | 7 | 如果觉得好用请点小星星,小星星就是对我最大的支持!(^_^) 8 | 9 | ## 1. 目录结构 10 | 11 | | 目录 | 说明 | 12 | | ---- | ------------------------------------------------- | 13 | | docs | 包含移植,原理等相关说明。 | 14 | | port | 移植文件(接管 debug 中断,输出打印,示例代码等) | 15 | | src | 核心源码,移植过程当中不需要修改。 | 16 | 17 | ## 2. API 说明 18 | 19 | #### 2.1 初始化 dwt 20 | 21 | 此函数将会使能 DWT 和 ITM 单元,并开启 DebugMonitor 的中断。 22 | 23 | ```c 24 | int dwt_init(void); 25 | ``` 26 | #### 2.2 反初始化 dwt 27 | 28 | 此函数将会失能 DWT 和 ITM 单元,关闭 DebugMonitor 中断,并将配置的参数清零。 29 | 30 | ```c 31 | int dwt_deinit(void) 32 | ``` 33 | 34 | #### 2.3 启动数据地址访问监控 35 | 36 | 此函数将会使用一个通道,启动对 `addr` 指向的内存地址的监控。一旦有线程或函数访问了此地址,就会产生 `DebugMon_Handler` 中断。 37 | 38 | ```c 39 | int data_address_watch_start(int ch, void *addr, uint32_t addr_mask, enum DWT_MODE mode); 40 | ``` 41 | 42 | | 参数 | 描述 | 43 | | --------- | ------------------------------------------------------------ | 44 | | ch | 选择要使用的监控通道。 | 45 | | addr | 要监控的内存地址。 | 46 | | addr_mask | 内存地址掩码。配合掩码可对一片内存地址进行监控。(注意:需小于等于 **0x0000001F**) | 47 | | mode | 监控模式,包含三种模式:1.读内存监控;2.写内存监控;3.读写内存监控; | 48 | 49 | #### 2.4 停止数据地址访问监控 50 | 51 | 此函数将会停止一个通道的监控功能,与 `data_address_watch_start` 成对使用。 52 | 53 | ```c 54 | int data_address_watch_stop(int ch) 55 | ``` 56 | 57 | | 参数 | 描述 | 58 | | ---- | ---------------------- | 59 | | ch | 选择要关闭的监控通道。 | 60 | 61 | #### 2.5 启动数据内容匹配监控 62 | 63 | 此函数将会使用多个通道,启动对最多两个内存地址上的内容的监控。一旦监控地址上的值与 `compare_value` 相等,就会产生一次 `DebugMon_Handler` 中断。 64 | 65 | ```c 66 | int data_value_watch_start(int ch, void *addr1, void *addr2, void *compare_value, enum DWT_DATA_SIZE data_size) 67 | ``` 68 | 69 | | 参数 | 描述 | 70 | | ------------- | -------------------------------------------- | 71 | | ch | 选择要使用的监控通道。 | 72 | | addr1 | 监控的内存地址1。(可填入 NULL ) | 73 | | addr2 | 监控的内存地址2。(可填入 NULL ) | 74 | | compare_value | 比较值。 | 75 | | data_size | 数据类型。(1. byte;2. half word;3. word) | 76 | 77 | #### 2.6 停止数据内容匹配监控 78 | 79 | 此函数将会停止一个通道的监控功能,与 `data_value_watch_start` 成对使用。 80 | 81 | ```c 82 | int data_value_watch_stop(int ch) 83 | ``` 84 | 85 | | 参数 | 描述 | 86 | | ---- | ---------------------- | 87 | | ch | 选择要关闭的监控通道。 | 88 | 89 | ## 3. 使用流程 90 | 91 | #### 3.1 内存地址监控 92 | 93 | ```c 94 | int dwt_address_test(int argc, char **argv) 95 | { 96 | int ch; 97 | int ret; 98 | volatile rt_uint8_t temp; 99 | temp = 0x55; 100 | databuf[1] = 0x00 ; 101 | 102 | /* 1.第一步 */ 103 | dwt_init(); 104 | ch = 1; 105 | /* 2.第二步 */ 106 | // ret = data_address_watch_start(ch, (void*)&databuf[1], 0x00000000, READ_ONLY); 107 | ret = data_address_watch_start(ch, (void*)&databuf[1], 0x00000000, READ_WRITE); 108 | // ret = data_address_watch_start(ch, (void*)&databuf[1], 0x00000000, WRITE_ONLY); 109 | if(ret != 0) 110 | { 111 | return 0; 112 | } 113 | rt_kprintf("1. temp = databuf[1];\r\n"); 114 | rt_thread_mdelay(500); 115 | temp = databuf[1]; 116 | 117 | rt_kprintf("2. databuf[1] = 0x55 ;\r\n"); 118 | rt_thread_mdelay(500); 119 | databuf[1] = 0x55 ; 120 | 121 | /* 3.第三步 */ 122 | data_address_watch_stop(ch); 123 | /* 4.第四步 */ 124 | dwt_deinit(); 125 | 126 | return 0; 127 | } 128 | ``` 129 | 130 | #### 3.1 内存数值监控 131 | 132 | ```c 133 | int dwt_value_test(int argc, char **argv) 134 | { 135 | int ch; 136 | int ret; 137 | volatile rt_uint8_t temp; 138 | temp = 0x55; 139 | databuf[1] = 0x00 ; 140 | databuf[2] = 0x00 ; 141 | 142 | /* 1.第一步 */ 143 | dwt_init(); 144 | ch = 1; 145 | /* 2.第二步 */ 146 | ret = data_value_watch_start(ch, (void*)&databuf[1], (void*)&databuf[2], (void*)&temp, SIZE_BYTE); 147 | // ret = data_value_watch_start(ch, (void*)NULL, (void*)&databuf[2], (void*)&temp, SIZE_BYTE); 148 | if(ret != 0) 149 | { 150 | return 0; 151 | } 152 | 153 | rt_kprintf("1. temp = databuf[1];\r\n"); 154 | rt_thread_mdelay(500); 155 | temp = databuf[1]; 156 | rt_kprintf("2. temp = databuf[2];\r\n"); 157 | rt_thread_mdelay(500); 158 | temp = databuf[2]; 159 | 160 | rt_kprintf("3. databuf[1] = 0x55 ;\r\n"); 161 | rt_thread_mdelay(500); 162 | databuf[1] = 0x55 ; 163 | rt_kprintf("4. databuf[2] = 0x55 ;\r\n"); 164 | rt_thread_mdelay(500); 165 | databuf[2] = 0x55 ; 166 | 167 | rt_thread_mdelay(500); 168 | 169 | rt_kprintf("5. temp = databuf[1];\r\n"); 170 | rt_thread_mdelay(500); 171 | temp = databuf[1]; 172 | rt_kprintf("6. temp = databuf[2];\r\n"); 173 | rt_thread_mdelay(500); 174 | temp = databuf[2]; 175 | 176 | 177 | rt_kprintf("7. databuf[1] = 0x56 ;\r\n"); 178 | rt_thread_mdelay(500); 179 | databuf[1] = 0x56 ; 180 | rt_kprintf("8. databuf[2] = 0x56 ;\r\n"); 181 | rt_thread_mdelay(500); 182 | databuf[2] = 0x56 ; 183 | 184 | /* 3.第三步 */ 185 | data_value_watch_stop(ch); 186 | /* 4.第四步 */ 187 | dwt_deinit(); 188 | 189 | return 0; 190 | } 191 | ``` 192 | -------------------------------------------------------------------------------- /SConscript: -------------------------------------------------------------------------------- 1 | from building import * 2 | 3 | cwd = GetCurrentDir() 4 | 5 | src = [] 6 | path = [] 7 | 8 | src += ['src/armv7m_dwt.c'] 9 | path += [cwd + '/src'] 10 | 11 | src += ['port/DebugMon_Handler.c'] 12 | src += ['port/dwt_rtt_port.c'] 13 | path += [cwd + '/port'] 14 | 15 | 16 | group = DefineGroup('arm_dwt', src, depend = ['PKG_USING_ARMV7M_DWT_TOOL'], CPPPATH = path) 17 | 18 | Return('group') 19 | -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/balanceTWK/armv7m_DWT/4d83e405ce6a5a6f95a742324234b828f24bcdd1/docs/README.md -------------------------------------------------------------------------------- /port/DebugMon_Handler.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the armv7m_DWT Library. 3 | * 4 | * Copyright (c) 2021-2022, BalanceTWK (balancetwk@yeah.net) 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining 7 | * a copy of this software and associated documentation files (the 8 | * 'Software'), to deal in the Software without restriction, including 9 | * without limitation the rights to use, copy, modify, merge, publish, 10 | * distribute, sublicense, and/or sell copies of the Software, and to 11 | * permit persons to whom the Software is furnished to do so, subject to 12 | * the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be 15 | * included in all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, 18 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 21 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 22 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 23 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | * 25 | * Function: Initialize function and other general function. 26 | * Created on: 2022-06-16 27 | */ 28 | 29 | #include "dwt_cfg.h" 30 | 31 | void DebugMon_Handler(void) 32 | { 33 | dwt_println("DebugMon_Handler\r\n"); 34 | #ifdef PKG_USING_ARMV7M_DWT_TOOL_DEMO 35 | extern int armv7_dwt_rtt_demo(void); 36 | armv7_dwt_rtt_demo(); 37 | #endif 38 | } 39 | -------------------------------------------------------------------------------- /port/dwt_cfg.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the armv7m_DWT Library. 3 | * 4 | * Copyright (c) 2021-2022, BalanceTWK (balancetwk@yeah.net) 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining 7 | * a copy of this software and associated documentation files (the 8 | * 'Software'), to deal in the Software without restriction, including 9 | * without limitation the rights to use, copy, modify, merge, publish, 10 | * distribute, sublicense, and/or sell copies of the Software, and to 11 | * permit persons to whom the Software is furnished to do so, subject to 12 | * the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be 15 | * included in all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, 18 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 21 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 22 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 23 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | * 25 | * Function: Initialize function and other general function. 26 | * Created on: 2022-06-16 27 | */ 28 | 29 | #ifndef _DWT_CFG_H_ 30 | #define _DWT_CFG_H_ 31 | 32 | #define COMPARATOR_MAX 4 33 | 34 | #ifdef __RTTHREAD__ 35 | #include 36 | 37 | #define dwt_println(...) rt_kprintf(__VA_ARGS__); 38 | 39 | #else 40 | 41 | #endif 42 | 43 | #endif /* _DWT_CFG_H_ */ 44 | -------------------------------------------------------------------------------- /port/dwt_rtt_port.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the armv7m_DWT Library. 3 | * 4 | * Copyright (c) 2021-2022, BalanceTWK (balancetwk@yeah.net) 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining 7 | * a copy of this software and associated documentation files (the 8 | * 'Software'), to deal in the Software without restriction, including 9 | * without limitation the rights to use, copy, modify, merge, publish, 10 | * distribute, sublicense, and/or sell copies of the Software, and to 11 | * permit persons to whom the Software is furnished to do so, subject to 12 | * the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be 15 | * included in all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, 18 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 21 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 22 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 23 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | * 25 | * Function: Initialize function and other general function. 26 | * Created on: 2022-06-16 27 | */ 28 | 29 | #include 30 | #include 31 | #include "armv7m_dwt.h" 32 | 33 | #include 34 | 35 | MSH_CMD_EXPORT(dwt_show_support, Shows DWT support information.); 36 | MSH_CMD_EXPORT(dwt_show_info, Shows DWT usage information.); 37 | MSH_CMD_EXPORT(dwt_init, Initialize DWT peripherals.); 38 | MSH_CMD_EXPORT(dwt_deinit, Restore DWT peripherals.); 39 | 40 | #ifdef PKG_USING_ARMV7M_DWT_TOOL_DEMO 41 | 42 | #define CALL_STACK_MAX_DEPTH 64 43 | #define GET_THREAD_STACK_START (uint32_t)(rt_thread_self()->stack_addr) 44 | #define GET_THREAD_STACK_SIZE rt_thread_self()->stack_size 45 | #define CODE_FLASH_START 0x08000000 46 | #define CODE_FLASH_END (CODE_FLASH_START+(128*1024*1024)) 47 | 48 | /* include or export for supported cmb_get_msp, cmb_get_psp and cmb_get_sp function */ 49 | #if defined(__CC_ARM) 50 | static __inline __asm uint32_t cmb_get_msp(void) { 51 | mrs r0, msp 52 | bx lr 53 | } 54 | static __inline __asm uint32_t cmb_get_psp(void) { 55 | mrs r0, psp 56 | bx lr 57 | } 58 | static __inline __asm uint32_t cmb_get_sp(void) { 59 | mov r0, sp 60 | bx lr 61 | } 62 | #elif defined(__CLANG_ARM) 63 | __attribute__( (always_inline) ) static __inline uint32_t cmb_get_msp(void) { 64 | uint32_t result; 65 | __asm volatile ("mrs %0, msp" : "=r" (result) ); 66 | return (result); 67 | } 68 | __attribute__( (always_inline) ) static __inline uint32_t cmb_get_psp(void) { 69 | uint32_t result; 70 | __asm volatile ("mrs %0, psp" : "=r" (result) ); 71 | return (result); 72 | } 73 | __attribute__( (always_inline) ) static __inline uint32_t cmb_get_sp(void) { 74 | uint32_t result; 75 | __asm volatile ("mov %0, sp" : "=r" (result) ); 76 | return (result); 77 | } 78 | #elif defined(__ICCARM__) 79 | /* IAR iccarm specific functions */ 80 | /* Close Raw Asm Code Warning */ 81 | #pragma diag_suppress=Pe940 82 | static uint32_t cmb_get_msp(void) 83 | { 84 | __asm("mrs r0, msp"); 85 | __asm("bx lr"); 86 | } 87 | static uint32_t cmb_get_psp(void) 88 | { 89 | __asm("mrs r0, psp"); 90 | __asm("bx lr"); 91 | } 92 | static uint32_t cmb_get_sp(void) 93 | { 94 | __asm("mov r0, sp"); 95 | __asm("bx lr"); 96 | } 97 | #pragma diag_default=Pe940 98 | #elif defined(__GNUC__) 99 | __attribute__( ( always_inline ) ) static inline uint32_t cmb_get_msp(void) { 100 | register uint32_t result; 101 | __asm volatile ("MRS %0, msp\n" : "=r" (result) ); 102 | return(result); 103 | } 104 | __attribute__( ( always_inline ) ) static inline uint32_t cmb_get_psp(void) { 105 | register uint32_t result; 106 | __asm volatile ("MRS %0, psp\n" : "=r" (result) ); 107 | return(result); 108 | } 109 | __attribute__( ( always_inline ) ) static inline uint32_t cmb_get_sp(void) { 110 | register uint32_t result; 111 | __asm volatile ("MOV %0, sp\n" : "=r" (result) ); 112 | return(result); 113 | } 114 | #else 115 | #error "not supported compiler" 116 | #endif 117 | 118 | typedef struct 119 | { 120 | uint32_t r0;// Register R0 121 | uint32_t r1;// Register R1 122 | uint32_t r2;// Register R2 123 | uint32_t r3;// Register R3 124 | uint32_t r12;// Register R12 125 | uint32_t lr;// Link register LR 126 | uint32_t pc;// Program counter PC 127 | uint32_t psr;// Program status word PSR 128 | }context_reg; 129 | #define BL_INS_MASK 0xF800 130 | #define BL_INS_HIGH 0xF800 131 | #define BL_INS_LOW 0xF000 132 | #define BLX_INX_MASK 0xFF00 133 | #define BLX_INX 0x4700 134 | 135 | /* check the disassembly instruction is 'BL' or 'BLX' */ 136 | static int disassembly_ins_is_bl_blx(uint32_t addr) 137 | { 138 | uint16_t ins1 = *((uint16_t *)addr); 139 | uint16_t ins2 = *((uint16_t *)(addr + 2)); 140 | 141 | if ((ins2 & BL_INS_MASK) == BL_INS_HIGH && (ins1 & BL_INS_MASK) == BL_INS_LOW) 142 | { 143 | return 1; 144 | } 145 | else if ((ins2 & BLX_INX_MASK) == BLX_INX) 146 | { 147 | return 1; 148 | } 149 | else 150 | { 151 | return 0; 152 | } 153 | } 154 | 155 | void prepare_call_stack_buf(uint32_t *buf, size_t size, uint32_t sp) 156 | { 157 | uint32_t stack_start; 158 | uint32_t stack_size; 159 | uint32_t pc; 160 | size_t depth = 0; 161 | 162 | stack_start = GET_THREAD_STACK_START; 163 | stack_size = GET_THREAD_STACK_SIZE; 164 | for (; sp < stack_start + stack_size; sp += sizeof(size_t)) 165 | { 166 | pc = *((uint32_t *) sp) - sizeof(size_t); 167 | if (pc % 2 == 0) 168 | { 169 | continue; 170 | } 171 | pc = *((uint32_t *)sp) - 1; 172 | if((pc < CODE_FLASH_START) || (pc > CODE_FLASH_END)) 173 | { 174 | continue; 175 | } 176 | if (disassembly_ins_is_bl_blx(pc - sizeof(size_t))) 177 | { 178 | buf[depth++] = pc; 179 | if(depth ==size) 180 | { 181 | break; 182 | } 183 | } 184 | } 185 | } 186 | 187 | int armv7_dwt_rtt_demo(void) 188 | { 189 | rt_kprintf("thread:%s psp:0x%08X\r\n",rt_thread_self()->name,cmb_get_psp()); 190 | #ifdef RT_USING_FINSH 191 | extern long list_thread(void); 192 | list_thread(); 193 | #endif 194 | uint32_t call_stack_buf[16] = {0}; 195 | prepare_call_stack_buf(call_stack_buf,sizeof(call_stack_buf),cmb_get_psp()); 196 | 197 | rt_kprintf("\r\naddr2line -e rtthread.elf -a -f"); 198 | for (int i = 0; i < sizeof(call_stack_buf); i++) 199 | { 200 | if(call_stack_buf[i]) 201 | { 202 | rt_kprintf(" %08X",call_stack_buf[i]); 203 | } 204 | else 205 | { 206 | break; 207 | } 208 | } 209 | rt_kprintf("\r\n"); 210 | 211 | return 0; 212 | } 213 | 214 | char databuf[64]; 215 | 216 | int dwt_value_test(int argc, char **argv) 217 | { 218 | int ch; 219 | int ret; 220 | volatile rt_uint8_t temp; 221 | temp = 0x55; 222 | databuf[1] = 0x00 ; 223 | databuf[2] = 0x00 ; 224 | 225 | if(argc == 2) 226 | { 227 | ch = strtol(argv[1], NULL, 0); 228 | ret = data_value_watch_start(ch, (void*)&databuf[1], (void*)&databuf[2], (void*)&temp, SIZE_BYTE); 229 | // ret = data_value_watch_start(ch, (void*)NULL, (void*)&databuf[2], (void*)&temp, SIZE_BYTE); 230 | if(ret != 0) 231 | { 232 | return 0; 233 | } 234 | 235 | rt_kprintf("1. temp = databuf[1];\r\n"); 236 | rt_thread_mdelay(500); 237 | temp = databuf[1]; 238 | rt_kprintf("2. temp = databuf[2];\r\n"); 239 | rt_thread_mdelay(500); 240 | temp = databuf[2]; 241 | 242 | rt_kprintf("3. databuf[1] = 0x55 ;\r\n"); 243 | rt_thread_mdelay(500); 244 | databuf[1] = 0x55 ; 245 | rt_kprintf("4. databuf[2] = 0x55 ;\r\n"); 246 | rt_thread_mdelay(500); 247 | databuf[2] = 0x55 ; 248 | 249 | rt_thread_mdelay(500); 250 | 251 | rt_kprintf("5. temp = databuf[1];\r\n"); 252 | rt_thread_mdelay(500); 253 | temp = databuf[1]; 254 | rt_kprintf("6. temp = databuf[2];\r\n"); 255 | rt_thread_mdelay(500); 256 | temp = databuf[2]; 257 | 258 | 259 | rt_kprintf("7. databuf[1] = 0x56 ;\r\n"); 260 | rt_thread_mdelay(500); 261 | databuf[1] = 0x56 ; 262 | rt_kprintf("8. databuf[2] = 0x56 ;\r\n"); 263 | rt_thread_mdelay(500); 264 | databuf[2] = 0x56 ; 265 | 266 | data_value_watch_stop(ch); 267 | } 268 | else 269 | { 270 | rt_kprintf("command: dwt_value_watch 1\r\n"); 271 | } 272 | return 0; 273 | } 274 | MSH_CMD_EXPORT(dwt_value_test, dwt_value_test); 275 | 276 | int dwt_address_test(int argc, char **argv) 277 | { 278 | int ch; 279 | int ret; 280 | volatile rt_uint8_t temp; 281 | temp = 0x55; 282 | databuf[1] = 0x00 ; 283 | 284 | if(argc == 2) 285 | { 286 | ch = strtol(argv[1], NULL, 0); 287 | // ret = data_address_watch_start(ch, (void*)&databuf[1], 0x00000000, READ_ONLY); 288 | ret = data_address_watch_start(ch, (void*)&databuf[1], 0x00000000, READ_WRITE); 289 | // ret = data_address_watch_start(ch, (void*)&databuf[1], 0x00000000, WRITE_ONLY); 290 | if(ret != 0) 291 | { 292 | return 0; 293 | } 294 | rt_kprintf("1. temp = databuf[1];\r\n"); 295 | rt_thread_mdelay(500); 296 | temp = databuf[1]; 297 | 298 | 299 | rt_kprintf("2. databuf[1] = 0x55 ;\r\n"); 300 | rt_thread_mdelay(500); 301 | databuf[1] = 0x55 ; 302 | 303 | data_address_watch_stop(ch); 304 | } 305 | else 306 | { 307 | rt_kprintf("command: dwt_value_watch 1\r\n"); 308 | } 309 | } 310 | MSH_CMD_EXPORT(dwt_address_test, dwt_address_test); 311 | 312 | #endif 313 | -------------------------------------------------------------------------------- /src/armv7m_dwt.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the armv7m_DWT Library. 3 | * 4 | * Copyright (c) 2021-2022, BalanceTWK (balancetwk@yeah.net) 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining 7 | * a copy of this software and associated documentation files (the 8 | * 'Software'), to deal in the Software without restriction, including 9 | * without limitation the rights to use, copy, modify, merge, publish, 10 | * distribute, sublicense, and/or sell copies of the Software, and to 11 | * permit persons to whom the Software is furnished to do so, subject to 12 | * the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be 15 | * included in all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, 18 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 21 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 22 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 23 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | * 25 | * Function: Initialize function and other general function. 26 | * Created on: 2022-06-16 27 | */ 28 | 29 | #include "dwt_cfg.h" 30 | #include "armv7m_dwt.h" 31 | 32 | typedef volatile struct 33 | { 34 | volatile uint32_t DHCSR; 35 | volatile uint32_t DCRSR; 36 | volatile uint32_t DCRDR; 37 | union /* Manages vector catch behavior and DebugMonitor handling when debugging. */ 38 | { 39 | volatile uint32_t all_in_one; 40 | struct 41 | { 42 | volatile uint32_t VC_CORERESET : 1; 43 | volatile uint32_t : 3; 44 | volatile uint32_t VC_MMERR : 1; 45 | volatile uint32_t VC_NOCPERR : 1; 46 | volatile uint32_t VC_CHKERR : 1; 47 | volatile uint32_t VC_STATERR : 1; 48 | volatile uint32_t VC_BUSERR : 1; 49 | volatile uint32_t VC_INTERR : 1; 50 | volatile uint32_t VC_HARDERR : 1; 51 | volatile uint32_t : 5; 52 | volatile uint32_t MON_EN : 1; 53 | volatile uint32_t MON_PEND : 1; 54 | volatile uint32_t MON_STEP : 1; 55 | volatile uint32_t MON_REQ : 1; 56 | volatile uint32_t : 4; 57 | volatile uint32_t TRCENA : 1; 58 | volatile uint32_t : 7; 59 | }; 60 | } DEMCR; 61 | } arm_debug_system_reg_t; 62 | 63 | #define DEBUG_SYSTEM_BASE_ADDRESS 0xE000EDF0 64 | #define DEBUG_SYSTEM (*(arm_debug_system_reg_t *)DEBUG_SYSTEM_BASE_ADDRESS) 65 | 66 | typedef volatile struct 67 | { 68 | uint32_t FB_CTRL; 69 | union 70 | { 71 | void *address; 72 | struct 73 | { 74 | const uint32_t : 29; 75 | const uint32_t RMPSPT : 1; 76 | const uint32_t : 2; 77 | }; 78 | } FP_REMAP; 79 | union 80 | { 81 | uintptr_t address; 82 | struct 83 | { 84 | uint32_t ENABLE : 1; 85 | uint32_t : 1; 86 | uint32_t COMP : 27; 87 | uint32_t : 1; 88 | uint32_t REPLACE : 2; 89 | }; 90 | } FP_COMP[8]; 91 | } arm_fpb_reg_t; 92 | 93 | #define FPB_BASE_ADDRESS 0xE0002000 94 | #define FPB (*(arm_fpb_reg_t *)FPB_BASE_ADDRESS) 95 | 96 | typedef volatile struct 97 | { 98 | volatile uint32_t DWT_COMP; 99 | union 100 | { 101 | volatile uint32_t all_in_one; 102 | struct 103 | { 104 | volatile uint32_t MASK : 5; 105 | volatile uint32_t : 27; 106 | }; 107 | } DWT_MASK; 108 | union 109 | { 110 | volatile uint32_t all_in_one; 111 | struct 112 | { 113 | volatile uint32_t FUNCTION : 4; 114 | volatile uint32_t : 1; 115 | volatile uint32_t EMITRANGE : 1; 116 | volatile uint32_t : 1; 117 | volatile uint32_t CYCMATCH : 1; 118 | volatile uint32_t DATAVMATCH : 1; 119 | volatile uint32_t LNK1ENA : 1; 120 | volatile uint32_t DATAVSIZE : 2; 121 | volatile uint32_t DATAVADDR0 : 4; 122 | volatile uint32_t DATAVADDR1 : 4; 123 | volatile uint32_t : 4; 124 | volatile uint32_t MATCHED : 1; 125 | volatile uint32_t : 7; 126 | }; 127 | } DWT_FUNCTION; 128 | uint32_t RESERVERED; 129 | }dwt_comparator_t; 130 | typedef volatile struct 131 | { 132 | union 133 | { 134 | volatile uint32_t all_in_one; 135 | struct 136 | { 137 | volatile uint32_t CYCCNTENA : 1; 138 | volatile uint32_t POSTPRESET : 4; 139 | volatile uint32_t POSTINIT : 4; 140 | volatile uint32_t CYCTAP : 1; 141 | volatile uint32_t SYNCTAP : 2; 142 | volatile uint32_t PCSAMPLENA : 1; 143 | volatile uint32_t : 3; 144 | volatile uint32_t EXCTRCENA : 1; 145 | volatile uint32_t CPIEVTENA : 1; 146 | volatile uint32_t EXCEVTENA : 1; 147 | volatile uint32_t SLEEPEVTENA : 1; 148 | volatile uint32_t LSUEVTENA : 1; 149 | volatile uint32_t FOLDEVTENA : 1; 150 | volatile uint32_t CYCEVTENA : 1; 151 | volatile uint32_t : 1; 152 | volatile uint32_t NOPRFCNT : 1; 153 | volatile uint32_t NOCYCCNT : 1; 154 | volatile uint32_t NOEXTTRIG : 1; 155 | volatile uint32_t NOTRCPKT : 1; 156 | volatile uint32_t NUMCOMP : 4; 157 | }; 158 | } DWT_CTRL; 159 | volatile uint32_t DWT_CYCCNT; 160 | volatile uint32_t DWT_CPICNT; 161 | volatile uint32_t DWT_EXCCNT; 162 | volatile uint32_t DWT_SLEEPCNT; 163 | volatile uint32_t DWT_LSUCNT; 164 | volatile uint32_t DWT_FOLDCNT; 165 | volatile uint32_t DWT_PCSR; 166 | volatile dwt_comparator_t COMPARATOR[16]; 167 | } arm_dwt_reg_t; 168 | 169 | #define DWT_BASE_ADDRESS 0xE0001000 170 | #define CORESIGHT_DWT (*(arm_dwt_reg_t *)DWT_BASE_ADDRESS) 171 | 172 | #define CoreDebug_BASE (0xE000EDF0UL) /*!< Core Debug Base Address */ 173 | #define CoreDebug ((CoreDebug_Type *) CoreDebug_BASE) /*!< Core Debug configuration struct */ 174 | 175 | typedef volatile struct 176 | { 177 | uint32_t can_cyccnt; 178 | uint32_t can_address_watch; 179 | uint32_t can_value_watch; 180 | uint32_t can_double_value_watch; 181 | }armv7m_dwt_comparator; 182 | 183 | armv7m_dwt_comparator dwt_comparator[COMPARATOR_MAX] = {0}; 184 | 185 | int dwt_show_support(void) 186 | { 187 | dwt_println("\r\n"); 188 | if(DEBUG_SYSTEM.DEMCR.TRCENA == 0) 189 | { 190 | dwt_println("=========================================\r\n"); 191 | dwt_println("| !!!warning: DEBUG_SYSTEM is disable |\r\n"); 192 | dwt_println("| You may need to call dwt_init() first.|\r\n"); 193 | dwt_println("=========================================\r\n"); 194 | return -1; 195 | } 196 | dwt_println("========================== DWT channels SUPPORT ===========================\r\n"); 197 | dwt_println("| %-*.*s | CYCCNT | address compare | vaule_0 compare | value_1 compare |\r\n", 8, 8, "channels"); 198 | dwt_println("---------------------------------------------------------------------------\r\n"); 199 | for (int i = 0; i < CORESIGHT_DWT.DWT_CTRL.NUMCOMP; i++) 200 | { 201 | dwt_println("| ch[%02d] |",i); 202 | dwt_println(" %-*.*s |", 6, 6, dwt_comparator[i].can_cyccnt ? "YES":"NO"); 203 | dwt_println(" %-*.*s |", 15, 15, dwt_comparator[i].can_address_watch ? "YES":"NO"); 204 | dwt_println(" %-*.*s |", 15, 15, dwt_comparator[i].can_value_watch ? "YES":"NO"); 205 | dwt_println(" %-*.*s |", 15, 15, dwt_comparator[i].can_double_value_watch ? "YES":"NO"); 206 | dwt_println("\r\n"); 207 | } 208 | dwt_println("===========================================================================\r\n"); 209 | return 0; 210 | } 211 | 212 | int dwt_show_info(void) 213 | { 214 | dwt_println("\r\n"); 215 | if(DEBUG_SYSTEM.DEMCR.TRCENA == 0) 216 | { 217 | dwt_println("=========================================\r\n"); 218 | dwt_println("| !!!warning: DEBUG_SYSTEM is disable |\r\n"); 219 | dwt_println("| You may need to call dwt_init() first.|\r\n"); 220 | dwt_println("=========================================\r\n"); 221 | return -1; 222 | } 223 | dwt_println("============= DWT channels table =============\r\n"); 224 | dwt_println("| %-*.*s | value compare | address compare |\r\n", 8, 8, "channels"); 225 | dwt_println("----------------------------------------------\r\n"); 226 | for (int i = 0; i < CORESIGHT_DWT.DWT_CTRL.NUMCOMP; i++) 227 | { 228 | dwt_println("| ch[%02d] |",i); 229 | if(CORESIGHT_DWT.COMPARATOR[i].DWT_FUNCTION.DATAVMATCH) 230 | { 231 | switch (CORESIGHT_DWT.COMPARATOR[i].DWT_FUNCTION.DATAVSIZE) 232 | { 233 | case SIZE_BYTE: 234 | dwt_println(" 0x%08X |", (uint8_t)(CORESIGHT_DWT.COMPARATOR[i].DWT_COMP)); 235 | break; 236 | case SIZE_HALF_WORD: 237 | dwt_println(" 0x%08X |", (uint16_t)(CORESIGHT_DWT.COMPARATOR[i].DWT_COMP)); 238 | break; 239 | case SIZE_WORD: 240 | dwt_println(" 0x%08X |", (uint32_t)(CORESIGHT_DWT.COMPARATOR[i].DWT_COMP)); 241 | break; 242 | default: 243 | dwt_println(" 0x%08X |", (uint32_t)(CORESIGHT_DWT.COMPARATOR[i].DWT_COMP)); 244 | break; 245 | } 246 | dwt_println(" ch[%02d] ch[%02d] |",CORESIGHT_DWT.COMPARATOR[i].DWT_FUNCTION.DATAVADDR0, (CORESIGHT_DWT.COMPARATOR[i].DWT_FUNCTION.DATAVADDR0!=CORESIGHT_DWT.COMPARATOR[i].DWT_FUNCTION.DATAVADDR1) ? CORESIGHT_DWT.COMPARATOR[i].DWT_FUNCTION.DATAVADDR1:-1); 247 | } 248 | else 249 | { 250 | dwt_println(" NULL |"); 251 | if((CORESIGHT_DWT.COMPARATOR[i].DWT_FUNCTION.DATAVMATCH == 0)&&(CORESIGHT_DWT.COMPARATOR[i].DWT_FUNCTION.FUNCTION != 0)) 252 | { 253 | dwt_println(" 0x%08X |",CORESIGHT_DWT.COMPARATOR[i].DWT_COMP); 254 | } 255 | else 256 | { 257 | dwt_println(" NULL |"); 258 | } 259 | } 260 | dwt_println("\r\n"); 261 | } 262 | dwt_println("==============================================\r\n"); 263 | 264 | } 265 | 266 | int dwt_init(void) 267 | { 268 | /* Global enable for all DWT and ITM features. */ 269 | DEBUG_SYSTEM.DEMCR.TRCENA = 1; 270 | /* Enable the DebugMonitor exception. */ 271 | DEBUG_SYSTEM.DEMCR.MON_EN = 1; 272 | CORESIGHT_DWT.DWT_CTRL.all_in_one = 0x00000000; 273 | 274 | for (int i = 0; i < CORESIGHT_DWT.DWT_CTRL.NUMCOMP; i++) 275 | { 276 | dwt_comparator[i].can_address_watch = 0; 277 | dwt_comparator[i].can_cyccnt = 0; 278 | dwt_comparator[i].can_value_watch = 0; 279 | dwt_comparator[i].can_double_value_watch = 0; 280 | } 281 | 282 | if(!CORESIGHT_DWT.DWT_CTRL.NOCYCCNT) 283 | { 284 | for (int i = 0; i < CORESIGHT_DWT.DWT_CTRL.NUMCOMP; i++) 285 | { 286 | CORESIGHT_DWT.COMPARATOR[i].DWT_FUNCTION.CYCMATCH = 1; 287 | if(CORESIGHT_DWT.COMPARATOR[i].DWT_FUNCTION.CYCMATCH) 288 | { 289 | dwt_comparator[i].can_cyccnt = 1; 290 | CORESIGHT_DWT.COMPARATOR[i].DWT_FUNCTION.CYCMATCH = 0; 291 | } 292 | } 293 | } 294 | for (int i = 0; i < CORESIGHT_DWT.DWT_CTRL.NUMCOMP; i++) 295 | { 296 | dwt_comparator[i].can_address_watch = 1; 297 | } 298 | if(CORESIGHT_DWT.DWT_CTRL.NOCYCCNT == 0) 299 | { 300 | for (int i = 0; i < CORESIGHT_DWT.DWT_CTRL.NUMCOMP; i++) 301 | { 302 | CORESIGHT_DWT.COMPARATOR[i].DWT_FUNCTION.DATAVMATCH = 1; 303 | if(CORESIGHT_DWT.COMPARATOR[i].DWT_FUNCTION.DATAVMATCH) 304 | { 305 | dwt_comparator[i].can_value_watch = 1; 306 | if(CORESIGHT_DWT.COMPARATOR[i].DWT_FUNCTION.LNK1ENA) 307 | { 308 | dwt_comparator[i].can_double_value_watch = 1; 309 | } 310 | CORESIGHT_DWT.COMPARATOR[i].DWT_FUNCTION.DATAVMATCH = 0; 311 | } 312 | } 313 | } 314 | 315 | for (int i = 0; i < CORESIGHT_DWT.DWT_CTRL.NUMCOMP; i++) 316 | { 317 | CORESIGHT_DWT.COMPARATOR[i].DWT_FUNCTION.all_in_one = 0x00000000; 318 | CORESIGHT_DWT.COMPARATOR[i].DWT_COMP = 0; 319 | CORESIGHT_DWT.COMPARATOR[i].DWT_MASK.MASK = 0; 320 | } 321 | dwt_show_support(); 322 | } 323 | 324 | int dwt_deinit(void) 325 | { 326 | CORESIGHT_DWT.DWT_CTRL.all_in_one = 0x00000000; 327 | for (int i = 0; i < CORESIGHT_DWT.DWT_CTRL.NUMCOMP; i++) 328 | { 329 | CORESIGHT_DWT.COMPARATOR[i].DWT_FUNCTION.all_in_one = 0x00000000; 330 | CORESIGHT_DWT.COMPARATOR[i].DWT_COMP = 0; 331 | CORESIGHT_DWT.COMPARATOR[i].DWT_MASK.MASK = 0; 332 | } 333 | /* Disenable all DWT and ITM features. */ 334 | DEBUG_SYSTEM.DEMCR.TRCENA = 0; 335 | /* Disenable the DebugMonitor exception. */ 336 | DEBUG_SYSTEM.DEMCR.MON_EN = 0; 337 | } 338 | 339 | int data_address_watch_start(int ch, void *addr, uint32_t addr_mask, enum DWT_MODE mode) 340 | { 341 | if(DEBUG_SYSTEM.DEMCR.TRCENA == 0) 342 | { 343 | dwt_println("=========================================\r\n"); 344 | dwt_println("| !!!warning: DEBUG_SYSTEM is disable |\r\n"); 345 | dwt_println("| You may need to call dwt_init() first.|\r\n"); 346 | dwt_println("=========================================\r\n"); 347 | return -1; 348 | } 349 | if( ch >= CORESIGHT_DWT.DWT_CTRL.NUMCOMP) 350 | { 351 | dwt_println("[ERROR]: The chip only supports [0-%d] channels, or You are not use \"dwt_init()\" first to enable DWT !\r\n", CORESIGHT_DWT.DWT_CTRL.NUMCOMP-1); 352 | return -1; 353 | } 354 | if(addr_mask > 0x0000001F) 355 | { 356 | dwt_println("[ERROR]: addr_mask is not greater than 0x0000001F\r\n"); 357 | return -1; 358 | } 359 | 360 | CORESIGHT_DWT.COMPARATOR[ch].DWT_COMP = (uint32_t)addr; 361 | CORESIGHT_DWT.COMPARATOR[ch].DWT_MASK.all_in_one = addr_mask; 362 | CORESIGHT_DWT.COMPARATOR[ch].DWT_FUNCTION.FUNCTION = mode; 363 | 364 | dwt_show_info(); 365 | return 0; 366 | } 367 | 368 | int data_address_watch_stop(int ch) 369 | { 370 | CORESIGHT_DWT.COMPARATOR[ch].DWT_FUNCTION.all_in_one = 0x00000000; 371 | CORESIGHT_DWT.COMPARATOR[ch].DWT_COMP = 0; 372 | CORESIGHT_DWT.COMPARATOR[ch].DWT_MASK.MASK = 0; 373 | 374 | return 0; 375 | } 376 | 377 | int data_value_watch_start(int ch, void *addr1, void *addr2, void *compare_value, enum DWT_DATA_SIZE data_size) 378 | { 379 | if(DEBUG_SYSTEM.DEMCR.TRCENA == 0) 380 | { 381 | dwt_println("=========================================\r\n"); 382 | dwt_println("| !!!warning: DEBUG_SYSTEM is disable |\r\n"); 383 | dwt_println("| You may need to call dwt_init() first.|\r\n"); 384 | dwt_println("=========================================\r\n"); 385 | return -1; 386 | } 387 | if(compare_value == NULL) 388 | { 389 | dwt_println("[ERROR]: compare_value is illegal\r\n"); 390 | goto ___fail_exit; 391 | } 392 | 393 | CORESIGHT_DWT.COMPARATOR[ch].DWT_COMP = *((uint32_t*)compare_value); 394 | CORESIGHT_DWT.COMPARATOR[ch].DWT_FUNCTION.FUNCTION = WRITE_ONLY; 395 | CORESIGHT_DWT.COMPARATOR[ch].DWT_FUNCTION.DATAVSIZE = data_size; 396 | 397 | if((addr1)&&(addr2)) 398 | { 399 | if(!dwt_comparator[ch].can_double_value_watch) 400 | { 401 | dwt_println("[ERROR]: ch[%d] is unsupported\r\n",ch); 402 | CORESIGHT_DWT.COMPARATOR[ch].DWT_COMP = 0x00000000; 403 | CORESIGHT_DWT.COMPARATOR[ch].DWT_FUNCTION.all_in_one = 0x00000000; 404 | CORESIGHT_DWT.COMPARATOR[ch].DWT_MASK.MASK = 0; 405 | goto ___fail_exit; 406 | } 407 | for (int ch_1 = 0; ch_1 < CORESIGHT_DWT.DWT_CTRL.NUMCOMP; ch_1++) 408 | { 409 | if(CORESIGHT_DWT.COMPARATOR[ch_1].DWT_FUNCTION.FUNCTION == 0) 410 | { 411 | CORESIGHT_DWT.COMPARATOR[ch].DWT_FUNCTION.DATAVMATCH = 1; 412 | CORESIGHT_DWT.COMPARATOR[ch].DWT_FUNCTION.DATAVADDR0 = ch_1; 413 | CORESIGHT_DWT.COMPARATOR[ch_1].DWT_COMP = (uint32_t)addr1; 414 | CORESIGHT_DWT.COMPARATOR[ch_1].DWT_FUNCTION.FUNCTION = READ_WRITE; 415 | CORESIGHT_DWT.COMPARATOR[ch_1].DWT_FUNCTION.DATAVSIZE = data_size; 416 | for (int ch_2 = 0; ch_2 < CORESIGHT_DWT.DWT_CTRL.NUMCOMP; ch_2++) 417 | { 418 | if(CORESIGHT_DWT.COMPARATOR[ch_2].DWT_FUNCTION.FUNCTION == 0) 419 | { 420 | if(CORESIGHT_DWT.COMPARATOR[ch].DWT_FUNCTION.LNK1ENA) 421 | { 422 | CORESIGHT_DWT.COMPARATOR[ch].DWT_FUNCTION.DATAVADDR1 = ch_2; 423 | CORESIGHT_DWT.COMPARATOR[ch_2].DWT_COMP = (uint32_t)addr2; 424 | CORESIGHT_DWT.COMPARATOR[ch_2].DWT_FUNCTION.FUNCTION = READ_WRITE; 425 | CORESIGHT_DWT.COMPARATOR[ch_2].DWT_FUNCTION.DATAVSIZE = data_size; 426 | dwt_show_info(); 427 | return 0; 428 | } 429 | CORESIGHT_DWT.COMPARATOR[ch].DWT_COMP = 0x00000000; 430 | CORESIGHT_DWT.COMPARATOR[ch].DWT_FUNCTION.all_in_one = 0x00000000; 431 | CORESIGHT_DWT.COMPARATOR[ch].DWT_MASK.MASK = 0; 432 | 433 | CORESIGHT_DWT.COMPARATOR[ch_1].DWT_COMP = 0x00000000; 434 | CORESIGHT_DWT.COMPARATOR[ch_1].DWT_FUNCTION.all_in_one = 0x00000000; 435 | CORESIGHT_DWT.COMPARATOR[ch_1].DWT_MASK.MASK = 0; 436 | dwt_println("%s:%d\r\n",__FUNCTION__,__LINE__); 437 | goto ___fail_exit; 438 | } 439 | } 440 | CORESIGHT_DWT.COMPARATOR[ch].DWT_FUNCTION.all_in_one = 0x00000000; 441 | CORESIGHT_DWT.COMPARATOR[ch].DWT_COMP = 0x00000000; 442 | CORESIGHT_DWT.COMPARATOR[ch].DWT_MASK.MASK = 0; 443 | 444 | CORESIGHT_DWT.COMPARATOR[ch_1].DWT_FUNCTION.all_in_one = 0x00000000; 445 | CORESIGHT_DWT.COMPARATOR[ch_1].DWT_COMP = 0x00000000; 446 | CORESIGHT_DWT.COMPARATOR[ch_1].DWT_MASK.MASK = 0; 447 | dwt_println("%s:%d\r\n",__FUNCTION__,__LINE__); 448 | goto ___fail_exit; 449 | } 450 | } 451 | CORESIGHT_DWT.COMPARATOR[ch].DWT_COMP = 0x00000000; 452 | CORESIGHT_DWT.COMPARATOR[ch].DWT_FUNCTION.all_in_one = 0x00000000; 453 | CORESIGHT_DWT.COMPARATOR[ch].DWT_MASK.MASK = 0; 454 | dwt_println("%s:%d\r\n",__FUNCTION__,__LINE__); 455 | goto ___fail_exit; 456 | } 457 | else if ((addr1)||(addr2)) 458 | { 459 | if(!dwt_comparator[ch].can_double_value_watch) 460 | { 461 | dwt_println("[ERROR]: ch[%d] is unsupported\r\n",ch); 462 | CORESIGHT_DWT.COMPARATOR[ch].DWT_COMP = 0x00000000; 463 | CORESIGHT_DWT.COMPARATOR[ch].DWT_FUNCTION.all_in_one = 0x00000000; 464 | CORESIGHT_DWT.COMPARATOR[ch].DWT_MASK.MASK = 0; 465 | goto ___fail_exit; 466 | } 467 | for (int ch_1 = 0; ch_1 < CORESIGHT_DWT.DWT_CTRL.NUMCOMP; ch_1++) 468 | { 469 | if(CORESIGHT_DWT.COMPARATOR[ch_1].DWT_FUNCTION.FUNCTION == 0) 470 | { 471 | CORESIGHT_DWT.COMPARATOR[ch].DWT_FUNCTION.DATAVMATCH = 1; 472 | CORESIGHT_DWT.COMPARATOR[ch].DWT_FUNCTION.DATAVADDR0 = ch_1; 473 | CORESIGHT_DWT.COMPARATOR[ch_1].DWT_COMP = ((uint32_t)addr1)|((uint32_t)addr2); 474 | CORESIGHT_DWT.COMPARATOR[ch_1].DWT_FUNCTION.FUNCTION = READ_WRITE; 475 | CORESIGHT_DWT.COMPARATOR[ch_1].DWT_FUNCTION.DATAVSIZE = data_size; 476 | dwt_show_info(); 477 | return 0; 478 | } 479 | } 480 | CORESIGHT_DWT.COMPARATOR[ch].DWT_COMP = 0x00000000; 481 | CORESIGHT_DWT.COMPARATOR[ch].DWT_FUNCTION.all_in_one = 0x00000000; 482 | CORESIGHT_DWT.COMPARATOR[ch].DWT_MASK.MASK = 0; 483 | dwt_println("%s:%d\r\n",__FUNCTION__,__LINE__); 484 | goto ___fail_exit; 485 | } 486 | ___fail_exit: 487 | dwt_show_support(); 488 | return -1; 489 | } 490 | 491 | int data_value_watch_stop(int ch) 492 | { 493 | int ch0,ch1; 494 | ch0 = CORESIGHT_DWT.COMPARATOR[ch].DWT_FUNCTION.DATAVADDR0; 495 | ch1 = CORESIGHT_DWT.COMPARATOR[ch].DWT_FUNCTION.DATAVADDR1; 496 | 497 | if(CORESIGHT_DWT.COMPARATOR[ch].DWT_FUNCTION.DATAVMATCH) 498 | { 499 | CORESIGHT_DWT.COMPARATOR[ch0].DWT_FUNCTION.all_in_one = 0x00000000; 500 | CORESIGHT_DWT.COMPARATOR[ch0].DWT_COMP = 0; 501 | CORESIGHT_DWT.COMPARATOR[ch0].DWT_MASK.MASK = 0; 502 | if(CORESIGHT_DWT.COMPARATOR[ch].DWT_FUNCTION.LNK1ENA) 503 | { 504 | CORESIGHT_DWT.COMPARATOR[ch1].DWT_FUNCTION.all_in_one = 0x00000000; 505 | CORESIGHT_DWT.COMPARATOR[ch1].DWT_COMP = 0; 506 | CORESIGHT_DWT.COMPARATOR[ch1].DWT_MASK.MASK = 0; 507 | } 508 | CORESIGHT_DWT.COMPARATOR[ch].DWT_FUNCTION.all_in_one = 0x00000000; 509 | CORESIGHT_DWT.COMPARATOR[ch].DWT_COMP = 0; 510 | CORESIGHT_DWT.COMPARATOR[ch].DWT_MASK.MASK = 0; 511 | } 512 | } 513 | 514 | -------------------------------------------------------------------------------- /src/armv7m_dwt.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the armv7m_DWT Library. 3 | * 4 | * Copyright (c) 2021-2022, BalanceTWK (balancetwk@yeah.net) 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining 7 | * a copy of this software and associated documentation files (the 8 | * 'Software'), to deal in the Software without restriction, including 9 | * without limitation the rights to use, copy, modify, merge, publish, 10 | * distribute, sublicense, and/or sell copies of the Software, and to 11 | * permit persons to whom the Software is furnished to do so, subject to 12 | * the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be 15 | * included in all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, 18 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 21 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 22 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 23 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | * 25 | * Function: Initialize function and other general function. 26 | * Created on: 2022-06-16 27 | */ 28 | 29 | #ifndef __ARMV7M_DWT_H__ 30 | #define __ARMV7M_DWT_H__ 31 | 32 | #include 33 | 34 | enum DWT_MODE 35 | { 36 | READ_ONLY = 5, 37 | WRITE_ONLY, 38 | READ_WRITE, 39 | MAX_TYPE 40 | }; 41 | 42 | enum DWT_DATA_SIZE 43 | { 44 | SIZE_BYTE = 0, 45 | SIZE_HALF_WORD = 1, 46 | SIZE_WORD = 2, 47 | MAX_SIZE 48 | }; 49 | 50 | int dwt_init(void); 51 | int dwt_deinit(void); 52 | int data_address_watch_start(int ch, void *addr, uint32_t addr_mask, enum DWT_MODE mode); 53 | int data_address_watch_stop(int ch); 54 | int data_value_watch_start(int ch, void *addr1, void *addr2, void *compare_value, enum DWT_DATA_SIZE data_size); 55 | int data_value_watch_stop(int ch); 56 | 57 | int dwt_show_support(void); 58 | int dwt_show_info(void); 59 | 60 | #endif /* __ARMV7M_DWT_H__ */ 61 | --------------------------------------------------------------------------------