├── .gitignore ├── README.md ├── bsp ├── beaglebone │ ├── applications │ │ └── application.c │ ├── drivers │ │ └── serial.c │ ├── rtconfig.h │ └── rtconfig.py └── stm32f40x │ ├── applications │ └── application.c │ ├── drivers │ ├── board.h │ ├── stm32f4xx_it.c │ └── usart.c │ ├── rtconfig.h │ ├── rtconfig.py │ └── stm32_rom.ld ├── components └── gdb │ ├── SConscript │ ├── gdb_stub.c │ ├── gdb_stub.h │ ├── hal_stub.c │ ├── libcpu │ ├── arm │ │ ├── arch_gdb.h │ │ └── arm_stub.c │ └── cortexm │ │ ├── arch_gdb.h │ │ ├── cortexm_stub.c │ │ ├── gdb_gcc.S │ │ └── gdb_handler.c │ └── readme-zh.txt ├── libcpu └── arm │ └── am335x │ ├── start_gcc.S │ └── trap.c └── readme-zh.txt /.gitignore: -------------------------------------------------------------------------------- 1 | # Object files 2 | *.o 3 | *.ko 4 | 5 | # Libraries 6 | *.lib 7 | *.a 8 | 9 | # Shared objects (inc. Windows DLLs) 10 | *.dll 11 | *.so 12 | *.so.* 13 | *.dylib 14 | 15 | # Executables 16 | *.exe 17 | *.out 18 | *.app 19 | 20 | 21 | *.pyc 22 | *.bin 23 | *.elf 24 | *.h~ 25 | *.c~ 26 | *.txt~ 27 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # GDB stub for RT-Thread # 2 | 3 | GDB Stub 是 GDB 在进行远程调试的时候,在目标机上运行的一套代码。其功能描述可以参 考 https://sourceware.org/gdb/onlinedocs/gdb/Remote-Stub.html 。简单的说来,本 项目就是在 RT-Thread 中实现类似于 KGDB 的功能,用来在没有仿真器(JTAG)的情况下调 试RT-Thread 内核和应用程序。 4 | 5 | RT-Thread is an open source real-time operating system for embedded devices from China. RT-Thread RTOS is a scalable real-time operating system: a tiny kernel for ARM Cortex-M0, Cortex-M3/4, or a full feature system in ARM Cortex-A8, ARM Cortex-A9 DualCore etc. 6 | 7 | 8 | ## Usage ## 9 | 10 | 1. use it in RT-Thread 11 | 12 | you have to copy the code to the RTT-ROOT folder. 13 | you can find demo from the bsp of beaglebone. 14 | 15 | ## Help ## 16 | 17 | more in readme-zh.txt 18 | 19 | -------------------------------------------------------------------------------- /bsp/beaglebone/applications/application.c: -------------------------------------------------------------------------------- 1 | /* 2 | * File : application.c 3 | * This file is part of RT-Thread RTOS 4 | * COPYRIGHT (C) 2012, RT-Thread Development Team 5 | * 6 | * The license and distribution terms for this file may be 7 | * found in the file LICENSE in this distribution or at 8 | * http://www.rt-thread.org/license/LICENSE 9 | * 10 | * Change Logs: 11 | * Date Author Notes 12 | * 2012-11-20 Bernard the first version 13 | */ 14 | 15 | #include 16 | #include 17 | #include 18 | 19 | #ifdef RT_USING_GDB 20 | #include 21 | #endif 22 | 23 | int rt_application_init() 24 | { 25 | /* do component initialization */ 26 | rt_components_init(); 27 | #ifdef RT_USING_NEWLIB 28 | libc_system_init(RT_CONSOLE_DEVICE_NAME); 29 | #endif 30 | #ifdef RT_USING_GDB 31 | gdb_set_device("uart4"); 32 | gdb_start(); 33 | #endif 34 | 35 | return 0; 36 | } 37 | -------------------------------------------------------------------------------- /bsp/beaglebone/drivers/serial.c: -------------------------------------------------------------------------------- 1 | /* 2 | * File : serial.c 3 | * This file is part of RT-Thread RTOS 4 | * COPYRIGHT (C) 2013, RT-Thread Development Team 5 | * 6 | * The license and distribution terms for this file may be 7 | * found in the file LICENSE in this distribution or at 8 | * http://www.rt-thread.org/license/LICENSE 9 | * 10 | * Change Logs: 11 | * Date Author Notes 12 | * 2013-07-06 Bernard the first version 13 | * 2014-01-11 RTsien support UART0 to UART5 straightly 14 | */ 15 | 16 | #include 17 | #include 18 | #include 19 | 20 | #include 21 | #include 22 | #include "serial.h" 23 | #include "serial_reg.h" 24 | 25 | struct am33xx_uart 26 | { 27 | unsigned long base; 28 | int irq; 29 | }; 30 | 31 | static void am33xx_uart_isr(int irqno, void* param) 32 | { 33 | rt_uint32_t iir; 34 | struct am33xx_uart* uart; 35 | struct rt_serial_device *serial; 36 | 37 | serial = (struct rt_serial_device*)param; 38 | uart = (struct am33xx_uart *)serial->parent.user_data; 39 | 40 | iir = UART_IIR_REG(uart->base); 41 | 42 | if ((iir & (0x02 << 1)) || (iir & (0x6 << 1))) 43 | { 44 | rt_hw_serial_isr(serial, RT_SERIAL_EVENT_RX_IND); 45 | } 46 | } 47 | 48 | #define NOT_IMPLEMENTED() RT_ASSERT(0) 49 | 50 | static rt_err_t am33xx_configure(struct rt_serial_device *serial, struct serial_configure *cfg) 51 | { 52 | struct am33xx_uart* uart; 53 | unsigned long base; 54 | 55 | RT_ASSERT(serial != RT_NULL); 56 | uart = (struct am33xx_uart *)serial->parent.user_data; 57 | RT_ASSERT(uart); 58 | base = uart->base; 59 | 60 | #define __LCR UART_LCR_REG(base) 61 | 62 | if (cfg->data_bits == DATA_BITS_8) 63 | __LCR |= 3; 64 | else 65 | NOT_IMPLEMENTED(); 66 | 67 | if (cfg->stop_bits == STOP_BITS_1) 68 | __LCR &= ~(1<<2); 69 | else 70 | __LCR |= (1<<2); 71 | 72 | if (cfg->parity == PARITY_NONE) 73 | __LCR &= ~(1<<3); 74 | else 75 | __LCR |= (1<<3); 76 | 77 | __LCR |= (1<<7); 78 | if (cfg->baud_rate == BAUD_RATE_115200) 79 | { 80 | UART_DLL_REG(base) = 26; 81 | UART_DLH_REG(base) = 0; 82 | } 83 | else if (cfg->baud_rate == BAUD_RATE_9600) 84 | { 85 | UART_DLL_REG(base) = 0x38; 86 | UART_DLH_REG(base) = 1; 87 | } 88 | else 89 | { 90 | NOT_IMPLEMENTED(); 91 | } 92 | __LCR &= ~(1<<7); 93 | 94 | UART_MDR1_REG(base) = 0; 95 | UART_MDR2_REG(base) = 0; 96 | 97 | #undef __LCR 98 | return RT_EOK; 99 | } 100 | 101 | static rt_err_t am33xx_control(struct rt_serial_device *serial, int cmd, void *arg) 102 | { 103 | struct am33xx_uart* uart; 104 | 105 | RT_ASSERT(serial != RT_NULL); 106 | uart = (struct am33xx_uart *)serial->parent.user_data; 107 | 108 | switch (cmd) 109 | { 110 | case RT_DEVICE_CTRL_CLR_INT: 111 | /* disable rx irq */ 112 | rt_hw_interrupt_mask(uart->irq); 113 | break; 114 | case RT_DEVICE_CTRL_SET_INT: 115 | /* enable rx irq */ 116 | rt_hw_interrupt_umask(uart->irq); 117 | break; 118 | } 119 | 120 | return RT_EOK; 121 | } 122 | 123 | int printkc(char c) 124 | { 125 | int base = 0xf9e09000; 126 | 127 | while (!(UART_LSR_REG(base) & 0x20)); 128 | UART_THR_REG(base) = c; 129 | 130 | return 1; 131 | } 132 | 133 | static int am33xx_putc(struct rt_serial_device *serial, char c) 134 | { 135 | struct am33xx_uart* uart; 136 | 137 | RT_ASSERT(serial != RT_NULL); 138 | uart = (struct am33xx_uart *)serial->parent.user_data; 139 | 140 | while (!(UART_LSR_REG(uart->base) & 0x20)); 141 | UART_THR_REG(uart->base) = c; 142 | 143 | return 1; 144 | } 145 | 146 | static int am33xx_getc(struct rt_serial_device *serial) 147 | { 148 | int ch; 149 | struct am33xx_uart* uart; 150 | 151 | RT_ASSERT(serial != RT_NULL); 152 | uart = (struct am33xx_uart *)serial->parent.user_data; 153 | 154 | ch = -1; 155 | if (UART_LSR_REG(uart->base) & 0x01) 156 | { 157 | ch = UART_RHR_REG(uart->base) & 0xff; 158 | } 159 | 160 | return ch; 161 | } 162 | 163 | static const struct rt_uart_ops am33xx_uart_ops = 164 | { 165 | am33xx_configure, 166 | am33xx_control, 167 | am33xx_putc, 168 | am33xx_getc, 169 | }; 170 | 171 | /* UART device driver structure */ 172 | #ifdef RT_USING_UART0 173 | struct am33xx_uart uart0 = 174 | { 175 | UART0_BASE, 176 | UART0_INT, 177 | }; 178 | struct rt_serial_device serial0; 179 | #endif 180 | 181 | #ifdef RT_USING_UART1 182 | struct am33xx_uart uart1 = 183 | { 184 | UART1_BASE, 185 | UART1_INT, 186 | }; 187 | struct rt_serial_device serial1; 188 | #endif 189 | 190 | #ifdef RT_USING_UART2 191 | struct am33xx_uart uart2 = 192 | { 193 | UART2_BASE, 194 | UART2_INT, 195 | }; 196 | struct rt_serial_device serial2; 197 | #endif 198 | 199 | #ifdef RT_USING_UART3 200 | struct am33xx_uart uart3 = 201 | { 202 | UART3_BASE, 203 | UART3_INT, 204 | }; 205 | struct rt_serial_device serial3; 206 | #endif 207 | 208 | #ifdef RT_USING_UART4 209 | struct am33xx_uart uart4 = 210 | { 211 | UART4_BASE, 212 | UART4_INT, 213 | }; 214 | struct rt_serial_device serial4; 215 | #endif 216 | 217 | #ifdef RT_USING_UART5 218 | struct am33xx_uart uart5 = 219 | { 220 | UART5_BASE, 221 | UART5_INT, 222 | }; 223 | struct rt_serial_device serial5; 224 | #endif 225 | 226 | #define write_reg(base, value) *(int*)(base) = value 227 | #define read_reg(base) *(int*)(base) 228 | 229 | #define PRM_PER_INTRANSLATION (1 << 20) 230 | #define PRM_PER_POWSTATEOFF (0) 231 | #define PRM_PER_PERMEMSTATEOFF (0) 232 | 233 | static void poweron_per_domain(void) 234 | { 235 | unsigned long prcm_base; 236 | unsigned long prm_state; 237 | 238 | prcm_base = AM33XX_PRCM_REGS; 239 | 240 | /* wait for ongoing translations */ 241 | for (prm_state = PRM_PER_PWRSTST_REG(prcm_base); 242 | prm_state & PRM_PER_INTRANSLATION; 243 | prm_state = PRM_PER_PWRSTST_REG(prcm_base)) 244 | ; 245 | 246 | /* check power state */ 247 | if ((prm_state & 0x03) == PRM_PER_POWSTATEOFF) 248 | /* power on PER domain */ 249 | PRM_PER_PWRSTCTRL_REG(prcm_base) |= 0x3; 250 | 251 | /* check per mem state */ 252 | if ((prm_state & 0x03) == PRM_PER_PERMEMSTATEOFF) 253 | /* power on PER domain */ 254 | PRM_PER_PWRSTCTRL_REG(prcm_base) |= 0x3 << 25; 255 | 256 | while (PRM_PER_PWRSTST_REG(prcm_base) & PRM_PER_INTRANSLATION) 257 | ; 258 | } 259 | 260 | static void start_uart_clk(void) 261 | { 262 | unsigned long prcm_base; 263 | 264 | prcm_base = AM33XX_PRCM_REGS; 265 | 266 | /* software forced wakeup */ 267 | CM_PER_L4LS_CLKSTCTRL_REG(prcm_base) |= 0x2; 268 | 269 | /* Waiting for the L4LS clock */ 270 | while (!(CM_PER_L4LS_CLKSTCTRL_REG(prcm_base) & (1<<8))) 271 | ; 272 | 273 | /* enable uart1 */ 274 | #ifdef RT_USING_UART1 275 | CM_PER_UART1_CLKCTRL_REG(prcm_base) |= 0x2; 276 | /* wait for uart1 clk */ 277 | while ((CM_PER_UART1_CLKCTRL_REG(prcm_base) & (0x3<<16)) != 0) 278 | ; 279 | #endif 280 | 281 | #ifdef RT_USING_UART2 282 | CM_PER_UART2_CLKCTRL_REG(prcm_base) |= 0x2; 283 | /* wait for uart2 clk */ 284 | while ((CM_PER_UART2_CLKCTRL_REG(prcm_base) & (0x3<<16)) != 0) 285 | ; 286 | #endif 287 | 288 | #ifdef RT_USING_UART3 289 | CM_PER_UART3_CLKCTRL_REG(prcm_base) |= 0x2; 290 | /* wait for uart3 clk */ 291 | while ((CM_PER_UART3_CLKCTRL_REG(prcm_base) & (0x3<<16)) != 0) 292 | ; 293 | #endif 294 | 295 | #ifdef RT_USING_UART4 296 | CM_PER_UART4_CLKCTRL_REG(prcm_base) |= 0x2; 297 | /* wait for uart4 clk */ 298 | while ((CM_PER_UART4_CLKCTRL_REG(prcm_base) & (0x3<<16)) != 0) 299 | ; 300 | #endif 301 | 302 | #ifdef RT_USING_UART5 303 | CM_PER_UART5_CLKCTRL_REG(prcm_base) |= 0x2; 304 | /* wait for uart5 clk */ 305 | while ((CM_PER_UART5_CLKCTRL_REG(prcm_base) & (0x3<<16)) != 0) 306 | ; 307 | #endif 308 | 309 | /* Waiting for the L4LS UART clock */ 310 | while (!(CM_PER_L4LS_CLKSTCTRL_REG(prcm_base) & (1<<10))) 311 | ; 312 | } 313 | 314 | static void config_pinmux(void) 315 | { 316 | unsigned long ctlm_base; 317 | 318 | ctlm_base = AM33XX_CTLM_REGS; 319 | 320 | /* make sure the pin mux is OK for uart */ 321 | #ifdef RT_USING_UART1 322 | REG32(ctlm_base + 0x800 + 0x180) = 0x20; 323 | REG32(ctlm_base + 0x800 + 0x184) = 0x00; 324 | #endif 325 | 326 | #ifdef RT_USING_UART2 327 | REG32(ctlm_base + 0x800 + 0x150) = 0x20; 328 | REG32(ctlm_base + 0x800 + 0x154) = 0x00; 329 | #endif 330 | 331 | #ifdef RT_USING_UART3 332 | REG32(ctlm_base + 0x800 + 0x164) = 0x01; 333 | #endif 334 | 335 | #ifdef RT_USING_UART4 336 | REG32(ctlm_base + 0x800 + 0x070) = 0x26; 337 | REG32(ctlm_base + 0x800 + 0x074) = 0x06; 338 | #endif 339 | 340 | #ifdef RT_USING_UART5 341 | REG32(ctlm_base + 0x800 + 0x0C4) = 0x24; 342 | REG32(ctlm_base + 0x800 + 0x0C0) = 0x04; 343 | #endif 344 | } 345 | 346 | int rt_hw_serial_init(void) 347 | { 348 | struct serial_configure config; 349 | 350 | poweron_per_domain(); 351 | start_uart_clk(); 352 | config_pinmux(); 353 | 354 | #ifdef RT_USING_UART0 355 | config.baud_rate = BAUD_RATE_115200; 356 | config.bit_order = BIT_ORDER_LSB; 357 | config.data_bits = DATA_BITS_8; 358 | config.parity = PARITY_NONE; 359 | config.stop_bits = STOP_BITS_1; 360 | config.invert = NRZ_NORMAL; 361 | config.bufsz = RT_SERIAL_RB_BUFSZ; 362 | 363 | serial0.ops = &am33xx_uart_ops; 364 | serial0.config = config; 365 | /* enable RX interrupt */ 366 | UART_IER_REG(uart0.base) = 0x01; 367 | /* install ISR */ 368 | rt_hw_interrupt_install(uart0.irq, am33xx_uart_isr, &serial0, "uart0"); 369 | rt_hw_interrupt_control(uart0.irq, 0, 0); 370 | rt_hw_interrupt_mask(uart0.irq); 371 | /* register UART0 device */ 372 | rt_hw_serial_register(&serial0, "uart0", 373 | RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX, 374 | &uart0); 375 | #endif 376 | 377 | #ifdef RT_USING_UART1 378 | config.baud_rate = BAUD_RATE_115200; 379 | config.bit_order = BIT_ORDER_LSB; 380 | config.data_bits = DATA_BITS_8; 381 | config.parity = PARITY_NONE; 382 | config.stop_bits = STOP_BITS_1; 383 | config.invert = NRZ_NORMAL; 384 | config.bufsz = RT_SERIAL_RB_BUFSZ; 385 | 386 | serial1.ops = &am33xx_uart_ops; 387 | serial1.config = config; 388 | /* enable RX interrupt */ 389 | UART_IER_REG(uart1.base) = 0x01; 390 | /* install ISR */ 391 | rt_hw_interrupt_install(uart1.irq, am33xx_uart_isr, &serial1, "uart1"); 392 | rt_hw_interrupt_control(uart1.irq, 0, 0); 393 | rt_hw_interrupt_mask(uart1.irq); 394 | /* register UART0 device */ 395 | rt_hw_serial_register(&serial1, "uart1", 396 | RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX, 397 | &uart1); 398 | #endif 399 | 400 | #ifdef RT_USING_UART2 401 | config.baud_rate = BAUD_RATE_115200; 402 | config.bit_order = BIT_ORDER_LSB; 403 | config.data_bits = DATA_BITS_8; 404 | config.parity = PARITY_NONE; 405 | config.stop_bits = STOP_BITS_1; 406 | config.invert = NRZ_NORMAL; 407 | config.bufsz = RT_SERIAL_RB_BUFSZ; 408 | 409 | serial2.ops = &am33xx_uart_ops; 410 | serial2.config = config; 411 | /* enable RX interrupt */ 412 | UART_IER_REG(uart2.base) = 0x01; 413 | /* install ISR */ 414 | rt_hw_interrupt_install(uart2.irq, am33xx_uart_isr, &serial2, "uart2"); 415 | rt_hw_interrupt_control(uart2.irq, 0, 0); 416 | rt_hw_interrupt_mask(uart2.irq); 417 | /* register UART2 device */ 418 | rt_hw_serial_register(&serial2, "uart2", 419 | RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX, 420 | &uart2); 421 | #endif 422 | 423 | #ifdef RT_USING_UART3 424 | config.baud_rate = BAUD_RATE_115200; 425 | config.bit_order = BIT_ORDER_LSB; 426 | config.data_bits = DATA_BITS_8; 427 | config.parity = PARITY_NONE; 428 | config.stop_bits = STOP_BITS_1; 429 | config.invert = NRZ_NORMAL; 430 | config.bufsz = RT_SERIAL_RB_BUFSZ; 431 | 432 | serial3.ops = &am33xx_uart_ops; 433 | serial3.config = config; 434 | /* enable RX interrupt */ 435 | UART_IER_REG(uart3.base) = 0x01; 436 | /* install ISR */ 437 | rt_hw_interrupt_install(uart3.irq, am33xx_uart_isr, &serial3, "uart3"); 438 | rt_hw_interrupt_control(uart3.irq, 0, 0); 439 | rt_hw_interrupt_mask(uart3.irq); 440 | /* register UART3 device */ 441 | rt_hw_serial_register(&serial3, "uart3", 442 | RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX, 443 | &uart3); 444 | #endif 445 | 446 | #ifdef RT_USING_UART4 447 | config.baud_rate = BAUD_RATE_9600; 448 | config.bit_order = BIT_ORDER_LSB; 449 | config.data_bits = DATA_BITS_8; 450 | config.parity = PARITY_NONE; 451 | config.stop_bits = STOP_BITS_1; 452 | config.invert = NRZ_NORMAL; 453 | config.bufsz = RT_SERIAL_RB_BUFSZ; 454 | 455 | serial4.ops = &am33xx_uart_ops; 456 | serial4.config = config; 457 | /* enable RX interrupt */ 458 | UART_IER_REG(uart4.base) = 0x00; 459 | /* install ISR */ 460 | rt_hw_interrupt_install(uart4.irq, am33xx_uart_isr, &serial4, "uart4"); 461 | rt_hw_interrupt_control(uart4.irq, 0, 0); 462 | rt_hw_interrupt_mask(uart4.irq); 463 | /* register UART4 device */ 464 | rt_hw_serial_register(&serial4, "uart4", 465 | RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_STREAM, 466 | &uart4); 467 | #endif 468 | 469 | #ifdef RT_USING_UART5 470 | config.baud_rate = BAUD_RATE_115200; 471 | config.bit_order = BIT_ORDER_LSB; 472 | config.data_bits = DATA_BITS_8; 473 | config.parity = PARITY_NONE; 474 | config.stop_bits = STOP_BITS_1; 475 | config.invert = NRZ_NORMAL; 476 | config.bufsz = RT_SERIAL_RB_BUFSZ; 477 | 478 | serial5.ops = &am33xx_uart_ops; 479 | serial5.config = config; 480 | /* enable RX interrupt */ 481 | UART_IER_REG(uart5.base) = 0x01; 482 | /* install ISR */ 483 | rt_hw_interrupt_install(uart5.irq, am33xx_uart_isr, &serial5, "uart5"); 484 | rt_hw_interrupt_control(uart5.irq, 0, 0); 485 | rt_hw_interrupt_mask(uart5.irq); 486 | /* register UART4 device */ 487 | rt_hw_serial_register(&serial5, "uart5", 488 | RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX, 489 | &uart5); 490 | #endif 491 | 492 | return 0; 493 | } 494 | INIT_BOARD_EXPORT(rt_hw_serial_init); 495 | -------------------------------------------------------------------------------- /bsp/beaglebone/rtconfig.h: -------------------------------------------------------------------------------- 1 | /* RT-Thread config file */ 2 | #ifndef __RTTHREAD_CFG_H__ 3 | #define __RTTHREAD_CFG_H__ 4 | 5 | //
6 | //#define RT_USING_GDB 7 | //#define RT_GDB_DEBUG 8 | #define RT_GDB_ICACHE 9 | //
10 | 11 | // 12 | 13 | // 14 | #define RT_NAME_MAX 6 15 | // 16 | #define RT_ALIGN_SIZE 4 17 | // 18 | // 8 19 | // 32 20 | // 256 21 | // 22 | #define RT_THREAD_PRIORITY_MAX 32 23 | // 24 | #define RT_TICK_PER_SECOND 1000 25 | // 26 | #define IDLE_THREAD_STACK_SIZE 512 27 | //
28 | #define RT_DEBUG 29 | //#define RT_DEBUG_SCHEDULER 1 30 | // 31 | // #define RT_THREAD_DEBUG 32 | // 33 | //#define RT_USING_OVERFLOW_CHECK 34 | //
35 | 36 | // 37 | #define RT_USING_HOOK 38 | //
39 | // #define RT_USING_TIMER_SOFT 40 | // 41 | #define RT_TIMER_THREAD_PRIO 4 42 | // 43 | #define RT_TIMER_THREAD_STACK_SIZE 512 44 | // 45 | #define RT_TIMER_TICK_PER_SECOND 10 46 | //
47 | 48 | //
49 | // 50 | #define RT_USING_SEMAPHORE 51 | // 52 | #define RT_USING_MUTEX 53 | // 54 | #define RT_USING_EVENT 55 | // 56 | #define RT_USING_MAILBOX 57 | // 58 | #define RT_USING_MESSAGEQUEUE 59 | //
60 | 61 | //
62 | // 63 | #define RT_USING_MEMPOOL 64 | // 65 | // #define RT_USING_MEMHEAP 66 | // 67 | #define RT_USING_HEAP 68 | // 69 | // #define RT_USING_MEMHEAP_AS_HEAP 70 | // 71 | #define RT_USING_SMALL_MEM 72 | // 73 | // #define RT_USING_SLAB 74 | //
75 | 76 | //
77 | #define RT_USING_DEVICE 78 | // 79 | #define RT_USING_DEVICE_IPC 80 | // 81 | #define RT_USING_SERIAL 82 | // 83 | #define RT_USING_UART0 84 | // 85 | #define RT_USING_UART1 86 | // 87 | #define RT_USING_UART2 88 | // 89 | //#define RT_USING_UART3 90 | // 91 | #define RT_USING_UART4 92 | // 93 | #define RT_USING_UART5 94 | // 95 | #define RT_UART_RX_BUFFER_SIZE 64 96 | // 97 | #define RT_USING_INTERRUPT_INFO 98 | //
99 | 100 | //
101 | #define RT_USING_CONSOLE 102 | // 103 | #define RT_CONSOLEBUF_SIZE 128 104 | // 105 | #define RT_CONSOLE_DEVICE_NAME "uart0" 106 | //
107 | 108 | // 109 | #define RT_USING_COMPONENTS_INIT 110 | //
111 | #define RT_USING_FINSH 112 | // 113 | #define FINSH_USING_MSH 114 | // 115 | //#define FINSH_USING_MSH_DEFAULT 116 | // 117 | #define FINSH_USING_SYMTAB 118 | // 119 | #define FINSH_USING_DESCRIPTION 120 | // 121 | #define FINSH_THREAD_STACK_SIZE 4096 122 | //
123 | 124 | //
125 | // 126 | //#define RT_USING_NEWLIB 127 | // 128 | #define RT_USING_PTHREADS 129 | //
130 | 131 | //
132 | // #define RT_USING_DFS 133 | // 134 | // #define DFS_USING_WORKDIR 135 | // 136 | #define DFS_FILESYSTEMS_MAX 2 137 | // 138 | #define DFS_FD_MAX 4 139 | // 140 | #define RT_USING_DFS_ELMFAT 141 | // 142 | // 1 143 | // 2 144 | // 145 | #define RT_DFS_ELM_USE_LFN 1 146 | // 147 | #define RT_DFS_ELM_MAX_LFN 64 148 | // 149 | // #define RT_USING_DFS_YAFFS2 150 | // 151 | // #define RT_USING_DFS_UFFS 152 | // 153 | // #define RT_USING_DFS_DEVFS 154 | // 155 | // #define RT_USING_DFS_NFS 156 | // 157 | #define RT_NFS_HOST_EXPORT "192.168.1.5:/" 158 | //
159 | 160 | //
161 | 162 | #define __rt_ffs __builtin_ffs 163 | 164 | #endif 165 | 166 | -------------------------------------------------------------------------------- /bsp/beaglebone/rtconfig.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | # toolchains options 4 | ARCH='arm' 5 | CPU='am335x' 6 | CROSS_TOOL='gcc' 7 | 8 | if os.getenv('RTT_CC'): 9 | CROSS_TOOL = os.getenv('RTT_CC') 10 | 11 | if CROSS_TOOL == 'gcc': 12 | PLATFORM = 'gcc' 13 | EXEC_PATH = r'C:\Program Files (x86)\CodeSourcery\Sourcery_CodeBench_Lite_for_ARM_EABI\bin' 14 | elif CROSS_TOOL == 'keil': 15 | PLATFORM = 'armcc' 16 | EXEC_PATH = 'C:/Keil' 17 | elif CROSS_TOOL == 'iar': 18 | print '================ERROR============================' 19 | print 'Not support IAR yet!' 20 | print '=================================================' 21 | exit(0) 22 | 23 | if os.getenv('RTT_EXEC_PATH'): 24 | EXEC_PATH = os.getenv('RTT_EXEC_PATH') 25 | 26 | BUILD = 'debug' 27 | 28 | if PLATFORM == 'gcc': 29 | # toolchains 30 | PREFIX = 'arm-none-eabi-' 31 | CC = PREFIX + 'gcc' 32 | CXX = PREFIX + 'g++' 33 | AS = PREFIX + 'gcc' 34 | AR = PREFIX + 'ar' 35 | LINK = PREFIX + 'gcc' 36 | TARGET_EXT = 'elf' 37 | SIZE = PREFIX + 'size' 38 | OBJDUMP = PREFIX + 'objdump' 39 | OBJCPY = PREFIX + 'objcopy' 40 | 41 | DEVICE = ' -Wall -march=armv7-a -mtune=cortex-a8'+\ 42 | ' -ftree-vectorize -ffast-math -mfpu=vfpv3-d16 -mfloat-abi=softfp' 43 | #DEVICE = ' ' 44 | CFLAGS = DEVICE 45 | AFLAGS = ' -c' + DEVICE + ' -x assembler-with-cpp -D__ASSEMBLY__' 46 | LFLAGS = DEVICE + ' -Wl,--gc-sections,-Map=rtthread-beaglebone.map,-cref,-u,Reset_Handler -T beaglebone_ram.lds' 47 | 48 | CPATH = '' 49 | LPATH = '' 50 | 51 | if BUILD == 'debug': 52 | CFLAGS += ' -O0 -gdwarf-2 -Wall' 53 | AFLAGS += ' -gdwarf-2' 54 | else: 55 | CFLAGS += ' -O2 -Wall' 56 | 57 | POST_ACTION = OBJCPY + ' -O binary $TARGET rtthread.bin\n' +\ 58 | SIZE + ' $TARGET \n' 59 | 60 | elif PLATFORM == 'armcc': 61 | # toolchains 62 | CC = 'armcc' 63 | CXX = 'armcc' 64 | AS = 'armasm' 65 | AR = 'armar' 66 | LINK = 'armlink' 67 | TARGET_EXT = 'axf' 68 | 69 | DEVICE = ' --device DARMP' 70 | CFLAGS = DEVICE + ' --apcs=interwork' 71 | AFLAGS = DEVICE 72 | LFLAGS = DEVICE + ' --info sizes --info totals --info unused --info veneers --list rtthread-beaglebone.map --scatter beaglebone_ram.sct' 73 | 74 | CFLAGS += ' -I' + EXEC_PATH + '/ARM/RV31/INC' 75 | LFLAGS += ' --libpath ' + EXEC_PATH + '/ARM/RV31/LIB' 76 | 77 | EXEC_PATH += '/arm/bin40/' 78 | 79 | if BUILD == 'debug': 80 | CFLAGS += ' -g -O0' 81 | AFLAGS += ' -g' 82 | else: 83 | CFLAGS += ' -O2' 84 | 85 | POST_ACTION = 'fromelf --bin $TARGET --output rtthread.bin \nfromelf -z $TARGET' 86 | 87 | elif PLATFORM == 'iar': 88 | # toolchains 89 | CC = 'iccarm' 90 | AS = 'iasmarm' 91 | AR = 'iarchive' 92 | LINK = 'ilinkarm' 93 | TARGET_EXT = 'out' 94 | 95 | DEVICE = ' --cpu DARMP' 96 | 97 | CFLAGS = '' 98 | AFLAGS = '' 99 | LFLAGS = ' --config beaglebone_ram.icf' 100 | 101 | EXEC_PATH += '/arm/bin/' 102 | RT_USING_MINILIBC = False 103 | POST_ACTION = '' 104 | -------------------------------------------------------------------------------- /bsp/stm32f40x/applications/application.c: -------------------------------------------------------------------------------- 1 | /* 2 | * File : application.c 3 | * This file is part of RT-Thread RTOS 4 | * COPYRIGHT (C) 2006, RT-Thread Development Team 5 | * 6 | * The license and distribution terms for this file may be 7 | * found in the file LICENSE in this distribution or at 8 | * http://www.rt-thread.org/license/LICENSE 9 | * 10 | * Change Logs: 11 | * Date Author Notes 12 | * 2009-01-05 Bernard the first version 13 | * 2014-04-27 Bernard make code cleanup. 14 | */ 15 | 16 | #include 17 | #include 18 | 19 | #ifdef RT_USING_LWIP 20 | #include 21 | #include 22 | #include 23 | #include "stm32_eth.h" 24 | #endif 25 | 26 | #ifdef RT_USING_GDB 27 | #include 28 | #endif 29 | 30 | void rt_init_thread_entry(void* parameter) 31 | { 32 | /* GDB STUB */ 33 | #ifdef RT_USING_GDB 34 | gdb_set_device("uart6"); 35 | gdb_start(); 36 | #endif 37 | 38 | /* LwIP Initialization */ 39 | #ifdef RT_USING_LWIP 40 | { 41 | extern void lwip_sys_init(void); 42 | 43 | /* register ethernetif device */ 44 | eth_system_device_init(); 45 | 46 | rt_hw_stm32_eth_init(); 47 | 48 | /* init lwip system */ 49 | lwip_sys_init(); 50 | rt_kprintf("TCP/IP initialized!\n"); 51 | } 52 | #endif 53 | } 54 | 55 | int rt_application_init() 56 | { 57 | rt_thread_t tid; 58 | 59 | tid = rt_thread_create("init", 60 | rt_init_thread_entry, RT_NULL, 61 | 2048, RT_THREAD_PRIORITY_MAX/3, 20); 62 | 63 | if (tid != RT_NULL) 64 | rt_thread_startup(tid); 65 | 66 | return 0; 67 | } 68 | 69 | /*@}*/ 70 | -------------------------------------------------------------------------------- /bsp/stm32f40x/drivers/board.h: -------------------------------------------------------------------------------- 1 | /* 2 | * File : board.h 3 | * This file is part of RT-Thread RTOS 4 | * COPYRIGHT (C) 2009, RT-Thread Development Team 5 | * 6 | * The license and distribution terms for this file may be 7 | * found in the file LICENSE in this distribution or at 8 | * http://www.rt-thread.org/license/LICENSE 9 | * 10 | * Change Logs: 11 | * Date Author Notes 12 | * 2009-09-22 Bernard add board.h to this bsp 13 | */ 14 | 15 | // <<< Use Configuration Wizard in Context Menu >>> 16 | #ifndef __BOARD_H__ 17 | #define __BOARD_H__ 18 | 19 | #include 20 | 21 | /* board configuration */ 22 | // SDCard Driver <1=>SDIO sdcard <0=>SPI MMC card 23 | // Default: 1 24 | #define STM32_USE_SDIO 0 25 | 26 | /* whether use board external SRAM memory */ 27 | // Use external SRAM memory on the board 28 | // Enable External SRAM memory 29 | #define STM32_EXT_SRAM 0 30 | // Begin Address of External SRAM 31 | // Default: 0x68000000 32 | #define STM32_EXT_SRAM_BEGIN 0x68000000 /* the begining address of external SRAM */ 33 | // End Address of External SRAM 34 | // Default: 0x68080000 35 | #define STM32_EXT_SRAM_END 0x68080000 /* the end address of external SRAM */ 36 | // 37 | 38 | // Internal SRAM memory size[Kbytes] <8-64> 39 | // Default: 64 40 | #define STM32_SRAM_SIZE 128 41 | #define STM32_SRAM_END (0x20000000 + STM32_SRAM_SIZE * 1024) 42 | 43 | //#define RT_USING_UART1 44 | #define RT_USING_UART2 45 | //#define RT_USING_UART3 46 | #define RT_USING_UART6 47 | 48 | // Console on USART: <0=> no console <1=>USART 1 <2=>USART 2 <3=> USART 3 49 | // Default: 1 50 | #define STM32_CONSOLE_USART 2 51 | 52 | void rt_hw_board_init(void); 53 | 54 | #if STM32_CONSOLE_USART == 0 55 | #define CONSOLE_DEVICE "no" 56 | #elif STM32_CONSOLE_USART == 1 57 | #define CONSOLE_DEVICE "uart1" 58 | #elif STM32_CONSOLE_USART == 2 59 | #define CONSOLE_DEVICE "uart2" 60 | #elif STM32_CONSOLE_USART == 3 61 | #define CONSOLE_DEVICE "uart3" 62 | #endif 63 | 64 | #define FINSH_DEVICE_NAME CONSOLE_DEVICE 65 | 66 | void rt_hw_usart_init(void); 67 | 68 | /* SD Card init function */ 69 | void rt_hw_msd_init(void); 70 | 71 | #endif 72 | 73 | // <<< Use Configuration Wizard in Context Menu >>> 74 | -------------------------------------------------------------------------------- /bsp/stm32f40x/drivers/stm32f4xx_it.c: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * @file IO_Toggle/stm32f4xx_it.c 4 | * @author MCD Application Team 5 | * @version V1.0.0 6 | * @date 19-September-2011 7 | * @brief Main Interrupt Service Routines. 8 | * This file provides template for all exceptions handler and 9 | * peripherals interrupt service routine. 10 | ****************************************************************************** 11 | * @attention 12 | * 13 | * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS 14 | * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE 15 | * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY 16 | * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING 17 | * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE 18 | * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. 19 | * 20 | *

© COPYRIGHT 2011 STMicroelectronics

21 | ****************************************************************************** 22 | */ 23 | 24 | /* Includes ------------------------------------------------------------------*/ 25 | #include "stm32f4xx.h" 26 | #include 27 | #include "board.h" 28 | 29 | /** @addtogroup STM32F4_Discovery_Peripheral_Examples 30 | * @{ 31 | */ 32 | 33 | /** @addtogroup IO_Toggle 34 | * @{ 35 | */ 36 | 37 | /* Private typedef -----------------------------------------------------------*/ 38 | /* Private define ------------------------------------------------------------*/ 39 | /* Private macro -------------------------------------------------------------*/ 40 | /* Private variables ---------------------------------------------------------*/ 41 | /* Private function prototypes -----------------------------------------------*/ 42 | /* Private functions ---------------------------------------------------------*/ 43 | 44 | /******************************************************************************/ 45 | /* Cortex-M4 Processor Exceptions Handlers */ 46 | /******************************************************************************/ 47 | 48 | /** 49 | * @brief This function handles NMI exception. 50 | * @param None 51 | * @retval None 52 | */ 53 | void NMI_Handler(void) 54 | { 55 | } 56 | 57 | /** 58 | * @brief This function handles Hard Fault exception. 59 | * @param None 60 | * @retval None 61 | */ 62 | //void HardFault_Handler(void) 63 | //{ 64 | // // definition in libcpu/arm/cortex-m4/context_*.S 65 | //} 66 | 67 | /** 68 | * @brief This function handles Memory Manage exception. 69 | * @param None 70 | * @retval None 71 | */ 72 | void MemManage_Handler(void) 73 | { 74 | /* Go to infinite loop when Memory Manage exception occurs */ 75 | while (1) 76 | { 77 | } 78 | } 79 | 80 | /** 81 | * @brief This function handles Bus Fault exception. 82 | * @param None 83 | * @retval None 84 | */ 85 | void BusFault_Handler(void) 86 | { 87 | /* Go to infinite loop when Bus Fault exception occurs */ 88 | while (1) 89 | { 90 | } 91 | } 92 | 93 | /** 94 | * @brief This function handles Usage Fault exception. 95 | * @param None 96 | * @retval None 97 | */ 98 | void UsageFault_Handler(void) 99 | { 100 | /* Go to infinite loop when Usage Fault exception occurs */ 101 | while (1) 102 | { 103 | } 104 | } 105 | 106 | /** 107 | * @brief This function handles SVCall exception. 108 | * @param None 109 | * @retval None 110 | */ 111 | void SVC_Handler(void) 112 | { 113 | } 114 | 115 | /** 116 | * @brief This function handles Debug Monitor exception. 117 | * @param None 118 | * @retval None 119 | */ 120 | //void DebugMon_Handler(void) 121 | //{ 122 | // defined in gdb/libcpu/cortexm/gdb_gcc.S 123 | //} 124 | 125 | /** 126 | * @brief This function handles PendSVC exception. 127 | * @param None 128 | * @retval None 129 | */ 130 | //void PendSV_Handler(void) 131 | //{ 132 | // // defined in libcpu/arm/cortex-m4/context_*.S 133 | //} 134 | 135 | /** 136 | * @brief This function handles SysTick Handler. 137 | * @param None 138 | * @retval None 139 | */ 140 | //void SysTick_Handler(void) 141 | //{ 142 | // // defined in boarc.c 143 | //} 144 | 145 | /******************************************************************************/ 146 | /* STM32F4xx Peripherals Interrupt Handlers */ 147 | /* Add here the Interrupt Handler for the used peripheral(s) (PPP), for the */ 148 | /* available peripheral interrupt handler's name please refer to the startup */ 149 | /* file (startup_stm32f4xx.s). */ 150 | /******************************************************************************/ 151 | 152 | /** 153 | * @brief This function handles PPP interrupt request. 154 | * @param None 155 | * @retval None 156 | */ 157 | /*void PPP_IRQHandler(void) 158 | { 159 | }*/ 160 | 161 | void USART1_IRQHandler(void) 162 | { 163 | #ifdef RT_USING_UART1 164 | extern struct rt_device uart1_device; 165 | extern void rt_hw_serial_isr(struct rt_device *device); 166 | 167 | /* enter interrupt */ 168 | rt_interrupt_enter(); 169 | 170 | rt_hw_serial_isr(&uart1_device); 171 | 172 | /* leave interrupt */ 173 | rt_interrupt_leave(); 174 | #endif 175 | } 176 | 177 | void USART2_IRQHandler(void) 178 | { 179 | #ifdef RT_USING_UART2 180 | extern struct rt_device uart2_device; 181 | extern void rt_hw_serial_isr(struct rt_device *device); 182 | 183 | /* enter interrupt */ 184 | rt_interrupt_enter(); 185 | 186 | rt_hw_serial_isr(&uart2_device); 187 | 188 | /* leave interrupt */ 189 | rt_interrupt_leave(); 190 | #endif 191 | } 192 | 193 | void USART3_IRQHandler(void) 194 | { 195 | #ifdef RT_USING_UART3 196 | extern struct rt_device uart3_device; 197 | extern void rt_hw_serial_isr(struct rt_device *device); 198 | 199 | /* enter interrupt */ 200 | rt_interrupt_enter(); 201 | 202 | rt_hw_serial_isr(&uart3_device); 203 | 204 | /* leave interrupt */ 205 | rt_interrupt_leave(); 206 | #endif 207 | } 208 | 209 | /** 210 | * @} 211 | */ 212 | 213 | /** 214 | * @} 215 | */ 216 | 217 | /******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/ 218 | -------------------------------------------------------------------------------- /bsp/stm32f40x/drivers/usart.c: -------------------------------------------------------------------------------- 1 | /* 2 | * File : usart.c 3 | * This file is part of RT-Thread RTOS 4 | * COPYRIGHT (C) 2009, RT-Thread Development Team 5 | * 6 | * The license and distribution terms for this file may be 7 | * found in the file LICENSE in this distribution or at 8 | * http://www.rt-thread.org/license/LICENSE 9 | * 10 | * Change Logs: 11 | * Date Author Notes 12 | * 2009-01-05 Bernard the first version 13 | * 2010-03-29 Bernard remove interrupt Tx and DMA Rx mode 14 | * 2012-02-08 aozima update for F4. 15 | */ 16 | 17 | #include "stm32f4xx.h" 18 | #include "usart.h" 19 | #include "board.h" 20 | #include 21 | 22 | /* 23 | * Use UART1 as console output and finsh input 24 | * interrupt Rx and poll Tx (stream mode) 25 | * 26 | * Use UART2 with interrupt Rx and poll Tx 27 | * Use UART3 with DMA Tx and interrupt Rx -- DMA channel 2 28 | * 29 | * USART DMA setting on STM32 30 | * USART1 Tx --> DMA Channel 4 31 | * USART1 Rx --> DMA Channel 5 32 | * USART2 Tx --> DMA Channel 7 33 | * USART2 Rx --> DMA Channel 6 34 | * USART3 Tx --> DMA Channel 2 35 | * USART3 Rx --> DMA Channel 3 36 | */ 37 | 38 | #ifdef RT_USING_UART1 39 | struct stm32_serial_int_rx uart1_int_rx; 40 | struct stm32_serial_device uart1 = 41 | { 42 | USART1, 43 | &uart1_int_rx, 44 | RT_NULL 45 | }; 46 | struct rt_device uart1_device; 47 | #endif 48 | 49 | #ifdef RT_USING_UART2 50 | struct stm32_serial_int_rx uart2_int_rx; 51 | struct stm32_serial_device uart2 = 52 | { 53 | USART2, 54 | &uart2_int_rx, 55 | RT_NULL 56 | }; 57 | struct rt_device uart2_device; 58 | #endif 59 | 60 | #ifdef RT_USING_UART3 61 | struct stm32_serial_int_rx uart3_int_rx; 62 | struct stm32_serial_dma_tx uart3_dma_tx; 63 | struct stm32_serial_device uart3 = 64 | { 65 | USART3, 66 | &uart3_int_rx, 67 | &uart3_dma_tx 68 | }; 69 | struct rt_device uart3_device; 70 | #endif 71 | 72 | #ifdef RT_USING_UART6 73 | struct stm32_serial_int_rx uart6_int_rx; 74 | struct stm32_serial_device uart6 = 75 | { 76 | USART6, 77 | &uart6_int_rx, 78 | RT_NULL 79 | }; 80 | struct rt_device uart6_device; 81 | #endif 82 | 83 | //#define USART1_DR_Base 0x40013804 84 | //#define USART2_DR_Base 0x40004404 85 | //#define USART3_DR_Base 0x40004804 86 | 87 | /* USART1_REMAP = 0 */ 88 | #define UART1_GPIO_TX GPIO_Pin_9 89 | #define UART1_TX_PIN_SOURCE GPIO_PinSource9 90 | #define UART1_GPIO_RX GPIO_Pin_10 91 | #define UART1_RX_PIN_SOURCE GPIO_PinSource10 92 | #define UART1_GPIO GPIOA 93 | #define UART1_GPIO_RCC RCC_AHB1Periph_GPIOA 94 | #define RCC_APBPeriph_UART1 RCC_APB2Periph_USART1 95 | #define UART1_TX_DMA DMA1_Channel4 96 | #define UART1_RX_DMA DMA1_Channel5 97 | 98 | #define UART2_GPIO_TX GPIO_Pin_2 99 | #define UART2_TX_PIN_SOURCE GPIO_PinSource2 100 | #define UART2_GPIO_RX GPIO_Pin_3 101 | #define UART2_RX_PIN_SOURCE GPIO_PinSource3 102 | #define UART2_GPIO GPIOA 103 | #define UART2_GPIO_RCC RCC_AHB1Periph_GPIOA 104 | #define RCC_APBPeriph_UART2 RCC_APB1Periph_USART2 105 | 106 | /* USART3_REMAP[1:0] = 00 */ 107 | #define UART3_GPIO_TX GPIO_Pin_10 108 | #define UART3_TX_PIN_SOURCE GPIO_PinSource10 109 | #define UART3_GPIO_RX GPIO_Pin_11 110 | #define UART3_RX_PIN_SOURCE GPIO_PinSource11 111 | #define UART3_GPIO GPIOB 112 | #define UART3_GPIO_RCC RCC_AHB1Periph_GPIOB 113 | #define RCC_APBPeriph_UART3 RCC_APB1Periph_USART3 114 | #define UART3_TX_DMA DMA1_Stream1 115 | #define UART3_RX_DMA DMA1_Stream3 116 | 117 | #define UART6_GPIO_TX GPIO_Pin_6 118 | #define UART6_TX_PIN_SOURCE GPIO_PinSource6 119 | #define UART6_GPIO_RX GPIO_Pin_7 120 | #define UART6_RX_PIN_SOURCE GPIO_PinSource7 121 | #define UART6_GPIO GPIOC 122 | #define UART6_GPIO_RCC RCC_AHB1Periph_GPIOC 123 | #define RCC_APBPeriph_UART6 RCC_APB2Periph_USART6 124 | 125 | static void RCC_Configuration(void) 126 | { 127 | #ifdef RT_USING_UART1 128 | /* Enable USART2 GPIO clocks */ 129 | RCC_AHB1PeriphClockCmd(UART1_GPIO_RCC, ENABLE); 130 | /* Enable USART2 clock */ 131 | RCC_APB2PeriphClockCmd(RCC_APBPeriph_UART1, ENABLE); 132 | #endif 133 | 134 | #ifdef RT_USING_UART2 135 | /* Enable USART2 GPIO clocks */ 136 | RCC_AHB1PeriphClockCmd(UART2_GPIO_RCC, ENABLE); 137 | /* Enable USART2 clock */ 138 | RCC_APB1PeriphClockCmd(RCC_APBPeriph_UART2, ENABLE); 139 | #endif 140 | 141 | #ifdef RT_USING_UART3 142 | /* Enable USART3 GPIO clocks */ 143 | RCC_AHB1PeriphClockCmd(UART3_GPIO_RCC, ENABLE); 144 | /* Enable USART3 clock */ 145 | RCC_APB1PeriphClockCmd(RCC_APBPeriph_UART3, ENABLE); 146 | 147 | /* DMA clock enable */ 148 | RCC_APB1PeriphClockCmd(RCC_AHB1Periph_DMA1, ENABLE); 149 | #endif 150 | 151 | #ifdef RT_USING_UART6 152 | /* Enable USART6 GPIO clocks */ 153 | RCC_AHB1PeriphClockCmd(UART6_GPIO_RCC, ENABLE); 154 | /* Enable USART6 clock */ 155 | RCC_APB2PeriphClockCmd(RCC_APBPeriph_UART6, ENABLE); 156 | #endif 157 | } 158 | 159 | static void GPIO_Configuration(void) 160 | { 161 | GPIO_InitTypeDef GPIO_InitStructure; 162 | 163 | GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; 164 | GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; 165 | GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; 166 | GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; 167 | 168 | #ifdef RT_USING_UART1 169 | /* Configure USART1 Rx/tx PIN */ 170 | GPIO_InitStructure.GPIO_Pin = UART1_GPIO_RX | UART1_GPIO_TX; 171 | GPIO_Init(UART1_GPIO, &GPIO_InitStructure); 172 | 173 | /* Connect alternate function */ 174 | GPIO_PinAFConfig(UART1_GPIO, UART1_TX_PIN_SOURCE, GPIO_AF_USART1); 175 | GPIO_PinAFConfig(UART1_GPIO, UART1_RX_PIN_SOURCE, GPIO_AF_USART1); 176 | #endif 177 | 178 | #ifdef RT_USING_UART2 179 | /* Configure USART2 Rx/tx PIN */ 180 | GPIO_InitStructure.GPIO_Pin = UART2_GPIO_TX | UART2_GPIO_RX; 181 | GPIO_Init(UART2_GPIO, &GPIO_InitStructure); 182 | 183 | /* Connect alternate function */ 184 | GPIO_PinAFConfig(UART2_GPIO, UART2_TX_PIN_SOURCE, GPIO_AF_USART2); 185 | GPIO_PinAFConfig(UART2_GPIO, UART2_RX_PIN_SOURCE, GPIO_AF_USART2); 186 | #endif 187 | 188 | #ifdef RT_USING_UART3 189 | /* Configure USART3 Rx/tx PIN */ 190 | GPIO_InitStructure.GPIO_Pin = UART3_GPIO_RX | UART3_GPIO_RX; 191 | GPIO_Init(UART3_GPIO, &GPIO_InitStructure); 192 | 193 | /* Connect alternate function */ 194 | GPIO_PinAFConfig(UART3_GPIO, UART3_TX_PIN_SOURCE, GPIO_AF_USART3); 195 | GPIO_PinAFConfig(UART3_GPIO, UART3_RX_PIN_SOURCE, GPIO_AF_USART3); 196 | #endif 197 | 198 | #ifdef RT_USING_UART6 199 | /* Configure USART6 Rx/tx PIN */ 200 | GPIO_InitStructure.GPIO_Pin = UART6_GPIO_TX | UART6_GPIO_RX; 201 | GPIO_Init(UART6_GPIO, &GPIO_InitStructure); 202 | 203 | /* Connect alternate function */ 204 | GPIO_PinAFConfig(UART6_GPIO, UART6_TX_PIN_SOURCE, GPIO_AF_USART6); 205 | GPIO_PinAFConfig(UART6_GPIO, UART6_RX_PIN_SOURCE, GPIO_AF_USART6); 206 | #endif 207 | } 208 | 209 | static void NVIC_Configuration(void) 210 | { 211 | NVIC_InitTypeDef NVIC_InitStructure; 212 | 213 | #ifdef RT_USING_UART1 214 | /* Enable the USART1 Interrupt */ 215 | NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; 216 | NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; 217 | NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; 218 | NVIC_Init(&NVIC_InitStructure); 219 | #endif 220 | 221 | #ifdef RT_USING_UART2 222 | /* Enable the USART2 Interrupt */ 223 | NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn; 224 | NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; 225 | NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; 226 | NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; 227 | NVIC_Init(&NVIC_InitStructure); 228 | #endif 229 | 230 | #ifdef RT_USING_UART3 231 | /* Enable the USART3 Interrupt */ 232 | NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn; 233 | NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; 234 | NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; 235 | NVIC_Init(&NVIC_InitStructure); 236 | 237 | /* Enable the DMA1 Channel2 Interrupt */ 238 | NVIC_InitStructure.NVIC_IRQChannel = DMA1_Stream1_IRQn; 239 | NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; 240 | NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; 241 | NVIC_Init(&NVIC_InitStructure); 242 | #endif 243 | 244 | #ifdef RT_USING_UART6 245 | /* Enable the USART6 Interrupt */ 246 | NVIC_InitStructure.NVIC_IRQChannel = USART6_IRQn; 247 | NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; 248 | NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; 249 | NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; 250 | NVIC_Init(&NVIC_InitStructure); 251 | #endif 252 | } 253 | 254 | static void DMA_Configuration(void) 255 | { 256 | #if defined (RT_USING_UART3) 257 | DMA_InitTypeDef DMA_InitStructure; 258 | 259 | // /* Configure DMA Stream */ 260 | // DMA_InitStructure.DMA_Channel = DMA_CHANNEL; 261 | // DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)SRC_Const_Buffer; 262 | // DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)DST_Buffer; 263 | // DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToMemory; 264 | // DMA_InitStructure.DMA_BufferSize = (uint32_t)BUFFER_SIZE; 265 | // DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Enable; 266 | // DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; 267 | // DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word; 268 | // DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Word; 269 | // DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; 270 | // DMA_InitStructure.DMA_Priority = DMA_Priority_High; 271 | // DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable; 272 | // DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full; 273 | // DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single; 274 | // DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single; 275 | // DMA_Init(DMA_STREAM, &DMA_InitStructure); 276 | 277 | /* Configure DMA Stream */ 278 | DMA_InitStructure.DMA_Channel = DMA_Channel_0; 279 | DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)(&USART3->DR); 280 | DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)0; 281 | DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral; 282 | DMA_InitStructure.DMA_BufferSize = (uint32_t)0; 283 | DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; 284 | DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; 285 | DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word; 286 | DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; 287 | DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; 288 | DMA_InitStructure.DMA_Priority = DMA_Priority_High; 289 | DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable; 290 | DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full; 291 | DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single; 292 | DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single; 293 | 294 | DMA_DeInit(UART3_TX_DMA); 295 | DMA_Init(UART3_TX_DMA, &DMA_InitStructure); 296 | 297 | // /* fill init structure */ 298 | // DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; 299 | // DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; 300 | // DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; 301 | // DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; 302 | // DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; 303 | // DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh; 304 | // DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; 305 | // 306 | // /* DMA1 Channel5 (triggered by USART3 Tx event) Config */ 307 | // DMA_DeInit(UART3_TX_DMA); 308 | // DMA_InitStructure.DMA_PeripheralBaseAddr = USART3_DR_Base; 309 | // DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST; 310 | // DMA_InitStructure.DMA_MemoryBaseAddr = (u32)0; 311 | // DMA_InitStructure.DMA_BufferSize = 0; 312 | // DMA_Init(UART3_TX_DMA, &DMA_InitStructure); 313 | DMA_ITConfig(UART3_TX_DMA, DMA_IT_TC | DMA_IT_TE, ENABLE); 314 | // DMA_ClearFlag(DMA1_FLAG_TC5); 315 | #endif 316 | } 317 | 318 | volatile USART_TypeDef * uart2_debug = USART2; 319 | /* 320 | * Init all related hardware in here 321 | * rt_hw_serial_init() will register all supported USART device 322 | */ 323 | void rt_hw_usart_init() 324 | { 325 | USART_InitTypeDef USART_InitStructure; 326 | 327 | RCC_Configuration(); 328 | 329 | GPIO_Configuration(); 330 | 331 | NVIC_Configuration(); 332 | 333 | DMA_Configuration(); 334 | 335 | /* uart init */ 336 | #ifdef RT_USING_UART1 337 | USART_InitStructure.USART_BaudRate = 115200; 338 | USART_InitStructure.USART_WordLength = USART_WordLength_8b; 339 | USART_InitStructure.USART_StopBits = USART_StopBits_1; 340 | USART_InitStructure.USART_Parity = USART_Parity_No; 341 | USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; 342 | USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; 343 | USART_Init(USART1, &USART_InitStructure); 344 | 345 | /* register uart1 */ 346 | rt_hw_serial_register(&uart1_device, "uart1", 347 | RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX | RT_DEVICE_FLAG_STREAM, 348 | &uart1); 349 | 350 | /* enable interrupt */ 351 | USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); 352 | #endif 353 | 354 | #ifdef RT_USING_UART2 355 | USART_InitStructure.USART_BaudRate = 115200; 356 | USART_InitStructure.USART_WordLength = USART_WordLength_8b; 357 | USART_InitStructure.USART_StopBits = USART_StopBits_1; 358 | USART_InitStructure.USART_Parity = USART_Parity_No; 359 | USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; 360 | USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; 361 | USART_Init(USART2, &USART_InitStructure); 362 | 363 | /* register uart2 */ 364 | rt_hw_serial_register(&uart2_device, "uart2", 365 | RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX | RT_DEVICE_FLAG_STREAM, 366 | &uart2); 367 | 368 | /* Enable USART2 DMA Rx request */ 369 | USART_ITConfig(USART2, USART_IT_RXNE, ENABLE); 370 | #endif 371 | 372 | #ifdef RT_USING_UART3 373 | USART_InitStructure.USART_BaudRate = 115200; 374 | USART_InitStructure.USART_WordLength = USART_WordLength_8b; 375 | USART_InitStructure.USART_StopBits = USART_StopBits_1; 376 | USART_InitStructure.USART_Parity = USART_Parity_No; 377 | USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; 378 | USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; 379 | USART_Init(USART3, &USART_InitStructure); 380 | 381 | // uart3_dma_tx.dma_channel= UART3_TX_DMA; 382 | 383 | /* register uart3 */ 384 | rt_hw_serial_register(&uart3_device, "uart3", 385 | RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX | RT_DEVICE_FLAG_DMA_TX, 386 | &uart3); 387 | 388 | /* Enable USART3 DMA Tx request */ 389 | USART_DMACmd(USART3, USART_DMAReq_Tx , ENABLE); 390 | 391 | /* enable interrupt */ 392 | USART_ITConfig(USART3, USART_IT_RXNE, ENABLE); 393 | #endif 394 | 395 | #ifdef RT_USING_UART6 396 | USART_InitStructure.USART_BaudRate = 9600; 397 | USART_InitStructure.USART_WordLength = USART_WordLength_8b; 398 | USART_InitStructure.USART_StopBits = USART_StopBits_1; 399 | USART_InitStructure.USART_Parity = USART_Parity_No; 400 | USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; 401 | USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; 402 | USART_Init(USART6, &USART_InitStructure); 403 | 404 | /* register uart6 */ 405 | rt_hw_serial_register(&uart6_device, "uart6", 406 | RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_STREAM, 407 | &uart6); 408 | #endif 409 | } 410 | -------------------------------------------------------------------------------- /bsp/stm32f40x/rtconfig.h: -------------------------------------------------------------------------------- 1 | /* RT-Thread config file */ 2 | #ifndef __RTTHREAD_CFG_H__ 3 | #define __RTTHREAD_CFG_H__ 4 | 5 | /* RT_GDB_STUB */ 6 | //#define RT_USING_GDB 7 | 8 | /* RT_NAME_MAX*/ 9 | #define RT_NAME_MAX 8 10 | 11 | /* RT_ALIGN_SIZE*/ 12 | #define RT_ALIGN_SIZE 8 13 | 14 | /* PRIORITY_MAX */ 15 | #define RT_THREAD_PRIORITY_MAX 32 16 | 17 | /* Tick per Second */ 18 | #define RT_TICK_PER_SECOND 100 19 | 20 | /* SECTION: RT_DEBUG */ 21 | /* Thread Debug */ 22 | #define RT_DEBUG 23 | 24 | #define RT_USING_OVERFLOW_CHECK 25 | 26 | /* Using Hook */ 27 | #define RT_USING_HOOK 28 | 29 | #define IDLE_THREAD_STACK_SIZE 1024 30 | 31 | /* Using Software Timer */ 32 | /* #define RT_USING_TIMER_SOFT */ 33 | #define RT_TIMER_THREAD_PRIO 4 34 | #define RT_TIMER_THREAD_STACK_SIZE 512 35 | #define RT_TIMER_TICK_PER_SECOND 10 36 | 37 | /* SECTION: IPC */ 38 | /* Using Semaphore*/ 39 | #define RT_USING_SEMAPHORE 40 | 41 | /* Using Mutex */ 42 | #define RT_USING_MUTEX 43 | 44 | /* Using Event */ 45 | #define RT_USING_EVENT 46 | 47 | /* Using MailBox */ 48 | #define RT_USING_MAILBOX 49 | 50 | /* Using Message Queue */ 51 | #define RT_USING_MESSAGEQUEUE 52 | 53 | /* SECTION: Memory Management */ 54 | /* Using Memory Pool Management*/ 55 | #define RT_USING_MEMPOOL 56 | 57 | /* Using Dynamic Heap Management */ 58 | #define RT_USING_HEAP 59 | 60 | /* Using Small MM */ 61 | #define RT_USING_SMALL_MEM 62 | 63 | /* SECTION: Device System */ 64 | /* Using Device System */ 65 | #define RT_USING_DEVICE 66 | 67 | /* SECTION: Console options */ 68 | #define RT_USING_CONSOLE 69 | /* the buffer size of console*/ 70 | #define RT_CONSOLEBUF_SIZE 128 71 | 72 | /* SECTION: finsh, a C-Express shell */ 73 | #define RT_USING_FINSH 74 | /* Using symbol table */ 75 | #define FINSH_USING_SYMTAB 76 | #define FINSH_USING_DESCRIPTION 77 | 78 | /* SECTION: device filesystem */ 79 | /* #define RT_USING_DFS */ 80 | //#define RT_USING_DFS_ELMFAT 81 | #define RT_DFS_ELM_WORD_ACCESS 82 | /* Reentrancy (thread safe) of the FatFs module. */ 83 | #define RT_DFS_ELM_REENTRANT 84 | /* Number of volumes (logical drives) to be used. */ 85 | #define RT_DFS_ELM_DRIVES 2 86 | /* #define RT_DFS_ELM_USE_LFN 1 */ 87 | #define RT_DFS_ELM_MAX_LFN 255 88 | /* Maximum sector size to be handled. */ 89 | #define RT_DFS_ELM_MAX_SECTOR_SIZE 512 90 | 91 | #define RT_USING_DFS_ROMFS 92 | 93 | /* the max number of mounted filesystem */ 94 | #define DFS_FILESYSTEMS_MAX 2 95 | /* the max number of opened files */ 96 | #define DFS_FD_MAX 4 97 | 98 | /* SECTION: lwip, a lighwight TCP/IP protocol stack */ 99 | /* #define RT_USING_LWIP */ 100 | /* LwIP uses RT-Thread Memory Management */ 101 | #define RT_LWIP_USING_RT_MEM 102 | /* Enable ICMP protocol*/ 103 | #define RT_LWIP_ICMP 104 | /* Enable UDP protocol*/ 105 | #define RT_LWIP_UDP 106 | /* Enable TCP protocol*/ 107 | #define RT_LWIP_TCP 108 | /* Enable DNS */ 109 | #define RT_LWIP_DNS 110 | 111 | /* the number of simulatenously active TCP connections*/ 112 | #define RT_LWIP_TCP_PCB_NUM 5 113 | 114 | /* ip address of target*/ 115 | #define RT_LWIP_IPADDR0 192 116 | #define RT_LWIP_IPADDR1 168 117 | #define RT_LWIP_IPADDR2 1 118 | #define RT_LWIP_IPADDR3 201 119 | 120 | /* gateway address of target*/ 121 | #define RT_LWIP_GWADDR0 192 122 | #define RT_LWIP_GWADDR1 168 123 | #define RT_LWIP_GWADDR2 1 124 | #define RT_LWIP_GWADDR3 1 125 | 126 | /* mask address of target*/ 127 | #define RT_LWIP_MSKADDR0 255 128 | #define RT_LWIP_MSKADDR1 255 129 | #define RT_LWIP_MSKADDR2 255 130 | #define RT_LWIP_MSKADDR3 0 131 | 132 | /* tcp thread options */ 133 | #define RT_LWIP_TCPTHREAD_PRIORITY 12 134 | #define RT_LWIP_TCPTHREAD_MBOX_SIZE 4 135 | #define RT_LWIP_TCPTHREAD_STACKSIZE 1024 136 | 137 | /* ethernet if thread options */ 138 | #define RT_LWIP_ETHTHREAD_PRIORITY 15 139 | #define RT_LWIP_ETHTHREAD_MBOX_SIZE 4 140 | #define RT_LWIP_ETHTHREAD_STACKSIZE 512 141 | 142 | /* TCP sender buffer space */ 143 | #define RT_LWIP_TCP_SND_BUF 8192 144 | /* TCP receive window. */ 145 | #define RT_LWIP_TCP_WND 8192 146 | 147 | #define CHECKSUM_CHECK_TCP 0 148 | #define CHECKSUM_CHECK_IP 0 149 | #define CHECKSUM_CHECK_UDP 0 150 | 151 | #define CHECKSUM_GEN_TCP 0 152 | #define CHECKSUM_GEN_IP 0 153 | #define CHECKSUM_GEN_UDP 0 154 | 155 | #endif 156 | -------------------------------------------------------------------------------- /bsp/stm32f40x/rtconfig.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | # toolchains options 4 | ARCH='arm' 5 | CPU='cortex-m4' 6 | CROSS_TOOL='gcc' 7 | 8 | if os.getenv('RTT_CC'): 9 | CROSS_TOOL = os.getenv('RTT_CC') 10 | 11 | # cross_tool provides the cross compiler 12 | # EXEC_PATH is the compiler execute path, for example, CodeSourcery, Keil MDK, IAR 13 | if CROSS_TOOL == 'gcc': 14 | PLATFORM = 'gcc' 15 | EXEC_PATH = r'E:/Program Files/CodeSourcery/Sourcery G++ Lite/bin' 16 | elif CROSS_TOOL == 'keil': 17 | PLATFORM = 'armcc' 18 | EXEC_PATH = r'C:/Keil' 19 | elif CROSS_TOOL == 'iar': 20 | print '================ERROR============================' 21 | print 'Not support iar yet!' 22 | print '=================================================' 23 | exit(0) 24 | 25 | if os.getenv('RTT_EXEC_PATH'): 26 | EXEC_PATH = os.getenv('RTT_EXEC_PATH') 27 | 28 | BUILD = 'debug' 29 | STM32_TYPE = 'STM32F4XX' 30 | 31 | if PLATFORM == 'gcc': 32 | # toolchains 33 | PREFIX = 'arm-none-eabi-' 34 | CC = PREFIX + 'gcc' 35 | AS = PREFIX + 'gcc' 36 | AR = PREFIX + 'ar' 37 | LINK = PREFIX + 'gcc' 38 | TARGET_EXT = 'axf' 39 | SIZE = PREFIX + 'size' 40 | OBJDUMP = PREFIX + 'objdump' 41 | OBJCPY = PREFIX + 'objcopy' 42 | 43 | DEVICE = ' -mcpu=cortex-m4 -mthumb -mfpu=fpv4-sp-d16 -mfloat-abi=hard -ffunction-sections -fdata-sections' 44 | CFLAGS = DEVICE + ' -g -Wall -DSTM32F407ZG -DSTM32F4XX -DUSE_STDPERIPH_DRIVER -D__ASSEMBLY__ -D__FPU_USED' 45 | AFLAGS = ' -c' + DEVICE + ' -x assembler-with-cpp -Wa,-mimplicit-it=thumb ' 46 | LFLAGS = DEVICE + ' -lm -lgcc -lc' + ' -nostartfiles -Wl,--gc-sections,-Map=rtthread-stm32.map,-cref,-u,Reset_Handler -T stm32_rom.ld' 47 | 48 | CPATH = '' 49 | LPATH = '' 50 | 51 | if BUILD == 'debug': 52 | CFLAGS += ' -O0 -gdwarf-2' 53 | AFLAGS += ' -gdwarf-2' 54 | else: 55 | CFLAGS += ' -O2' 56 | 57 | POST_ACTION = OBJCPY + ' -O binary $TARGET rtthread.bin\n' + SIZE + ' $TARGET \n' 58 | 59 | elif PLATFORM == 'armcc': 60 | # toolchains 61 | CC = 'armcc' 62 | AS = 'armasm' 63 | AR = 'armar' 64 | LINK = 'armlink' 65 | TARGET_EXT = 'axf' 66 | 67 | DEVICE = ' --cortex-m4.fp' 68 | CFLAGS = DEVICE + ' --apcs=interwork -DUSE_STDPERIPH_DRIVER -DSTM32F40_41xxx' 69 | AFLAGS = DEVICE 70 | LFLAGS = DEVICE + ' --info sizes --info totals --info unused --info veneers --list rtthread-stm32.map --scatter stm32_rom.sct' 71 | 72 | CFLAGS += ' -I' + EXEC_PATH + '/ARM/RV31/INC' 73 | LFLAGS += ' --libpath ' + EXEC_PATH + '/ARM/RV31/LIB' 74 | 75 | EXEC_PATH += '/arm/bin40/' 76 | 77 | if BUILD == 'debug': 78 | CFLAGS += ' -g -O0' 79 | AFLAGS += ' -g' 80 | else: 81 | CFLAGS += ' -O2' 82 | 83 | POST_ACTION = 'fromelf --bin $TARGET --output rtthread.bin \nfromelf -z $TARGET' 84 | 85 | elif PLATFORM == 'iar': 86 | # toolchains 87 | CC = 'iccarm' 88 | AS = 'iasmarm' 89 | AR = 'iarchive' 90 | LINK = 'ilinkarm' 91 | TARGET_EXT = 'out' 92 | 93 | DEVICE = ' -D USE_STDPERIPH_DRIVER' + ' -D STM32F10X_HD' 94 | 95 | CFLAGS = DEVICE 96 | CFLAGS += ' --diag_suppress Pa050' 97 | CFLAGS += ' --no_cse' 98 | CFLAGS += ' --no_unroll' 99 | CFLAGS += ' --no_inline' 100 | CFLAGS += ' --no_code_motion' 101 | CFLAGS += ' --no_tbaa' 102 | CFLAGS += ' --no_clustering' 103 | CFLAGS += ' --no_scheduling' 104 | CFLAGS += ' --debug' 105 | CFLAGS += ' --endian=little' 106 | CFLAGS += ' --cpu=Cortex-M4' 107 | CFLAGS += ' -e' 108 | CFLAGS += ' --fpu=None' 109 | CFLAGS += ' --dlib_config "' + IAR_PATH + '/arm/INC/c/DLib_Config_Normal.h"' 110 | CFLAGS += ' -Ol' 111 | CFLAGS += ' --use_c++_inline' 112 | 113 | AFLAGS = '' 114 | AFLAGS += ' -s+' 115 | AFLAGS += ' -w+' 116 | AFLAGS += ' -r' 117 | AFLAGS += ' --cpu Cortex-M4' 118 | AFLAGS += ' --fpu None' 119 | 120 | LFLAGS = ' --config stm32f10x_flash.icf' 121 | LFLAGS += ' --redirect _Printf=_PrintfTiny' 122 | LFLAGS += ' --redirect _Scanf=_ScanfSmall' 123 | LFLAGS += ' --entry __iar_program_start' 124 | 125 | EXEC_PATH = IAR_PATH + '/arm/bin/' 126 | POST_ACTION = '' 127 | -------------------------------------------------------------------------------- /bsp/stm32f40x/stm32_rom.ld: -------------------------------------------------------------------------------- 1 | /* 2 | * linker script for STM32F10x with GNU ld 3 | * bernard.xiong 2009-10-14 4 | */ 5 | 6 | /* Program Entry, set to mark it as "used" and avoid gc */ 7 | MEMORY 8 | { 9 | CODE (rx) : ORIGIN = 0x08000000, LENGTH = 1024k /* 1024KB flash */ 10 | DATA (rw) : ORIGIN = 0x20000000, LENGTH = 128k /* 128K sram */ 11 | } 12 | ENTRY(Reset_Handler) 13 | _system_stack_size = 0x200; 14 | 15 | SECTIONS 16 | { 17 | .text : 18 | { 19 | . = ALIGN(4); 20 | _stext = .; 21 | KEEP(*(.isr_vector)) /* Startup code */ 22 | . = ALIGN(4); 23 | *(.text) /* remaining code */ 24 | *(.text.*) /* remaining code */ 25 | *(.rodata) /* read-only data (constants) */ 26 | *(.rodata*) 27 | *(.glue_7) 28 | *(.glue_7t) 29 | *(.gnu.linkonce.t*) 30 | 31 | /* section information for finsh shell */ 32 | . = ALIGN(4); 33 | __fsymtab_start = .; 34 | KEEP(*(FSymTab)) 35 | __fsymtab_end = .; 36 | . = ALIGN(4); 37 | __vsymtab_start = .; 38 | KEEP(*(VSymTab)) 39 | __vsymtab_end = .; 40 | . = ALIGN(4); 41 | 42 | /* section information for initial. */ 43 | . = ALIGN(4); 44 | __rt_init_start = .; 45 | KEEP(*(SORT(.rti_fn*))) 46 | __rt_init_end = .; 47 | . = ALIGN(4); 48 | 49 | . = ALIGN(4); 50 | _etext = .; 51 | } > CODE = 0 52 | 53 | /* .ARM.exidx is sorted, so has to go in its own output section. */ 54 | __exidx_start = .; 55 | .ARM.exidx : 56 | { 57 | *(.ARM.exidx* .gnu.linkonce.armexidx.*) 58 | 59 | /* This is used by the startup in order to initialize the .data secion */ 60 | _sidata = .; 61 | } > CODE 62 | __exidx_end = .; 63 | 64 | /* .data section which is used for initialized data */ 65 | 66 | .data : AT (_sidata) 67 | { 68 | . = ALIGN(4); 69 | /* This is used by the startup in order to initialize the .data secion */ 70 | _sdata = . ; 71 | 72 | *(.data) 73 | *(.data.*) 74 | *(.gnu.linkonce.d*) 75 | 76 | . = ALIGN(4); 77 | /* This is used by the startup in order to initialize the .data secion */ 78 | _edata = . ; 79 | } >DATA 80 | 81 | .stack : 82 | { 83 | . = . + _system_stack_size; 84 | . = ALIGN(4); 85 | _estack = .; 86 | } >DATA 87 | 88 | __bss_start = .; 89 | .bss : 90 | { 91 | . = ALIGN(4); 92 | /* This is used by the startup in order to initialize the .bss secion */ 93 | _sbss = .; 94 | 95 | *(.bss) 96 | *(.bss.*) 97 | *(COMMON) 98 | 99 | . = ALIGN(4); 100 | /* This is used by the startup in order to initialize the .bss secion */ 101 | _ebss = . ; 102 | 103 | *(.bss.init) 104 | } > DATA 105 | __bss_end = .; 106 | 107 | _end = .; 108 | 109 | /* Stabs debugging sections. */ 110 | .stab 0 : { *(.stab) } 111 | .stabstr 0 : { *(.stabstr) } 112 | .stab.excl 0 : { *(.stab.excl) } 113 | .stab.exclstr 0 : { *(.stab.exclstr) } 114 | .stab.index 0 : { *(.stab.index) } 115 | .stab.indexstr 0 : { *(.stab.indexstr) } 116 | .comment 0 : { *(.comment) } 117 | /* DWARF debug sections. 118 | * Symbols in the DWARF debugging sections are relative to the beginning 119 | * of the section so we begin them at 0. */ 120 | /* DWARF 1 */ 121 | .debug 0 : { *(.debug) } 122 | .line 0 : { *(.line) } 123 | /* GNU DWARF 1 extensions */ 124 | .debug_srcinfo 0 : { *(.debug_srcinfo) } 125 | .debug_sfnames 0 : { *(.debug_sfnames) } 126 | /* DWARF 1.1 and DWARF 2 */ 127 | .debug_aranges 0 : { *(.debug_aranges) } 128 | .debug_pubnames 0 : { *(.debug_pubnames) } 129 | /* DWARF 2 */ 130 | .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } 131 | .debug_abbrev 0 : { *(.debug_abbrev) } 132 | .debug_line 0 : { *(.debug_line) } 133 | .debug_frame 0 : { *(.debug_frame) } 134 | .debug_str 0 : { *(.debug_str) } 135 | .debug_loc 0 : { *(.debug_loc) } 136 | .debug_macinfo 0 : { *(.debug_macinfo) } 137 | /* SGI/MIPS DWARF 2 extensions */ 138 | .debug_weaknames 0 : { *(.debug_weaknames) } 139 | .debug_funcnames 0 : { *(.debug_funcnames) } 140 | .debug_typenames 0 : { *(.debug_typenames) } 141 | .debug_varnames 0 : { *(.debug_varnames) } 142 | } 143 | -------------------------------------------------------------------------------- /components/gdb/SConscript: -------------------------------------------------------------------------------- 1 | Import('rtconfig') 2 | from building import * 3 | 4 | comm = 'libcpu/' + rtconfig.ARCH 5 | if (rtconfig.CPU == 'cortex-m4') or (rtconfig.CPU == 'cortex-m3'): 6 | comm = 'libcpu/cortexm' 7 | src = [] 8 | cwd = GetCurrentDir() 9 | if rtconfig.PLATFORM == 'armcc': 10 | src = Glob('*.c') + Glob(comm + '/*.c') + Glob(comm + '/*_rvds.S') 11 | 12 | if rtconfig.PLATFORM == 'gcc': 13 | src = Glob('*.c') + Glob(comm + '/*.c') + Glob(comm + '/*_gcc.S') 14 | 15 | if rtconfig.PLATFORM == 'iar': 16 | src = Glob('*.c') + Glob(comm + '/*.c') + Glob(comm + '/*_iar.S') 17 | 18 | 19 | CPPPATH = [cwd, cwd + '/' + comm] 20 | 21 | group = DefineGroup('gdb', src, depend = ['RT_USING_GDB'], CPPPATH = CPPPATH) 22 | 23 | Return('group') 24 | -------------------------------------------------------------------------------- /components/gdb/gdb_stub.c: -------------------------------------------------------------------------------- 1 | /* 2 | * GDB stub. 3 | * 4 | * Migarte form linux to rt-thread by Wzyy2 5 | * Original edition : KGDB stub 6 | * 7 | * File : gdb_stub.c 8 | * This file is part of RT-Thread RTOS 9 | * COPYRIGHT (C) 2006, RT-Thread Develop Team 10 | * 11 | * The license and distribution terms for this file may be 12 | * found in the file LICENSE in this distribution or at 13 | * http://www.rt-thread.org/license/LICENSE 14 | * 15 | * Change Logs: 16 | * Date Author Notes 17 | * 2014-07-04 Wzyy2 first version 18 | * 19 | * This file incorporates work covered by the following copyright and 20 | * permission notice: 21 | * 22 | * KGDB stub. 23 | * 24 | * Maintainer: Jason Wessel 25 | * 26 | * Copyright (C) 2000-2001 VERITAS Software Corporation. 27 | * Copyright (C) 2002-2004 Timesys Corporation 28 | * Copyright (C) 2003-2004 Amit S. Kale 29 | * Copyright (C) 2004 Pavel Machek 30 | * Copyright (C) 2004-2006 Tom Rini 31 | * Copyright (C) 2004-2006 LinSysSoft Technologies Pvt. Ltd. 32 | * Copyright (C) 2005-2008 Wind River Systems, Inc. 33 | * Copyright (C) 2007 MontaVista Software, Inc. 34 | * Copyright (C) 2008 Red Hat, Inc., Ingo Molnar 35 | * 36 | * Contributors at various stages not listed above: 37 | * Jason Wessel ( jason.wessel@windriver.com ) 38 | * George Anzinger 39 | * Anurekh Saxena (anurekh.saxena@timesys.com) 40 | * Lake Stevens Instrument Division (Glenn Engel) 41 | * Jim Kingdon, Cygnus Support. 42 | * 43 | * Original KGDB stub: David Grothe , 44 | * Tigran Aivazian 45 | * 46 | * This file is licensed under the terms of the GNU General Public License 47 | * version 2. This program is licensed "as is" without any warranty of any 48 | * kind, whether express or implied. 49 | */ 50 | #include 51 | #include 52 | #include 53 | #include "gdb_stub.h" 54 | 55 | 56 | struct gdb_state { 57 | int signo; 58 | int pass_exception; 59 | }gs; 60 | 61 | /** 62 | * gdb_connected - Is a host GDB connected to us? 63 | */ 64 | int gdb_connected; 65 | 66 | 67 | 68 | /* 69 | * Holds information about breakpoints in a kernel. These breakpoints are 70 | * added and removed by gdb. 71 | */ 72 | #if RT_GDB_HAVE_SWBP 73 | static struct gdb_bkpt gdb_break[GDB_MAX_BREAKPOINTS] = { 74 | [0 ... GDB_MAX_BREAKPOINTS-1] = { .state = BP_UNDEFINED } 75 | }; 76 | #endif 77 | 78 | 79 | /* Storage for the registers, in GDB format. */ 80 | static unsigned long gdb_regs[(NUMREGBYTES + 81 | sizeof(unsigned long) - 1) / 82 | sizeof(unsigned long)]; 83 | 84 | char remcom_in_buffer[BUFMAX]; 85 | char remcom_out_buffer[BUFMAX]; 86 | 87 | 88 | static const char hexchars[] = "0123456789abcdef"; 89 | 90 | 91 | //to call that there has been an error 92 | void* volatile gdb_mem_fault_handler = (void *)0; 93 | static long probe_kernel_write(void *dst, void *src, size_t size) 94 | { 95 | int i = 0; 96 | char *dst_ptr = (char *)dst; 97 | char *src_ptr = (char *)src; 98 | 99 | gdb_mem_fault_handler = &&err; 100 | 101 | for (i = 0; i= 'a') && (ch <= 'f')) 118 | return ch - 'a' + 10; 119 | if ((ch >= '0') && (ch <= '9')) 120 | return ch - '0'; 121 | if ((ch >= 'A') && (ch <= 'F')) 122 | return ch - 'A' + 10; 123 | return -1; 124 | } 125 | 126 | static char tohex(char c) 127 | { 128 | return hexchars[c & 15]; 129 | } 130 | 131 | /* 132 | * Copy the binary array pointed to by buf into mem. Fix $, #, and 133 | * 0x7d escaped with 0x7d. Return a pointer to the character after 134 | * the last byte written. 135 | */ 136 | int gdb_ebin2mem(char *buf, char *mem, int count) 137 | { 138 | int err = 0; 139 | char c; 140 | 141 | while (count-- > 0) { 142 | c = *buf++; 143 | if (c == 0x7d) 144 | c = *buf++ ^ 0x20; 145 | 146 | err = probe_kernel_write(mem, &c, 1); 147 | if (err) 148 | break; 149 | 150 | mem++; 151 | } 152 | 153 | return err; 154 | } 155 | 156 | /* 157 | * Convert the hex array pointed to by buf into binary to be placed in mem. 158 | * Return a pointer to the character AFTER the last byte written. 159 | * May return an error. 160 | */ 161 | int gdb_hex2mem(char *buf, char *mem, int count) 162 | { 163 | char *tmp_raw; 164 | char *tmp_hex; 165 | 166 | tmp_raw = buf + count * 2; 167 | 168 | tmp_hex = tmp_raw - 1; 169 | while (tmp_hex >= buf) { 170 | tmp_raw--; 171 | *tmp_raw = hex(*tmp_hex--); 172 | *tmp_raw |= hex(*tmp_hex--) << 4; 173 | } 174 | 175 | return probe_kernel_write(mem, tmp_raw, count); 176 | } 177 | /* 178 | * Convert the memory pointed to by mem into hex, placing result in buf. 179 | * Return a pointer to the last char put in buf (null). May return an error. 180 | */ 181 | int gdb_mem2hex(char *mem, char *buf, int count) 182 | { 183 | char *tmp = mem; 184 | char ch; 185 | 186 | gdb_mem_fault_handler = &&err; 187 | 188 | while (count > 0) { 189 | ch = *(tmp++); 190 | *(buf++) = tohex((ch >> 4) & 0xf); 191 | *(buf++) = tohex(ch & 0xf); 192 | 193 | count--; 194 | } 195 | *buf = 0; 196 | 197 | gdb_mem_fault_handler = (void *)0; 198 | return 0; 199 | err: 200 | gdb_mem_fault_handler = (void *)0; 201 | return -1; 202 | } 203 | 204 | /* 205 | * While we find nice hex chars, build a long_val. 206 | * Return number of chars processed. 207 | */ 208 | int gdb_hex2long(char **ptr, unsigned long *long_val) 209 | { 210 | int hex_val; 211 | int num = 0; 212 | int negate = 0; 213 | 214 | *long_val = 0; 215 | 216 | if (**ptr == '-') { 217 | negate = 1; 218 | (*ptr)++; 219 | } 220 | while (**ptr) { 221 | hex_val = hex(**ptr); 222 | if (hex_val < 0) 223 | break; 224 | 225 | *long_val = (*long_val << 4) | hex_val; 226 | num++; 227 | (*ptr)++; 228 | } 229 | 230 | if (negate) 231 | *long_val = -*long_val; 232 | 233 | return num; 234 | } 235 | 236 | /* Write memory due to an 'M' or 'X' packet. */ 237 | static int write_mem_msg(int binary) 238 | { 239 | char *ptr = &remcom_in_buffer[1]; 240 | unsigned long addr; 241 | unsigned long length; 242 | int err; 243 | 244 | if (gdb_hex2long(&ptr, &addr) > 0 && *(ptr++) == ',' && 245 | gdb_hex2long(&ptr, &length) > 0 && *(ptr++) == ':') { 246 | #ifdef GDB_DATA_ACCESS 247 | //accesses to areas not backed can cause error 248 | if (gdb_permit_data_access(addr, length)) 249 | return -1; 250 | #endif 251 | if (binary) 252 | err = gdb_ebin2mem(ptr, (char *)addr, length); 253 | else 254 | err = gdb_hex2mem(ptr, (char *)addr, length); 255 | if (err) 256 | return err; 257 | #ifdef RT_GDB_ICACHE 258 | if (CACHE_FLUSH_IS_SAFE) 259 | gdb_flush_icache_range(addr, addr + length); 260 | #endif 261 | return 0; 262 | } 263 | 264 | return -1; 265 | } 266 | 267 | /* 268 | * Send the packet in buffer. 269 | * Check for gdb connection if asked for. 270 | */ 271 | static void put_packet(char *buffer) 272 | { 273 | unsigned char checksum; 274 | int count; 275 | char ch; 276 | 277 | /* 278 | * $#. 279 | */ 280 | while (1) { 281 | gdb_io_ops.write_char('$'); 282 | checksum = 0; 283 | count = 0; 284 | 285 | while ((ch = buffer[count])) { 286 | gdb_io_ops.write_char(ch); 287 | checksum += ch; 288 | count++; 289 | } 290 | 291 | gdb_io_ops.write_char('#'); 292 | gdb_io_ops.write_char(tohex((checksum >> 4) & 0xf)); 293 | gdb_io_ops.write_char(tohex(checksum & 0xf)); 294 | 295 | 296 | /* Now see what we get in reply. */ 297 | ch = gdb_io_ops.read_char(); 298 | 299 | /* If we get an ACK, we are done. */ 300 | if (ch == '+') 301 | return; 302 | 303 | /* 304 | * If we get the start of another packet, this means 305 | * that GDB is attempting to reconnect. We will NAK 306 | * the packet being sent, and stop trying to send this 307 | * packet. 308 | */ 309 | if (ch == '$') { 310 | gdb_io_ops.write_char('-'); 311 | if (gdb_io_ops.flush) 312 | gdb_io_ops.flush(); 313 | return; 314 | } 315 | } 316 | } 317 | 318 | /* scan for the sequence $# */ 319 | static void get_packet(char *buffer) 320 | { 321 | unsigned char checksum; 322 | unsigned char xmitcsum; 323 | int count; 324 | char ch; 325 | 326 | do { 327 | /* 328 | * Spin and wait around for the start character, ignore all 329 | * other characters: 330 | */ 331 | while ((ch = (gdb_io_ops.read_char())) != '$') 332 | /* nothing */; 333 | gdb_connected = 1; 334 | checksum = 0; 335 | xmitcsum = -1; 336 | 337 | count = 0; 338 | 339 | /* 340 | * now, read until a # or end of buffer is found: 341 | */ 342 | while (count < (BUFMAX - 1)) { 343 | ch = gdb_io_ops.read_char(); 344 | if (ch == '#') 345 | break; 346 | checksum = checksum + ch; 347 | buffer[count] = ch; 348 | count = count + 1; 349 | } 350 | buffer[count] = 0; 351 | 352 | if (ch == '#') { 353 | xmitcsum = hex(gdb_io_ops.read_char()) << 4; 354 | xmitcsum += hex(gdb_io_ops.read_char()); 355 | 356 | if (checksum != xmitcsum) 357 | /* failed checksum */ 358 | gdb_io_ops.write_char('-'); 359 | else 360 | /* successful transfer */ 361 | gdb_io_ops.write_char('+'); 362 | if (gdb_io_ops.flush) 363 | gdb_io_ops.flush(); 364 | } 365 | } while (checksum != xmitcsum); 366 | } 367 | 368 | static void error_packet(char *pkt, int error) 369 | { 370 | error = -error; 371 | pkt[0] = 'E'; 372 | pkt[1] = tohex((error / 10)); 373 | pkt[2] = tohex((error % 10)); 374 | pkt[3] = '\0'; 375 | } 376 | 377 | #if RT_GDB_HAVE_SWBP 378 | static int gdb_arch_set_breakpoint(unsigned long addr, char *saved_instr) 379 | { 380 | int err; 381 | 382 | err = probe_kernel_write((void *)saved_instr, (void *)addr, BREAK_INSTR_SIZE); 383 | if (err) 384 | return err; 385 | 386 | return probe_kernel_write((void *)addr, (void *)arch_gdb_ops.gdb_bpt_instr, 387 | BREAK_INSTR_SIZE); 388 | } 389 | 390 | static int gdb_arch_remove_breakpoint(unsigned long addr, char *bundle) 391 | { 392 | return probe_kernel_write((void *)addr, 393 | (void *)bundle, BREAK_INSTR_SIZE); 394 | } 395 | static int gdb_validate_break_address(unsigned long addr) 396 | { 397 | char tmp_variable[BREAK_INSTR_SIZE]; 398 | int err; 399 | /* Validate setting the breakpoint and then removing it. In the 400 | * remove fails, the kernel needs to emit a bad message because we 401 | * are deep trouble not being able to put things back the way we 402 | * found them. 403 | */ 404 | err = gdb_arch_set_breakpoint(addr, tmp_variable); 405 | if (err) 406 | return err; 407 | err = gdb_arch_remove_breakpoint(addr, tmp_variable); 408 | if (err) 409 | rt_kprintf("GDB: Critical breakpoint error,memory destroyed at: %08x \n", addr); 410 | return err; 411 | } 412 | 413 | /* 414 | * Some architectures need cache flushes when we set/clear a 415 | * breakpoint: 416 | */ 417 | static void gdb_flush_swbreak_addr(unsigned long addr) 418 | { 419 | if (!CACHE_FLUSH_IS_SAFE) 420 | return; 421 | 422 | /* Force flush instruction cache if it was outside the mm */ 423 | gdb_flush_icache_range(addr, addr + BREAK_INSTR_SIZE); 424 | } 425 | 426 | /* 427 | * SW breakpoint management: 428 | */ 429 | static int gdb_activate_sw_breakpoints(void) 430 | { 431 | unsigned long addr; 432 | int error = 0; 433 | int i; 434 | 435 | for (i = 0; i < GDB_MAX_BREAKPOINTS; i++) { 436 | if (gdb_break[i].state != BP_SET) 437 | continue; 438 | 439 | addr = gdb_break[i].bpt_addr; 440 | error = gdb_arch_set_breakpoint(addr, 441 | (char *)(gdb_break[i].saved_instr)); 442 | if (error) 443 | return error; 444 | 445 | gdb_flush_swbreak_addr(addr); 446 | gdb_break[i].state = BP_ACTIVE; 447 | } 448 | return 0; 449 | } 450 | 451 | int gdb_set_sw_break(unsigned long addr) 452 | { 453 | int err = gdb_validate_break_address(addr); 454 | int breakno = -1; 455 | int i; 456 | 457 | if (err) 458 | return err; 459 | 460 | for (i = 0; i < GDB_MAX_BREAKPOINTS; i++) { 461 | if ((gdb_break[i].state == BP_SET) && 462 | (gdb_break[i].bpt_addr == addr)) 463 | return -1; 464 | } 465 | for (i = 0; i < GDB_MAX_BREAKPOINTS; i++) { 466 | if (gdb_break[i].state == BP_REMOVED) { 467 | breakno = i; 468 | break; 469 | } 470 | } 471 | 472 | if (breakno == -1) { 473 | for (i = 0; i < GDB_MAX_BREAKPOINTS; i++) { 474 | if (gdb_break[i].state == BP_UNDEFINED) { 475 | breakno = i; 476 | break; 477 | } 478 | } 479 | } 480 | 481 | if (breakno == -1) 482 | return -1; 483 | 484 | gdb_break[breakno].state = BP_SET; 485 | gdb_break[breakno].type = BP_BREAKPOINT; 486 | gdb_break[breakno].bpt_addr = addr; 487 | 488 | return 0; 489 | } 490 | 491 | static int gdb_deactivate_sw_breakpoints(void) 492 | { 493 | unsigned long addr; 494 | int error = 0; 495 | int i; 496 | 497 | for (i = 0; i < GDB_MAX_BREAKPOINTS; i++) { 498 | if (gdb_break[i].state != BP_ACTIVE) 499 | continue; 500 | addr = gdb_break[i].bpt_addr; 501 | error = gdb_arch_remove_breakpoint(addr, 502 | (char *)(gdb_break[i].saved_instr)); 503 | if (error) 504 | return error; 505 | 506 | gdb_flush_swbreak_addr(addr); 507 | gdb_break[i].state = BP_SET; 508 | } 509 | return 0; 510 | } 511 | 512 | int gdb_remove_sw_break(unsigned long addr) 513 | { 514 | int i; 515 | 516 | for (i = 0; i < GDB_MAX_BREAKPOINTS; i++) { 517 | if ((gdb_break[i].state == BP_SET) && 518 | (gdb_break[i].bpt_addr == addr)) { 519 | gdb_break[i].state = BP_REMOVED; 520 | return 0; 521 | } 522 | } 523 | return -1; 524 | } 525 | 526 | int gdb_isremovedbreak(unsigned long addr) 527 | { 528 | int i; 529 | 530 | for (i = 0; i < GDB_MAX_BREAKPOINTS; i++) { 531 | if ((gdb_break[i].state == BP_REMOVED) && 532 | (gdb_break[i].bpt_addr == addr)) 533 | return 1; 534 | } 535 | return 0; 536 | } 537 | #endif 538 | 539 | static int remove_all_break() 540 | { 541 | #if RT_GDB_HAVE_SWBP 542 | unsigned long addr; 543 | int error=0; 544 | int i; 545 | 546 | /* Clear memory breakpoints. */ 547 | for (i = 0; i < GDB_MAX_BREAKPOINTS; i++) { 548 | if (gdb_break[i].state != BP_ACTIVE) 549 | goto setundefined; 550 | addr = gdb_break[i].bpt_addr; 551 | error = gdb_arch_remove_breakpoint(addr, 552 | (char *)gdb_break[i].saved_instr); 553 | if (error) 554 | rt_kprintf("GDB: breakpoint remove failed: %lx\n", 555 | addr); 556 | setundefined: 557 | gdb_break[i].state = BP_UNDEFINED; 558 | } 559 | #endif 560 | 561 | #if RT_GDB_HAVE_HWBP 562 | /* Clear hardware breakpoints. */ 563 | arch_gdb_ops.remove_all_hw_break(); 564 | #endif 565 | 566 | return 0; 567 | } 568 | 569 | 570 | static char gdbmsgbuf[BUFMAX + 1]; 571 | static void gdb_msg_write(const char *s, int len) 572 | { 573 | char *bufptr; 574 | int wcount; 575 | int i; 576 | 577 | /* 'O'utput */ 578 | gdbmsgbuf[0] = 'O'; 579 | 580 | /* Fill and send buffers... */ 581 | while (len > 0) { 582 | bufptr = gdbmsgbuf + 1; 583 | 584 | /* Calculate how many this time */ 585 | if ((len << 1) > (BUFMAX - 2)) 586 | wcount = (BUFMAX - 2) >> 1; 587 | else 588 | wcount = len; 589 | 590 | /* Pack in hex chars */ 591 | for (i = 0; i < wcount; i++) { 592 | *(bufptr++) = tohex((s[i] >> 4) & 0xf); 593 | *(bufptr++) = tohex(s[i] & 0xf); 594 | } 595 | *bufptr = '\0'; 596 | 597 | /* Move up */ 598 | s += wcount; 599 | len -= wcount; 600 | 601 | /* Write packet */ 602 | put_packet(gdbmsgbuf); 603 | } 604 | } 605 | 606 | /* 607 | * Return true if there is a valid gdb I/O module. Also if no 608 | * debugger is attached a message can be printed to the console about 609 | * waiting for the debugger to attach. 610 | * 611 | * The print_wait argument is only to be true when called from inside 612 | * the core gdb_handle_exception, because it will wait for the 613 | * debugger to attach. 614 | */ 615 | static int gdb_io_ready(int print_wait) 616 | { 617 | if (!gdb_dev) 618 | return 0; 619 | if (gdb_connected) 620 | return 1; 621 | if (print_wait) 622 | rt_kprintf("GDB: Waiting for remote debugger\n"); 623 | return 1; 624 | } 625 | 626 | /* Handle the '?' status packets */ 627 | static void gdb_cmd_status(struct gdb_state *gs) 628 | { 629 | /* 630 | * We know that this packet is only sent 631 | * during initial connect. So to be safe, 632 | * we clear out our breakpoints now in case 633 | * GDB is reconnecting. 634 | */ 635 | remove_all_break(); 636 | 637 | remcom_out_buffer[0] = 'S'; 638 | remcom_out_buffer[1] = tohex((gs->signo >> 4) &0xf); 639 | remcom_out_buffer[2] = tohex(gs->signo & 0xf); 640 | remcom_out_buffer[3] = 0; 641 | } 642 | 643 | /* Handle the 'm' memory read bytes */ 644 | static void gdb_cmd_memread(struct gdb_state *gs) 645 | { 646 | char *ptr = &remcom_in_buffer[1]; 647 | unsigned long length; 648 | unsigned long addr; 649 | int err; 650 | 651 | if (gdb_hex2long(&ptr, &addr) > 0 && *ptr++ == ',' && 652 | gdb_hex2long(&ptr, &length) > 0) { 653 | #ifdef GDB_DATA_ACCESS 654 | //accesses to areas not backed can cause error 655 | if (gdb_permit_data_access(addr, length)) 656 | return ; 657 | #endif 658 | err = gdb_mem2hex((char *)addr, remcom_out_buffer, length); 659 | if (err) 660 | error_packet(remcom_out_buffer, err); 661 | } else { 662 | error_packet(remcom_out_buffer, -1); 663 | } 664 | } 665 | 666 | /* Handle the 'M' memory write bytes */ 667 | static void gdb_cmd_memwrite(struct gdb_state *gs) 668 | { 669 | int err = write_mem_msg(0); 670 | 671 | if (err) 672 | error_packet(remcom_out_buffer, err); 673 | else 674 | strcpy(remcom_out_buffer, "OK"); 675 | } 676 | 677 | /* Handle the 'X' memory binary write bytes */ 678 | static void gdb_cmd_binwrite(struct gdb_state *gs) 679 | { 680 | int err = write_mem_msg(1); 681 | 682 | if (err) 683 | error_packet(remcom_out_buffer, err); 684 | else 685 | strcpy(remcom_out_buffer, "OK"); 686 | } 687 | 688 | /* Handle the 'q' query packets */ 689 | static void gdb_cmd_query(struct gdb_state *gs) 690 | { 691 | /* nothing,because we have no thread support */ 692 | } 693 | 694 | 695 | /* Handle the 'g' or 'p' get registers request */ 696 | static void gdb_cmd_getregs(struct gdb_state *gs) 697 | { 698 | char len = sizeof(long); 699 | 700 | gdb_get_register((unsigned long *)gdb_regs); 701 | 702 | /*get one registers*/ 703 | if (remcom_in_buffer[0] == 'p'){ 704 | char *p = &remcom_in_buffer[1]; 705 | unsigned long regno = 0; 706 | 707 | if (gdb_hex2long(&p, ®no)){ 708 | gdb_mem2hex(((char *)gdb_regs) + regno * len, remcom_out_buffer, len); 709 | return; 710 | } else { 711 | strcpy(remcom_out_buffer, "INVALID"); 712 | return; 713 | } 714 | } 715 | 716 | gdb_mem2hex((char *)gdb_regs, remcom_out_buffer, NUMREGBYTES); 717 | } 718 | 719 | /* Handle the 'G' or 'P' set registers request */ 720 | static void gdb_cmd_setregs(struct gdb_state *gs) 721 | { 722 | char len = sizeof(long); 723 | 724 | /*set one registers*/ 725 | if (remcom_in_buffer[0] == 'P'){ 726 | char *p = &remcom_in_buffer[1]; 727 | unsigned long regno = 0; 728 | 729 | if (gdb_hex2long(&p, ®no) && *p++ == '='){ 730 | gdb_get_register((unsigned long *)gdb_regs); 731 | gdb_hex2mem(p, ((char *)gdb_regs) + regno * len, len); 732 | gdb_put_register(gdb_regs); 733 | strcpy(remcom_out_buffer, "OK"); 734 | } 735 | 736 | return; 737 | } 738 | 739 | gdb_hex2mem(&remcom_in_buffer[1], (char *)gdb_regs, NUMREGBYTES); 740 | 741 | gdb_put_register(gdb_regs); 742 | strcpy(remcom_out_buffer, "OK"); 743 | } 744 | 745 | /* Handle the 'D' or 'k', detach or kill packets */ 746 | static void gdb_cmd_detachkill(struct gdb_state *gs) 747 | { 748 | int error; 749 | 750 | /* The detach case */ 751 | if (remcom_in_buffer[0] == 'D') { 752 | error = remove_all_break(); 753 | if (error < 0) { 754 | error_packet(remcom_out_buffer, error); 755 | } else { 756 | strcpy(remcom_out_buffer, "OK"); 757 | gdb_connected = 0; 758 | } 759 | put_packet(remcom_out_buffer); 760 | } else { 761 | /* 762 | * Assume the kill case, with no exit code checking, 763 | * trying to force detach the debugger: 764 | */ 765 | remove_all_break(); 766 | gdb_connected = 0; 767 | } 768 | } 769 | 770 | /* Handle the 'z' or 'Z' breakpoint remove or set packets */ 771 | static void gdb_cmd_break(struct gdb_state *gs) 772 | { 773 | /* 774 | * Since GDB-5.3, it's been drafted that '0' is a software 775 | * breakpoint, '1' is a hardware breakpoint, so let's do that. 776 | */ 777 | char *bpt_type = &remcom_in_buffer[1]; 778 | char *ptr = &remcom_in_buffer[2]; 779 | unsigned long addr; 780 | unsigned long length; 781 | int error = 0; 782 | 783 | if (arch_gdb_ops.set_hw_breakpoint && *bpt_type >= '1') { 784 | /* Unsupported */ 785 | if (*bpt_type > '4') 786 | return; 787 | } 788 | /* 789 | * Test if this is a hardware breakpoint, and 790 | * if we support it: 791 | */ 792 | if (*bpt_type == '1' && !(arch_gdb_ops.flags)) { 793 | /* Unsupported. */ 794 | return; 795 | } 796 | if (*(ptr++) != ',') { 797 | error_packet(remcom_out_buffer, -1); 798 | return; 799 | } 800 | if (!gdb_hex2long(&ptr, &addr)) { 801 | error_packet(remcom_out_buffer, -1); 802 | return; 803 | } 804 | if (*(ptr++) != ',' || 805 | !gdb_hex2long(&ptr, &length)) { 806 | error_packet(remcom_out_buffer, -1); 807 | return; 808 | } 809 | #if RT_GDB_HAVE_SWBP 810 | if (remcom_in_buffer[0] == 'Z' && *bpt_type == '0') 811 | error = gdb_set_sw_break(addr); 812 | else if (remcom_in_buffer[0] == 'z' && *bpt_type == '0') 813 | error = gdb_remove_sw_break(addr); 814 | #else 815 | if (remcom_in_buffer[0] == 'Z' && *bpt_type == '0') 816 | error = arch_gdb_ops.set_hw_breakpoint(addr, 817 | (int)length, BP_HARDWARE_BREAKPOINT); 818 | else if (remcom_in_buffer[0] == 'z' && *bpt_type == '0') 819 | error = arch_gdb_ops.remove_hw_breakpoint(addr, 820 | (int) length, BP_HARDWARE_BREAKPOINT); 821 | #endif 822 | else if (remcom_in_buffer[0] == 'Z') 823 | error = arch_gdb_ops.set_hw_breakpoint(addr, 824 | (int)length, *bpt_type - '0'); 825 | else if (remcom_in_buffer[0] == 'z') 826 | error = arch_gdb_ops.remove_hw_breakpoint(addr, 827 | (int) length, *bpt_type - '0'); 828 | 829 | if (error == 0) 830 | strcpy(remcom_out_buffer, "OK"); 831 | else 832 | error_packet(remcom_out_buffer, error); 833 | } 834 | 835 | /* Handle the 'C' signal / exception passing packets */ 836 | static int gdb_cmd_exception_pass(struct gdb_state *gs) 837 | { 838 | /* C09 == pass exception 839 | * C15 == detach gdb, pass exception 840 | */ 841 | if (remcom_in_buffer[1] == '0' && remcom_in_buffer[2] == '9') { 842 | 843 | gs->pass_exception = 1; 844 | remcom_in_buffer[0] = 'c'; 845 | 846 | } else if (remcom_in_buffer[1] == '1' && remcom_in_buffer[2] == '5') { 847 | 848 | gs->pass_exception = 1; 849 | remcom_in_buffer[0] = 'D'; 850 | remove_all_break(); 851 | gdb_connected = 0; 852 | return 1; 853 | 854 | } else { 855 | error_packet(remcom_out_buffer, -1); 856 | return 0; 857 | } 858 | 859 | /* Indicate fall through */ 860 | return -1; 861 | } 862 | 863 | 864 | /*more about packet in https://www.sourceware.org/gdb/current/onlinedocs/gdb/Packets.html#Packets*/ 865 | static int process_packet(char *pkt) 866 | { 867 | int status = 0; 868 | int tmp; 869 | 870 | status = gdb_arch_handle_exception(remcom_in_buffer, 871 | remcom_out_buffer); 872 | 873 | remcom_out_buffer[0] = 0; 874 | switch (pkt[0]) { 875 | case '?':/* gdbserial status */ 876 | gdb_cmd_status(&gs); 877 | break; 878 | case 'q':/* query command */ 879 | gdb_cmd_query(&gs); 880 | break; 881 | case 'p': /* return the value of a single CPU register */ 882 | case 'g': /* return the value of the CPU registers */ 883 | gdb_cmd_getregs(&gs); 884 | break; 885 | case 'P': /* set the value of a single CPU registers - return OK */ 886 | case 'G': /* set the value of the CPU registers - return OK */ 887 | gdb_cmd_setregs(&gs); 888 | break; 889 | case 'm': /* mAA..AA,LLLL Read LLLL bytes at address AA..AA */ 890 | gdb_cmd_memread(&gs); 891 | break; 892 | case 'X':/* XAA..AA,LLLL: Write LLLL escaped binary bytes at address AA.AA*/ 893 | gdb_cmd_binwrite(&gs); 894 | break; 895 | case 'M':/* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */ 896 | gdb_cmd_memwrite(&gs); 897 | break; 898 | case 'D': /* Debugger detach */ 899 | case 'k': /* Debugger detach via kill */ 900 | gdb_cmd_detachkill(&gs); 901 | break; 902 | case 'C':/* Exception passing */ 903 | tmp = gdb_cmd_exception_pass(&gs); 904 | if (tmp > 0) 905 | process_packet(remcom_in_buffer); 906 | if (tmp == 0) 907 | break; 908 | case 'z':/* Break point remove */ 909 | case 'Z':/* Break point set */ 910 | gdb_cmd_break(&gs); 911 | break; 912 | case 'H':/* task related */ 913 | break; 914 | case 'T':/* Query thread status */ 915 | break; 916 | case 'b': /* bBB... Set baud rate to BB... */ 917 | break; 918 | case 's': /* sAA..AA step form address AA..AA (optional) */ 919 | case 'c': /* cAA..AA Continue at address AA..AA (optional) */ 920 | #if RT_GDB_HAVE_SWBP 921 | gdb_activate_sw_breakpoints(); 922 | #endif 923 | break; 924 | } 925 | 926 | if (!status) 927 | return -1; 928 | 929 | exit: 930 | put_packet(remcom_out_buffer); 931 | return 0; 932 | } 933 | 934 | 935 | /* 936 | * This function does all command procesing for interfacing to gdb. 937 | */ 938 | int gdb_process_exception() 939 | { 940 | int status; 941 | 942 | do { 943 | get_packet(remcom_in_buffer); 944 | status = process_packet(remcom_in_buffer); 945 | } while (status == 0); 946 | 947 | if (status < 0) 948 | return 0; 949 | else 950 | return 1; 951 | } 952 | 953 | 954 | int gdb_handle_exception(int signo, void *regs) 955 | { 956 | int error; 957 | 958 | gs.signo = signo; 959 | 960 | if (!gdb_io_ready(1)) { 961 | error = 1; 962 | return error; /* No I/O connection, so resume the system */ 963 | } 964 | 965 | #if RT_GDB_HAVE_SWBP 966 | gdb_deactivate_sw_breakpoints(); 967 | #endif 968 | gdb_set_register(regs); 969 | 970 | /* Clear the out buffer. */ 971 | memset(remcom_out_buffer, 0, sizeof(remcom_out_buffer)); 972 | 973 | if (gdb_connected) { 974 | char *ptr; 975 | 976 | gdb_io_ops.write_char('\n'); 977 | /* Reply to host that an exception has occurred */ 978 | ptr = remcom_out_buffer; 979 | *ptr++ = 'T'; 980 | *ptr++ = tohex((gs.signo >> 4) &0xf); 981 | *ptr++ = tohex(gs.signo & 0xf); 982 | /*ptr += strlen(strcpy(ptr, "thread:"));*/ 983 | /**ptr++ = ';';*/ 984 | put_packet(remcom_out_buffer); 985 | } 986 | gs.pass_exception = 0; 987 | 988 | 989 | while (gdb_process_exception()); 990 | 991 | error = gs.pass_exception; 992 | 993 | return error; 994 | } 995 | 996 | void gdb_console_write(const char *s, unsigned count) 997 | { 998 | /* If we're debugging, or GDB has not connected, don't try 999 | * and print. */ 1000 | if (!gdb_connected) 1001 | return; 1002 | 1003 | gdb_msg_write(s, count); 1004 | } 1005 | 1006 | -------------------------------------------------------------------------------- /components/gdb/gdb_stub.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This provides the functions that GDB needs to share between 3 | * different portions. 4 | * 5 | * GDB stub. 6 | * 7 | * Migarte form linux to rt-thread by Wzyy2 8 | * Original edition : KGDB stub 9 | * 10 | * File : gdb_stub.h 11 | * This file is part of RT-Thread RTOS 12 | * COPYRIGHT (C) 2006, RT-Thread Develop Team 13 | * 14 | * The license and distribution terms for this file may be 15 | * found in the file LICENSE in this distribution or at 16 | * http://www.rt-thread.org/license/LICENSE 17 | * 18 | * Change Logs: 19 | * Date Author Notes 20 | * 2014-07-04 Wzyy2 first version 21 | */ 22 | #ifndef __GDB_STUB_H__ 23 | #define __GDB_STUB_H__ 24 | 25 | #include 26 | #include 27 | 28 | 29 | #ifndef RT_GDB_MAX_BREAKPOINTS 30 | #define GDB_MAX_BREAKPOINTS 20 31 | #else 32 | #define GDB_MAX_BREAKPOINTS RT_GDB_MAX_BREAKPOINTS 33 | #endif 34 | 35 | 36 | // Signal definitions 37 | #define SIGHUP 1 /* hangup */ 38 | #define SIGINT 2 /* interrupt */ //irq or fiq 39 | #define SIGQUIT 3 /* quit */ 40 | #define SIGILL 4 /* illegal instruction (not reset when caught) */ 41 | #define SIGTRAP 5 /* trace trap (not reset when caught) */ 42 | #define SIGIOT 6 /* IOT instruction */ 43 | #define SIGABRT 6 /* used by abort, replace SIGIOT in the future */ 44 | #define SIGEMT 7 /* EMT instruction */ 45 | #define SIGFPE 8 /* floating point exception */ 46 | #define SIGKILL 9 /* kill (cannot be caught or ignored) */ 47 | #define SIGBUS 10 /* bus error */ //abort or reserved 48 | #define SIGSEGV 11 /* segmentation violation */ 49 | #define SIGSYS 12 /* bad argument to system call */ 50 | #define SIGPIPE 13 /* write on a pipe with no one to read it */ 51 | #define SIGALRM 14 /* alarm clock */ 52 | #define SIGTERM 15 /* software termination signal from kill */ 53 | 54 | enum gdb_bptype { 55 | BP_BREAKPOINT = 0, 56 | BP_HARDWARE_BREAKPOINT, 57 | BP_WRITE_WATCHPOINT, 58 | BP_READ_WATCHPOINT, 59 | BP_ACCESS_WATCHPOINT, 60 | BP_POKE_BREAKPOINT, 61 | }; 62 | 63 | enum gdb_bpstate { 64 | BP_UNDEFINED = 0, 65 | BP_REMOVED, 66 | BP_SET, 67 | BP_ACTIVE 68 | }; 69 | 70 | struct gdb_bkpt { 71 | unsigned long bpt_addr; 72 | unsigned char saved_instr[BREAK_INSTR_SIZE]; 73 | enum gdb_bptype type; 74 | enum gdb_bpstate state; 75 | }; 76 | 77 | /** 78 | * struct gdb_arch - Describe architecture specific values. 79 | * @gdb_bpt_instr: The instruction to trigger a breakpoint. 80 | * @flags: Flags for the breakpoint, currently just %GDB_HW_BREAKPOINT. 81 | * @set_hw_breakpoint: Allow an architecture to specify how to set a hardware 82 | * breakpoint. 83 | * @remove_hw_breakpoint: Allow an architecture to specify how to remove a 84 | * hardware breakpoint. 85 | * @remove_all_hw_break: Allow an architecture to specify how to remove all 86 | * hardware breakpoints. 87 | */ 88 | struct gdb_arch { 89 | unsigned char gdb_bpt_instr[BREAK_INSTR_SIZE]; 90 | unsigned long flags; 91 | 92 | int (*set_hw_breakpoint)(unsigned long, int, enum gdb_bptype); 93 | int (*remove_hw_breakpoint)(unsigned long, int, enum gdb_bptype); 94 | void (*remove_all_hw_break)(void); 95 | }; 96 | /** 97 | * struct gdb_io - Describe the interface for an I/O driver to talk with KGDB. 98 | * @read_char: Pointer to a function that will return one char. 99 | * @write_char: Pointer to a function that will write one char. 100 | * @flush: Pointer to a function that will flush any pending writes. 101 | * @init: Pointer to a function that will initialize the device. 102 | */ 103 | struct gdb_io { 104 | int (*read_char) (void); 105 | void (*write_char) (char); 106 | void (*flush) (void); 107 | int (*init) (void); 108 | }; 109 | 110 | extern int gdb_connected; 111 | extern void* volatile gdb_mem_fault_handler; 112 | 113 | int gdb_hex2long(char **ptr, unsigned long *long_val); 114 | int gdb_mem2hex(char *mem, char *buf, int count); 115 | int gdb_hex2mem(char *buf, char *mem, int count); 116 | int gdb_ebin2mem(char *buf, char *mem, int count); 117 | int gdb_set_sw_break(unsigned long addr); 118 | int gdb_remove_sw_break(unsigned long addr); 119 | int gdb_isremovedbreak(unsigned long addr); 120 | void gdb_console_write(const char *s, unsigned count); 121 | int gdb_handle_exception(int signo, void *regs); 122 | 123 | /* hal */ 124 | extern struct gdb_io gdb_io_ops; 125 | extern rt_device_t gdb_dev; 126 | void gdb_start(); 127 | void gdb_set_device(const char* device_name); 128 | 129 | 130 | 131 | #endif /* __GDB_STUB_H__ */ 132 | -------------------------------------------------------------------------------- /components/gdb/hal_stub.c: -------------------------------------------------------------------------------- 1 | /* 2 | * I/O and interface portion of GDB stub 3 | * 4 | * File : hal_stub.c 5 | * This file is part of RT-Thread RTOS 6 | * COPYRIGHT (C) 2006, RT-Thread Develop Team 7 | * 8 | * The license and distribution terms for this file may be 9 | * found in the file LICENSE in this distribution or at 10 | * http://www.rt-thread.org/license/LICENSE 11 | * 12 | * Change Logs: 13 | * Date Author Notes 14 | * 2014-07-04 Wzyy2 first version 15 | */ 16 | #include 17 | #include 18 | #include "gdb_stub.h" 19 | 20 | #ifdef RT_USING_SERIAL 21 | #include 22 | #endif 23 | 24 | rt_device_t gdb_dev = RT_NULL; 25 | static struct rt_serial_device *gdb_serial; 26 | char gdb_io_set; 27 | 28 | void gdb_uart_putc(char c); 29 | int gdb_uart_getc(); 30 | 31 | 32 | /*if you want to use something instead of the serial,change it */ 33 | struct gdb_io gdb_io_ops = { 34 | gdb_uart_getc, 35 | gdb_uart_putc 36 | }; 37 | 38 | 39 | /** 40 | * @ingroup gdb_stub 41 | * 42 | * This function will get GDB stubs started, with a proper environment 43 | */ 44 | void gdb_start() 45 | { 46 | if (gdb_dev == RT_NULL) 47 | rt_kprintf("GDB: no gdb_dev found,please set it first\n"); 48 | else 49 | gdb_breakpoint(); 50 | } 51 | 52 | 53 | /** 54 | * @ingroup gdb_stub 55 | * 56 | * This function sets the input device of gdb_stub. 57 | * 58 | * @param device_name the name of new input device. 59 | */ 60 | void gdb_set_device(const char* device_name) 61 | { 62 | rt_device_t dev = RT_NULL; 63 | dev = rt_device_find(device_name); 64 | if(dev == RT_NULL){ 65 | rt_kprintf("GDB: can not find device: %s\n", device_name); 66 | return; 67 | } 68 | 69 | /* open this device and set the new device */ 70 | if (rt_device_open(dev, RT_DEVICE_OFLAG_RDWR) == RT_EOK) 71 | { 72 | gdb_dev = dev; 73 | gdb_serial = (struct rt_serial_device *)gdb_dev; 74 | } 75 | } 76 | 77 | void gdb_uart_putc(char c) 78 | { 79 | #ifdef RT_GDB_DEBUG 80 | rt_kprintf("%c",c); 81 | #endif 82 | rt_device_write(gdb_dev, 0, &c, 1); 83 | } 84 | 85 | /* polling */ 86 | int gdb_uart_getc() 87 | { 88 | int ch; 89 | 90 | #ifdef RT_USING_SERIAL 91 | ch = -1; 92 | do { 93 | ch = gdb_serial->ops->getc(gdb_serial); 94 | } while (ch == -1); 95 | #else 96 | rt_device_read(gdb_dev, 0, &ch, 1); 97 | #endif 98 | 99 | #ifdef RT_GDB_DEBUG 100 | rt_kprintf("%c",ch); 101 | #endif 102 | 103 | return ch; 104 | } 105 | 106 | -------------------------------------------------------------------------------- /components/gdb/libcpu/arm/arch_gdb.h: -------------------------------------------------------------------------------- 1 | /* 2 | * ARM GDB support 3 | * arch-specific portion of GDB stub 4 | * 5 | * File : arch_gdb.h(arm) 6 | * This file is part of RT-Thread RTOS 7 | * COPYRIGHT (C) 2006, RT-Thread Develop Team 8 | * 9 | * The license and distribution terms for this file may be 10 | * found in the file LICENSE in this distribution or at 11 | * http://www.rt-thread.org/license/LICENSE 12 | * 13 | * Change Logs: 14 | * Date Author Notes 15 | * 2014-07-04 wzyy2 first version 16 | */ 17 | #ifndef __ARM_GDB_H__ 18 | #define __ARM_GDB_H__ 19 | 20 | #include 21 | 22 | 23 | #ifndef RT_GDB_HAVE_HWBP 24 | #define RT_GDB_HAVE_HWBP 0 25 | #endif 26 | #ifndef RT_GDB_HAVE_SWBP 27 | #define RT_GDB_HAVE_SWBP 1 28 | #endif 29 | 30 | 31 | #if RT_GDB_HAVE_HWBP 32 | #error GDB:No hardware_breakpoint support 33 | #endif 34 | 35 | 36 | /* 37 | * By doing this as an undefined instruction trap, we force a mode 38 | * switch from SVC to UND mode, allowing us to save full kernel state. 39 | * We also define a GDB_COMPILED_BREAK which can be used to compile 40 | * in breakpoints. 41 | */ 42 | #define BREAK_INSTR_SIZE 4 43 | #define GDB_BREAKINST 0xe7ffdefe 44 | #define GDB_COMPILED_BREAK 0xe7ffdeff 45 | #define CACHE_FLUSH_IS_SAFE 1 46 | 47 | #define ARM_GP_REGS 16 48 | #define ARM_FP_REGS 8 49 | #define ARM_EXTRA_REGS 2 50 | #define GDB_MAX_REGS (ARM_GP_REGS + (ARM_FP_REGS * 3) + ARM_EXTRA_REGS) 51 | #define NUMREGBYTES (GDB_MAX_REGS << 2) 52 | 53 | 54 | //#define BUFMAX ((NUMREGBYTES << 1) + 10) 55 | #define BUFMAX 400 56 | 57 | enum regnames { 58 | GDB_R0, /*0*/ 59 | GDB_R1, /*1*/ 60 | GDB_R2, /*2*/ 61 | GDB_R3, /*3*/ 62 | GDB_R4, /*4*/ 63 | GDB_R5, /*5*/ 64 | GDB_R6, /*6*/ 65 | GDB_R7, /*7*/ 66 | GDB_R8, /*8*/ 67 | GDB_R9, /*9*/ 68 | GDB_R10, /*10*/ 69 | GDB_FP, /*11*/ 70 | GDB_IP, /*12*/ 71 | GDB_SPT, /*13*/ 72 | GDB_LR, /*14*/ 73 | GDB_PC, /*15*/ 74 | GDB_CPSR = GDB_MAX_REGS-1 75 | }; 76 | 77 | /* arch */ 78 | extern struct gdb_arch arch_gdb_ops; 79 | void gdb_breakpoint(); 80 | void gdb_get_register(unsigned long *gdb_regs); 81 | void gdb_put_register(unsigned long *gdb_regs); 82 | void gdb_set_register(void *hw_regs); 83 | int gdb_arch_handle_exception(char *remcom_in_buffer, 84 | char *remcom_out_buffer); 85 | void gdb_flush_icache_range(unsigned long start, unsigned long end); 86 | int gdb_undef_hook(void *regs); 87 | 88 | int gdb_handle_exception(int signo, void *regs); 89 | 90 | #endif /* __ARM_GDB_H__ */ 91 | -------------------------------------------------------------------------------- /components/gdb/libcpu/arm/arm_stub.c: -------------------------------------------------------------------------------- 1 | /* 2 | * ARM GDB support 3 | * arch-specific portion of GDB stub 4 | * 5 | * File : arm_stub.c 6 | * This file is part of RT-Thread RTOS 7 | * COPYRIGHT (C) 2006, RT-Thread Develop Team 8 | * 9 | * The license and distribution terms for this file may be 10 | * found in the file LICENSE in this distribution or at 11 | * http://www.rt-thread.org/license/LICENSE 12 | * 13 | * Change Logs: 14 | * Date Author Notes 15 | * 2014-07-04 Wzyy2 first version 16 | */ 17 | #include 18 | #include 19 | #include 20 | #include 21 | 22 | #define PS_N 0x80000000 23 | #define PS_Z 0x40000000 24 | #define PS_C 0x20000000 25 | #define PS_V 0x10000000 26 | 27 | #define IS_THUMB_ADDR(addr) ((addr) & 1) 28 | #define MAKE_THUMB_ADDR(addr) ((addr) | 1) 29 | #define UNMAKE_THUMB_ADDR(addr) ((addr) & ~1) 30 | 31 | static int compiled_break = 0; 32 | static unsigned long step_addr = 0; 33 | static int ins_will_execute(unsigned long ins); 34 | static unsigned long target_ins(unsigned long *pc, unsigned long ins); 35 | 36 | 37 | /*struct gdb_arch - Describe architecture specific values.*/ 38 | struct gdb_arch arch_gdb_ops = { 39 | .gdb_bpt_instr = {0xfe, 0xde, 0xff, 0xe7} //Little-Endian 40 | }; 41 | 42 | struct rt_gdb_register 43 | { 44 | rt_uint32_t r0; 45 | rt_uint32_t r1; 46 | rt_uint32_t r2; 47 | rt_uint32_t r3; 48 | rt_uint32_t r4; 49 | rt_uint32_t r5; 50 | rt_uint32_t r6; 51 | rt_uint32_t r7; 52 | rt_uint32_t r8; 53 | rt_uint32_t r9; 54 | rt_uint32_t r10; 55 | rt_uint32_t fp; 56 | rt_uint32_t ip; 57 | rt_uint32_t sp; 58 | rt_uint32_t lr; 59 | rt_uint32_t pc; 60 | rt_uint32_t cpsr; 61 | rt_uint32_t ORIG_r0; 62 | }*regs; 63 | 64 | /** 65 | * gdb_breakpoint - generate a compiled_breadk 66 | * It is used to sync up with a debugger and stop progarm 67 | */ 68 | void gdb_breakpoint() 69 | { 70 | asm(".word 0xe7ffdeff"); 71 | } 72 | 73 | void gdb_set_register(void *hw_regs) 74 | { 75 | regs = (struct rt_gdb_register *)hw_regs; 76 | } 77 | void gdb_get_register(unsigned long *gdb_regs) 78 | { 79 | int regno; 80 | /* Initialize all to zero. */ 81 | for (regno = 0; regno < GDB_MAX_REGS; regno++) 82 | gdb_regs[regno] = 0; 83 | 84 | gdb_regs[GDB_R0] = regs->r0; 85 | gdb_regs[GDB_R1] = regs->r1; 86 | gdb_regs[GDB_R2] = regs->r2; 87 | gdb_regs[GDB_R3] = regs->r3; 88 | gdb_regs[GDB_R4] = regs->r4; 89 | gdb_regs[GDB_R5] = regs->r5; 90 | gdb_regs[GDB_R6] = regs->r6; 91 | gdb_regs[GDB_R7] = regs->r7; 92 | gdb_regs[GDB_R8] = regs->r8; 93 | gdb_regs[GDB_R9] = regs->r9; 94 | gdb_regs[GDB_R10] = regs->r10; 95 | gdb_regs[GDB_FP] = regs->fp; 96 | gdb_regs[GDB_IP] = regs->ip; 97 | gdb_regs[GDB_SPT] = regs->sp; 98 | gdb_regs[GDB_LR] = regs->lr; 99 | gdb_regs[GDB_PC] = regs->pc; 100 | gdb_regs[GDB_CPSR] = regs->cpsr; 101 | 102 | }; 103 | 104 | 105 | void gdb_put_register(unsigned long *gdb_regs) 106 | { 107 | regs->r0 = gdb_regs[GDB_R0]; 108 | regs->r1 = gdb_regs[GDB_R1]; 109 | regs->r2 = gdb_regs[GDB_R2]; 110 | regs->r3 = gdb_regs[GDB_R3]; 111 | regs->r4 = gdb_regs[GDB_R4]; 112 | regs->r5 = gdb_regs[GDB_R5]; 113 | regs->r6 = gdb_regs[GDB_R6]; 114 | regs->r7 = gdb_regs[GDB_R7]; 115 | regs->r8 = gdb_regs[GDB_R8]; 116 | regs->r9 = gdb_regs[GDB_R9]; 117 | regs->r10 = gdb_regs[GDB_R10]; 118 | regs->fp = gdb_regs[GDB_FP]; 119 | regs->ip = gdb_regs[GDB_IP]; 120 | regs->sp = gdb_regs[GDB_SPT]; 121 | regs->lr = gdb_regs[GDB_LR]; 122 | regs->pc = gdb_regs[GDB_PC]; 123 | regs->cpsr = gdb_regs[GDB_CPSR]; 124 | } 125 | 126 | 127 | /* It will be called during process_packet */ 128 | int gdb_arch_handle_exception(char *remcom_in_buffer, 129 | char *remcom_out_buffer) 130 | { 131 | unsigned long addr,curins; 132 | char *ptr; 133 | 134 | /*clear single step*/ 135 | if (step_addr) { 136 | gdb_remove_sw_break(step_addr); 137 | step_addr = 0; 138 | } 139 | 140 | switch (remcom_in_buffer[0]) { 141 | case 'D': 142 | case 'k': 143 | case 'c': 144 | /* 145 | * If this was a compiled breakpoint, we need to move 146 | * to the next instruction or we will breakpoint 147 | * over and over again 148 | */ 149 | ptr = &remcom_in_buffer[1]; 150 | if (gdb_hex2long(&ptr, &addr)) 151 | regs->pc = addr; 152 | else if (compiled_break == 1) 153 | regs->pc += 4; 154 | compiled_break = 0; 155 | return 0; 156 | 157 | case 's': 158 | ptr = &remcom_in_buffer[1]; 159 | if (gdb_hex2long(&ptr, &addr)) 160 | regs->pc = addr; 161 | 162 | curins = *(unsigned long*)(regs->pc); 163 | if (ins_will_execute(curins)) 164 | //Decode instruction to decide what the next pc will be 165 | step_addr = target_ins((unsigned long *)regs->pc, curins); 166 | else 167 | step_addr = regs->pc + 4; 168 | 169 | #ifdef RT_GDB_DEBUG 170 | rt_kprintf("\n next will be %x \n",step_addr); 171 | #endif 172 | gdb_set_sw_break(step_addr); 173 | 174 | if (compiled_break == 1) 175 | regs->pc += 4; 176 | compiled_break = 0; 177 | return 0; 178 | } 179 | 180 | return -1; 181 | 182 | } 183 | 184 | /* flush icache to let the sw breakpoint working */ 185 | void gdb_flush_icache_range(unsigned long start, unsigned long end) 186 | { 187 | #ifdef RT_GDB_ICACHE 188 | extern void mmu_invalidate_icache(); 189 | mmu_invalidate_icache(); //for arm,wo can only invalidate it 190 | #endif 191 | } 192 | 193 | /* register a hook in undef*/ 194 | int gdb_undef_hook(void *regs) 195 | { 196 | struct rt_gdb_register *tmp_reg = (struct rt_gdb_register *)regs; 197 | unsigned long *tmp_pc = (unsigned long *)tmp_reg->pc; 198 | 199 | /* it is a compiled break */ 200 | if (*tmp_pc == GDB_COMPILED_BREAK) { 201 | compiled_break = 1; 202 | gdb_handle_exception(SIGTRAP, regs); 203 | return 1; 204 | 205 | } 206 | /* it is a sw break */ 207 | else if (*tmp_pc == GDB_BREAKINST) { 208 | gdb_handle_exception(SIGTRAP, regs); 209 | return 1; 210 | } 211 | /*or we just go */ 212 | return 0; 213 | 214 | } 215 | 216 | static unsigned long gdb_arch_regs[GDB_MAX_REGS]; 217 | static int ins_will_execute(unsigned long ins) 218 | { 219 | unsigned long psr = regs->cpsr; // condition codes 220 | int res = 0; 221 | switch ((ins & 0xF0000000) >> 28) { 222 | case 0x0: // EQ 223 | res = (psr & PS_Z) != 0; 224 | break; 225 | case 0x1: // NE 226 | res = (psr & PS_Z) == 0; 227 | break; 228 | case 0x2: // CS 229 | res = (psr & PS_C) != 0; 230 | break; 231 | case 0x3: // CC 232 | res = (psr & PS_C) == 0; 233 | break; 234 | case 0x4: // MI 235 | res = (psr & PS_N) != 0; 236 | break; 237 | case 0x5: // PL 238 | res = (psr & PS_N) == 0; 239 | break; 240 | case 0x6: // VS 241 | res = (psr & PS_V) != 0; 242 | break; 243 | case 0x7: // VC 244 | res = (psr & PS_V) == 0; 245 | break; 246 | case 0x8: // HI 247 | res = ((psr & PS_C) != 0) && ((psr & PS_Z) == 0); 248 | break; 249 | case 0x9: // LS 250 | res = ((psr & PS_C) == 0) || ((psr & PS_Z) != 0); 251 | break; 252 | case 0xA: // GE 253 | res = ((psr & (PS_N|PS_V)) == (PS_N|PS_V)) || 254 | ((psr & (PS_N|PS_V)) == 0); 255 | break; 256 | case 0xB: // LT 257 | res = ((psr & (PS_N|PS_V)) == PS_N) || 258 | ((psr & (PS_N|PS_V)) == PS_V); 259 | break; 260 | case 0xC: // GT 261 | res = ((psr & (PS_N|PS_V)) == (PS_N|PS_V)) || 262 | ((psr & (PS_N|PS_V)) == 0); 263 | res = ((psr & PS_Z) == 0) && res; 264 | break; 265 | case 0xD: // LE 266 | res = ((psr & (PS_N|PS_V)) == PS_N) || 267 | ((psr & (PS_N|PS_V)) == PS_V); 268 | res = ((psr & PS_Z) == PS_Z) || res; 269 | break; 270 | case 0xE: // AL 271 | res = 1; 272 | break; 273 | case 0xF: // NV 274 | if (((ins & 0x0E000000) >> 24) == 0xA) 275 | res = 1; 276 | else 277 | res = 0; 278 | break; 279 | } 280 | return res; 281 | } 282 | 283 | static unsigned long RmShifted(int shift) 284 | { 285 | unsigned long Rm = gdb_arch_regs[shift & 0x00F]; 286 | int shift_count; 287 | if ((shift & 0x010) == 0) { 288 | shift_count = (shift & 0xF80) >> 7; 289 | } else { 290 | shift_count = gdb_arch_regs[(shift & 0xF00) >> 8]; 291 | } 292 | switch ((shift & 0x060) >> 5) { 293 | case 0x0: // Logical left 294 | Rm <<= shift_count; 295 | break; 296 | case 0x1: // Logical right 297 | Rm >>= shift_count; 298 | break; 299 | case 0x2: // Arithmetic right 300 | Rm = (unsigned long)((long)Rm >> shift_count); 301 | break; 302 | case 0x3: // Rotate right 303 | if (shift_count == 0) { 304 | // Special case, RORx 305 | Rm >>= 1; 306 | if (gdb_arch_regs[GDB_CPSR] & PS_C) Rm |= 0x80000000; 307 | } else { 308 | Rm = (Rm >> shift_count) | (Rm << (32-shift_count)); 309 | } 310 | break; 311 | } 312 | return Rm; 313 | } 314 | 315 | // Decide the next instruction to be executed for a given instruction 316 | static unsigned long target_ins(unsigned long *pc, unsigned long ins) 317 | { 318 | unsigned long new_pc, offset, op2; 319 | unsigned long Rn; 320 | int i, reg_count, c; 321 | 322 | gdb_get_register(gdb_arch_regs); 323 | 324 | switch ((ins & 0x0C000000) >> 26) { 325 | case 0x0: 326 | // BX or BLX 327 | if ((ins & 0x0FFFFFD0) == 0x012FFF10) { 328 | new_pc = (unsigned long)gdb_arch_regs[ins & 0x0000000F]; 329 | return new_pc; 330 | } 331 | // Data processing 332 | new_pc = (unsigned long)(pc+1); 333 | if ((ins & 0x0000F000) == 0x0000F000) { 334 | // Destination register is PC 335 | if ((ins & 0x0FBF0000) != 0x010F0000) { 336 | Rn = (unsigned long)gdb_arch_regs[(ins & 0x000F0000) >> 16]; 337 | if ((ins & 0x000F0000) == 0x000F0000) Rn += 8; // PC prefetch! 338 | if ((ins & 0x02000000) == 0) { 339 | op2 = RmShifted(ins & 0x00000FFF); 340 | } else { 341 | op2 = ins & 0x000000FF; 342 | i = (ins & 0x00000F00) >> 8; // Rotate count 343 | op2 = (op2 >> (i*2)) | (op2 << (32-(i*2))); 344 | } 345 | switch ((ins & 0x01E00000) >> 21) { 346 | case 0x0: // AND 347 | new_pc = Rn & op2; 348 | break; 349 | case 0x1: // EOR 350 | new_pc = Rn ^ op2; 351 | break; 352 | case 0x2: // SUB 353 | new_pc = Rn - op2; 354 | break; 355 | case 0x3: // RSB 356 | new_pc = op2 - Rn; 357 | break; 358 | case 0x4: // ADD 359 | new_pc = Rn + op2; 360 | break; 361 | case 0x5: // ADC 362 | c = (gdb_arch_regs[GDB_CPSR] & PS_C) != 0; 363 | new_pc = Rn + op2 + c; 364 | break; 365 | case 0x6: // SBC 366 | c = (gdb_arch_regs[GDB_CPSR] & PS_C) != 0; 367 | new_pc = Rn - op2 + c - 1; 368 | break; 369 | case 0x7: // RSC 370 | c = (gdb_arch_regs[GDB_CPSR] & PS_C) != 0; 371 | new_pc = op2 - Rn +c - 1; 372 | break; 373 | case 0x8: // TST 374 | case 0x9: // TEQ 375 | case 0xA: // CMP 376 | case 0xB: // CMN 377 | break; // PC doesn't change 378 | case 0xC: // ORR 379 | new_pc = Rn | op2; 380 | break; 381 | case 0xD: // MOV 382 | new_pc = op2; 383 | break; 384 | case 0xE: // BIC 385 | new_pc = Rn & ~op2; 386 | break; 387 | case 0xF: // MVN 388 | new_pc = ~op2; 389 | break; 390 | } 391 | } 392 | } 393 | return new_pc; 394 | case 0x1: 395 | if ((ins & 0x02000010) == 0x02000010) { 396 | // Undefined! 397 | return (unsigned long)(pc+1); 398 | } else { 399 | if ((ins & 0x00100000) == 0) { 400 | // STR 401 | return (unsigned long)(pc+1); 402 | } else { 403 | // LDR 404 | if ((ins & 0x0000F000) != 0x0000F000) { 405 | // Rd not PC 406 | return (unsigned long)(pc+1); 407 | } else { 408 | Rn = (unsigned long)gdb_arch_regs[(ins & 0x000F0000) >> 16]; 409 | if ((ins & 0x000F0000) == 0x000F0000) Rn += 8; // PC prefetch! 410 | if (ins & 0x01000000) { 411 | // Add/subtract offset before 412 | if ((ins & 0x02000000) == 0) { 413 | // Immediate offset 414 | if (ins & 0x00800000) { 415 | // Add offset 416 | Rn += (ins & 0x00000FFF); 417 | } else { 418 | // Subtract offset 419 | Rn -= (ins & 0x00000FFF); 420 | } 421 | } else { 422 | // Offset is in a register 423 | if (ins & 0x00800000) { 424 | // Add offset 425 | Rn += RmShifted(ins & 0x00000FFF); 426 | } else { 427 | // Subtract offset 428 | Rn -= RmShifted(ins & 0x00000FFF); 429 | } 430 | } 431 | } 432 | return *(unsigned long *)Rn; 433 | } 434 | } 435 | } 436 | return (unsigned long)(pc+1); 437 | case 0x2: // Branch, LDM/STM 438 | if ((ins & 0x02000000) == 0) { 439 | // LDM/STM 440 | if ((ins & 0x00100000) == 0) { 441 | // STM 442 | return (unsigned long)(pc+1); 443 | } else { 444 | // LDM 445 | if ((ins & 0x00008000) == 0) { 446 | // PC not in list 447 | return (unsigned long)(pc+1); 448 | } else { 449 | Rn = (unsigned long)gdb_arch_regs[(ins & 0x000F0000) >> 16]; 450 | if ((ins & 0x000F0000) == 0x000F0000) Rn += 8; // PC prefetch! 451 | offset = ins & 0x0000FFFF; 452 | reg_count = 0; 453 | for (i = 0; i < 15; i++) { 454 | if (offset & (1< 21 | 22 | #ifndef RT_GDB_HAVE_HWBP 23 | #define RT_GDB_HAVE_HWBP 1 24 | #endif 25 | #ifndef RT_GDB_HAVE_SWBP 26 | #define RT_GDB_HAVE_SWBP 0 27 | #endif 28 | 29 | #ifndef GDB_CORTEXM_PRIORITY_MAX 30 | #define GDB_CORTEXM_PRIORITY_MAX (1 << 6) 31 | #endif 32 | 33 | #define GDB_DATA_ACCESS 34 | 35 | #define BREAK_INSTR_SIZE 4 36 | #define ARM_GP_REGS 16 37 | #define ARM_FP_REGS 8 38 | #define ARM_EXTRA_REGS 2 39 | #define GDB_MAX_REGS (ARM_GP_REGS + (ARM_FP_REGS * 3) + ARM_EXTRA_REGS) 40 | #define NUMREGBYTES (GDB_MAX_REGS << 2) 41 | 42 | #define HBP_NUM 6 //Max hardware breakpoint 43 | #define HWP_NUM 4 //Max hardware watchpoint 44 | 45 | //#define BUFMAX ((NUMREGBYTES << 1) + 10) 46 | #define BUFMAX 400 47 | 48 | #define GDB_DEBUG_REG_BASE 0xE000EDF0 49 | #define GDB_DEBUG_REG_DHSR 0x00 50 | #define GDB_DEBUG_REG_DCRSR 0x04 51 | #define GDB_DEBUG_REG_DCRDR 0x08 52 | #define GDB_DEBUG_REG_DEMCR 0x0c 53 | 54 | #define GDB_DEBUG_REG_DEMCR_MON_EN (1UL << 16) 55 | #define GDB_DEBUG_REG_DEMCR_MON_PEND (1UL << 17) 56 | #define GDB_DEBUG_REG_DEMCR_MON_STEP (1UL << 18) 57 | #define GDB_DEBUG_REG_DEMCR_TRCENA (1UL << 24) 58 | 59 | #define GDB_NVIC_REG_BASE 0xE000E000 60 | #define GDB_NVIC_REG_SHCSR 0xD24 61 | #define GDB_NVIC_REG_DFSR 0xD30 62 | 63 | #define GDB_NVIC_REG_SHCSR_MEMFAULTENA (1 << 16) 64 | 65 | #define GDB_FPB_REG_BASE 0xE0002000 66 | #define GDB_FPB_REG_CTRL 0x0 67 | #define GDB_FPB_REG_REMAP 0x4 68 | #define GDB_FPB_REG_COMP 0x8 69 | 70 | #define GDB_FPB_REG_CTRL_KEY (1UL << 1) 71 | #define GDB_FPB_REG_CTRL_ENABLE 1 72 | #define GDB_FPB_REG_COMP_ENABLE 1 73 | #define GDB_FPB_REG_COMP_ADDR (((1UL << 29) -1) << 2) 74 | #define GDB_FPB_REG_COMP_REPLACE (((1UL << 32) -1) << 30) 75 | 76 | #define GDB_DWT_REG_BASE 0xE0001000 77 | #define GDB_DWT_REG_CTRL 0x0 78 | #define GDB_DWT_REG_COMP 0x20 79 | #define GDB_DWT_REG_MASK 0x24 80 | #define GDB_DWT_REG_FUNCTION 0x28 81 | 82 | #define GDB_DWT_REG_FUNCTION_FUC (((1UL << 4) -1) << 0) 83 | 84 | 85 | 86 | 87 | enum regnames { 88 | GDB_R0, /*0*/ 89 | GDB_R1, /*1*/ 90 | GDB_R2, /*2*/ 91 | GDB_R3, /*3*/ 92 | GDB_R4, /*4*/ 93 | GDB_R5, /*5*/ 94 | GDB_R6, /*6*/ 95 | GDB_R7, /*7*/ 96 | GDB_R8, /*8*/ 97 | GDB_R9, /*9*/ 98 | GDB_R10, /*10*/ 99 | GDB_FP, /*11*/ 100 | GDB_IP, /*12*/ 101 | GDB_SPT, /*13*/ 102 | GDB_LR, /*14*/ 103 | GDB_PC, /*15*/ 104 | GDB_F0, /*16*/ 105 | GDB_F1, /*17*/ 106 | GDB_F2, /*18*/ 107 | GDB_F3, /*19*/ 108 | GDB_F4, /*20*/ 109 | GDB_F5, /*21*/ 110 | GDB_F6, /*22*/ 111 | GDB_F7, /*23*/ 112 | GDB_FPS, /*24*/ 113 | GDB_CPSR = GDB_MAX_REGS-1 114 | }; 115 | 116 | typedef struct 117 | { 118 | unsigned long type; // State type 119 | unsigned long vector; // Exception vector number 120 | unsigned long basepri; // BASEPRI 121 | 122 | unsigned long r4; // Remaining CPU registers 123 | unsigned long r5; // Remaining CPU registers 124 | unsigned long r6; // Remaining CPU registers 125 | unsigned long r7; // Remaining CPU registers 126 | unsigned long r8; // Remaining CPU registers 127 | unsigned long r9; // Remaining CPU registers 128 | unsigned long r10; // Remaining CPU registers 129 | unsigned long r11; // Remaining CPU registers 130 | unsigned long sp; // Remaining CPU registers 131 | 132 | unsigned long xlr; // Exception return LR 133 | // The following are saved and restored automatically by the CPU 134 | // for exceptions or interrupts. 135 | unsigned long r0; 136 | unsigned long r1; 137 | unsigned long r2; 138 | unsigned long r3; 139 | unsigned long r12; 140 | unsigned long lr; 141 | unsigned long pc; 142 | unsigned long psr; 143 | } Gdb_SavedRegisters; 144 | 145 | /* arch */ 146 | extern struct gdb_arch arch_gdb_ops; 147 | void gdb_breakpoint(); 148 | void gdb_get_register(unsigned long *gdb_regs); 149 | void gdb_put_register(unsigned long *gdb_regs); 150 | void gdb_set_register(void *hw_regs); 151 | int gdb_arch_handle_exception(char *remcom_in_buffer, 152 | char *remcom_out_buffer); 153 | 154 | int gdb_permit_data_access(unsigned long addr, unsigned long count); 155 | void gdb_arch_exit(); 156 | void gdb_arch_late(); 157 | 158 | #endif /* __CORTEXM_GDB_H__ */ 159 | -------------------------------------------------------------------------------- /components/gdb/libcpu/cortexm/cortexm_stub.c: -------------------------------------------------------------------------------- 1 | /* 2 | * CORTEXM GDB support 3 | * arch-specific portion of GDB stub 4 | * 5 | * File : cortexm_stub.c 6 | * This file is part of RT-Thread RTOS 7 | * COPYRIGHT (C) 2006, RT-Thread Develop Team 8 | * 9 | * The license and distribution terms for this file may be 10 | * found in the file LICENSE in this distribution or at 11 | * http://www.rt-thread.org/license/LICENSE 12 | * 13 | * Change Logs: 14 | * Date Author Notes 15 | * 2014-07-04 Wzyy2 first version 16 | */ 17 | #include 18 | #include 19 | #include 20 | 21 | static Gdb_SavedRegisters *regs; 22 | unsigned long single_step_basepri = 0; 23 | 24 | void gdb_remove_all_hw_break(); 25 | void gdb_enable_hw_debug(); 26 | void gdb_disable_hw_debug(); 27 | int gdb_set_hw_break(unsigned long, int, enum gdb_bptype); 28 | int gdb_remove_hw_break(unsigned long, int, enum gdb_bptype); 29 | 30 | /*struct gdb_arch - Describe architecture specific values.*/ 31 | struct gdb_arch arch_gdb_ops = { 32 | /* Breakpoint instruction: */ 33 | .gdb_bpt_instr = {0xfe, 0xde, 0xff, 0xe7}, //Little-Endian 34 | .flags = RT_GDB_HAVE_HWBP, 35 | .set_hw_breakpoint = gdb_set_hw_break, 36 | .remove_hw_breakpoint = gdb_remove_hw_break, 37 | .remove_all_hw_break = gdb_remove_all_hw_break 38 | }; 39 | 40 | static struct hw_breakpoint { 41 | int enabled; 42 | unsigned long addr; 43 | } breakinfo[HBP_NUM]; 44 | 45 | static struct hw_watchpoint { 46 | int enabled; 47 | unsigned long addr; 48 | int len; 49 | enum gdb_bptype type; 50 | } watchinfo[HWP_NUM]; 51 | 52 | //The following table defines the memory areas that GDB is allow to touch 53 | static const struct { 54 | unsigned long start; 55 | unsigned long end; 56 | } data_access[] = 57 | { 58 | { 0x20000000, 0x40000000-1}, // On-chip ram 59 | { 0x60000000, 0xa0000000-1}, // External ram 60 | { 0x00000000, 0x20000000-1}, // On-chip flash 61 | { 0x60000000, 0xa0000000-1}, // External flash 62 | { 0xE0000000, 0x00000000-1}, // cortex-M peripheral 63 | { 0x40000000, 0x60000000-1}, // mcu peripheral 64 | }; 65 | 66 | 67 | int gdb_permit_data_access(unsigned long addr, unsigned long count) 68 | { 69 | unsigned char i; 70 | 71 | for (i = 0; i < sizeof(data_access)/sizeof(data_access[0]); i++) { 72 | if ((addr >= data_access[i].start) && (addr + count) <= data_access[i].end) { 73 | return 0; 74 | } 75 | } 76 | 77 | return -1; 78 | } 79 | 80 | /*we need to block all pending interrupts by swtting basepri 81 | * before doing the steo 82 | */ 83 | void gdb_single_step() 84 | { 85 | volatile unsigned long *base; 86 | 87 | //mask all interrupts 88 | single_step_basepri = regs->basepri; 89 | regs->basepri = GDB_CORTEXM_PRIORITY_MAX; 90 | 91 | //When MON_EN = 1, this steps the core 92 | base = (unsigned long*)(GDB_DEBUG_REG_BASE + GDB_DEBUG_REG_DEMCR); 93 | *base |= GDB_DEBUG_REG_DEMCR_MON_STEP; 94 | 95 | /* Clear any bits set in DFSR*/ 96 | base = (unsigned long*)(GDB_NVIC_REG_BASE + GDB_NVIC_REG_DFSR); 97 | *base = 0xffffffff; 98 | 99 | } 100 | 101 | void gdb_clear_single_step() 102 | { 103 | volatile unsigned long *base; 104 | 105 | regs->basepri = single_step_basepri; 106 | 107 | /*clear single step*/ 108 | base = (unsigned long*)(GDB_DEBUG_REG_BASE + GDB_DEBUG_REG_DEMCR); 109 | *base &= ~GDB_DEBUG_REG_DEMCR_MON_STEP; 110 | 111 | // Clear any bits set in DFSR 112 | base = (unsigned long*)(GDB_NVIC_REG_BASE + GDB_NVIC_REG_DFSR); 113 | *base = 0xffffffff; 114 | 115 | } 116 | 117 | /** 118 | * gdb_breakpoint - generate a breadk 119 | * It is used to sync up with a debugger and stop progarm 120 | */ 121 | void gdb_breakpoint() 122 | { 123 | volatile unsigned long *base; 124 | 125 | // Enable the FPB-FLASH PATCH BREAKPOINT 126 | base = (unsigned long*)(GDB_FPB_REG_BASE + GDB_FPB_REG_CTRL); 127 | *base |= GDB_FPB_REG_CTRL_KEY | GDB_FPB_REG_CTRL_ENABLE ; 128 | 129 | base = (unsigned long*)(GDB_DEBUG_REG_BASE + GDB_DEBUG_REG_DEMCR); 130 | /* 131 | * Enable the debug monitor. When enabled, the System handler priority 132 | * register controls its priority level. 133 | * If disabled, then all debug events go 134 | * to Hard fault 135 | */ 136 | *base |= GDB_DEBUG_REG_DEMCR_MON_EN; 137 | 138 | // Enable DWT 139 | *base |= GDB_DEBUG_REG_DEMCR_TRCENA ; 140 | 141 | //Fall into debug monitor 142 | *base |= GDB_DEBUG_REG_DEMCR_MON_PEND; 143 | 144 | } 145 | 146 | void gdb_set_register(void *hw_regs) 147 | { 148 | regs = hw_regs; 149 | } 150 | 151 | void gdb_get_register(unsigned long *gdb_regs) 152 | { 153 | int regno; 154 | /* Initialize all to zero. */ 155 | for (regno = 0; regno < GDB_MAX_REGS; regno++) 156 | gdb_regs[regno] = 0; 157 | 158 | gdb_regs[GDB_R0] = regs->r0; 159 | gdb_regs[GDB_R1] = regs->r1; 160 | gdb_regs[GDB_R2] = regs->r2; 161 | gdb_regs[GDB_R3] = regs->r3; 162 | gdb_regs[GDB_R4] = regs->r4; 163 | gdb_regs[GDB_R5] = regs->r5; 164 | gdb_regs[GDB_R6] = regs->r6; 165 | gdb_regs[GDB_R7] = regs->r7; 166 | gdb_regs[GDB_R8] = regs->r8; 167 | gdb_regs[GDB_R9] = regs->r9; 168 | gdb_regs[GDB_R10] = regs->r10; 169 | gdb_regs[GDB_FP] = regs->r11; 170 | gdb_regs[GDB_IP] = regs->r12; 171 | gdb_regs[GDB_SPT] = regs->sp; 172 | gdb_regs[GDB_LR] = regs->lr; 173 | gdb_regs[GDB_PC] = regs->pc; 174 | gdb_regs[GDB_CPSR] = regs->psr; 175 | 176 | }; 177 | 178 | 179 | void gdb_put_register(unsigned long *gdb_regs) 180 | { 181 | regs->r0 = gdb_regs[GDB_R0]; 182 | regs->r1 = gdb_regs[GDB_R1]; 183 | regs->r2 = gdb_regs[GDB_R2]; 184 | regs->r3 = gdb_regs[GDB_R3]; 185 | 186 | regs->r4 = gdb_regs[GDB_R4]; 187 | regs->r5 = gdb_regs[GDB_R5]; 188 | regs->r6 = gdb_regs[GDB_R6]; 189 | regs->r7 = gdb_regs[GDB_R7]; 190 | regs->r8 = gdb_regs[GDB_R8]; 191 | regs->r9 = gdb_regs[GDB_R9]; 192 | regs->r10 = gdb_regs[GDB_R10]; 193 | regs->r11 = gdb_regs[GDB_FP]; 194 | regs->r12 = gdb_regs[GDB_IP]; 195 | regs->sp = gdb_regs[GDB_SPT]; 196 | regs->lr = gdb_regs[GDB_LR]; 197 | regs->pc = gdb_regs[GDB_PC]; 198 | regs->psr = gdb_regs[GDB_CPSR]; 199 | 200 | } 201 | 202 | 203 | /* It will be called during process_packet */ 204 | int gdb_arch_handle_exception(char *remcom_in_buffer, 205 | char *remcom_out_buffer) 206 | { 207 | unsigned long addr; 208 | char *ptr; 209 | static int step = 0; 210 | 211 | if (step){ 212 | gdb_clear_single_step(); 213 | step = 0; 214 | } 215 | 216 | switch (remcom_in_buffer[0]) { 217 | case 'D': 218 | case 'k': 219 | case 'c': 220 | /* 221 | * If this was a compiled breakpoint, we need to move 222 | * to the next instruction or we will breakpoint 223 | * over and over again 224 | */ 225 | ptr = &remcom_in_buffer[1]; 226 | if (gdb_hex2long(&ptr, &addr)) 227 | regs->pc = addr; 228 | 229 | return 0; 230 | case 's': 231 | ptr = &remcom_in_buffer[1]; 232 | if (gdb_hex2long(&ptr, &addr)) 233 | regs->pc = addr; 234 | 235 | gdb_single_step(); 236 | step = 1; 237 | 238 | return 0; 239 | } 240 | 241 | return -1; 242 | 243 | } 244 | 245 | int gdb_set_hw_break(unsigned long addr, int len, enum gdb_bptype bptype) 246 | { 247 | int i; 248 | 249 | if (bptype == BP_HARDWARE_BREAKPOINT) { 250 | for (i = 0; i < HBP_NUM; i++) 251 | if (!breakinfo[i].enabled) 252 | break; 253 | if (i == HBP_NUM) 254 | return -1; 255 | breakinfo[i].addr = addr; 256 | breakinfo[i].enabled = 1; 257 | } 258 | else if (bptype == BP_WRITE_WATCHPOINT) { 259 | for (i = 0; i < HWP_NUM; i++) 260 | if (!watchinfo[i].enabled) 261 | break; 262 | if (i == HWP_NUM) 263 | return -1; 264 | watchinfo[i].addr = addr; 265 | watchinfo[i].len = len; 266 | watchinfo[i].type = BP_WRITE_WATCHPOINT; 267 | watchinfo[i].enabled = 1; 268 | } 269 | else if (bptype == BP_READ_WATCHPOINT) { 270 | for (i = 0; i < HWP_NUM; i++) 271 | if (!watchinfo[i].enabled) 272 | break; 273 | if (i == HWP_NUM) 274 | return -1; 275 | watchinfo[i].addr = addr; 276 | watchinfo[i].len = len; 277 | watchinfo[i].type = BP_READ_WATCHPOINT; 278 | watchinfo[i].enabled = 1; 279 | } 280 | else if (bptype == BP_ACCESS_WATCHPOINT) { 281 | for (i = 0; i < HWP_NUM; i++) 282 | if (!watchinfo[i].enabled) 283 | break; 284 | if (i == HWP_NUM) 285 | return -1; 286 | watchinfo[i].addr = addr; 287 | watchinfo[i].len = len; 288 | watchinfo[i].type = BP_ACCESS_WATCHPOINT; 289 | watchinfo[i].enabled = 1; 290 | } 291 | 292 | return 0; 293 | } 294 | 295 | int gdb_remove_hw_break(unsigned long addr, int len, enum gdb_bptype bptype) 296 | { 297 | int i; 298 | 299 | if (bptype == BP_HARDWARE_BREAKPOINT) { 300 | for (i = 0; i < HBP_NUM; i++) 301 | if (breakinfo[i].addr == addr && breakinfo[i].enabled) 302 | break; 303 | if (i == HBP_NUM) 304 | return -1; 305 | breakinfo[i].enabled = 0; 306 | 307 | } 308 | else if (bptype == BP_WRITE_WATCHPOINT) { 309 | for (i = 0; i < HWP_NUM; i++) 310 | if (watchinfo[i].addr == addr && watchinfo[i].enabled && watchinfo[i].type == bptype) 311 | break; 312 | if (i == HWP_NUM) 313 | return -1; 314 | watchinfo[i].enabled = 0; 315 | 316 | } 317 | else if (bptype == BP_READ_WATCHPOINT) { 318 | for (i = 0; i < HWP_NUM; i++) 319 | if (watchinfo[i].addr == addr && watchinfo[i].enabled && watchinfo[i].type == bptype) 320 | break; 321 | if (i == HWP_NUM) 322 | return -1; 323 | watchinfo[i].enabled = 0; 324 | 325 | } 326 | else if (bptype == BP_ACCESS_WATCHPOINT) { 327 | for (i = 0; i < HWP_NUM; i++) 328 | if (watchinfo[i].addr == addr && watchinfo[i].enabled && watchinfo[i].type == bptype) 329 | break; 330 | if (i == HWP_NUM) 331 | return -1; 332 | watchinfo[i].enabled = 0; 333 | 334 | } 335 | 336 | return 0; 337 | } 338 | 339 | void gdb_remove_all_hw_break() 340 | { 341 | int i; 342 | volatile unsigned long *base; 343 | 344 | // Disable hardware break 345 | for (i = 0; i < HBP_NUM; i++) { 346 | if (!breakinfo[i].enabled) 347 | break; 348 | base = (unsigned long*)(GDB_FPB_REG_BASE + GDB_FPB_REG_COMP + i * 4); 349 | *base &= ~GDB_FPB_REG_COMP_ENABLE ; 350 | } 351 | 352 | // Disable watchpoint 353 | for (i = 0; i < HWP_NUM; i++) { 354 | if (!watchinfo[i].enabled) 355 | break; 356 | base = (unsigned long*)(GDB_DWT_REG_BASE + GDB_DWT_REG_FUNCTION + i * 12); 357 | *base &= ~GDB_DWT_REG_FUNCTION_FUC ; 358 | } 359 | 360 | } 361 | 362 | void gdb_arch_late() 363 | { 364 | gdb_remove_all_hw_break(); 365 | } 366 | 367 | void gdb_arch_exit() 368 | { 369 | volatile unsigned long *base; 370 | char num = 1; 371 | int i; 372 | 373 | // Install the hardware break 374 | for (i = 0; i < HBP_NUM; i++) { 375 | if (breakinfo[i].enabled) { 376 | base = (unsigned long*)(GDB_FPB_REG_BASE + GDB_FPB_REG_COMP + i * 4); 377 | 378 | *base = GDB_FPB_REG_COMP_ADDR & ((unsigned long)(breakinfo[i].addr)); 379 | 380 | if (breakinfo[i].addr & 2) 381 | *base |= (1UL << 31); //set BKPT on upper halfword 382 | else 383 | *base |= (1UL << 30); //set BKPT on lower halfword, 384 | 385 | *base |= GDB_FPB_REG_COMP_ENABLE ; 386 | } 387 | } 388 | 389 | // Install the watchpoint 390 | for (i = 0; i < HWP_NUM; i++) { 391 | if (watchinfo[i].enabled) { 392 | base = (unsigned long*)(GDB_DWT_REG_BASE + GDB_DWT_REG_COMP + i * 12); 393 | *base = watchinfo[i].addr; 394 | 395 | base = (unsigned long*)(GDB_DWT_REG_BASE + GDB_DWT_REG_MASK + i * 12); 396 | while (watchinfo[i].len >> num) { 397 | num++; 398 | } 399 | *base = num - 1; //DWT matching is performed as:(ADDR & (~0 << MASK)) == COMP 400 | 401 | base = (unsigned long*)(GDB_DWT_REG_BASE + GDB_DWT_REG_FUNCTION + i * 12); 402 | 403 | if (watchinfo[i].type == BP_WRITE_WATCHPOINT) 404 | *base = (*base & ~GDB_DWT_REG_FUNCTION_FUC) + 0x05; 405 | else if (watchinfo[i].type == BP_READ_WATCHPOINT) 406 | *base = (*base & ~GDB_DWT_REG_FUNCTION_FUC) + 0x06; 407 | else if (watchinfo[i].type == BP_ACCESS_WATCHPOINT) 408 | *base = (*base & ~GDB_DWT_REG_FUNCTION_FUC) + 0x07; 409 | 410 | } 411 | } 412 | 413 | } 414 | 415 | -------------------------------------------------------------------------------- /components/gdb/libcpu/cortexm/gdb_gcc.S: -------------------------------------------------------------------------------- 1 | .cpu cortex-m4 2 | .syntax unified 3 | .thumb 4 | .text 5 | 6 | .global DebugMon_Handler 7 | .type DebugMon_Handler, %function 8 | DebugMon_Handler: 9 | mrs r0,psp ;// Get process stack 10 | sub r1,r0,#(4*13) ;// Make space for saved state 11 | msr psp,r1 ;// Ensure PSP is up to date 12 | 13 | mov r12,r0 ;// R12 = stack 14 | mov r1,#1 ;// R1 = exception state type 15 | mrs r2,ipsr ;// R2 = vector number 16 | mrs r3,basepri ;// R3 = basepri 17 | stmfd r0!,{r1-r12,lr} ;// Push type, vector, basepri, r4-11 18 | 19 | mov r4,r0 ;// R4 = saved state pointer 20 | bl rt_hw_debugmon_exception 21 | 22 | mov r0,r4 ;// R4 = saved state pointer 23 | ldmfd r0!,{r1-r12,lr} ;// Pop type, vec, basepri, registers and LR 24 | msr psp,r0 ;// Restore PSP 25 | msr basepri,r3 ;// Restore basepri 26 | 27 | bx lr ;// Return 28 | -------------------------------------------------------------------------------- /components/gdb/libcpu/cortexm/gdb_handler.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | void rt_hw_debugmon_exception(void *regs) 5 | { 6 | #ifdef RT_USING_GDB 7 | gdb_arch_late(); 8 | gdb_handle_exception(SIGTRAP, regs); 9 | gdb_arch_exit(); 10 | #endif 11 | } 12 | -------------------------------------------------------------------------------- /components/gdb/readme-zh.txt: -------------------------------------------------------------------------------- 1 | 说明: 2 | 3 | 一 当前版本进度 4 | 5 | 1).分类 6 | 考虑到arm各种版本的调试寄存器地址和种类都有很大不同 7 | 所以分为两个版本,均只在GCC下编译 8 | 9 | 1.基础ARM(软件断点(使用undef指令的办法),需要ram运行,模拟单步) 10 | 2.cortex M系列(不支持M0,基于寄存器操作,支持硬件断点,数据观察点,硬件单步) 11 | 12 | 理论上cortexA系列和cortexM的调式单元是一样的,有需要的话也可以在基础arm版本里单独为cortexA做出可选的数据断点,硬件单步 13 | 14 | 二 安装说明 15 | 16 | 1) 下载 17 | 下载最新RT-THREAD GDB STUB代码,并解压 18 | 19 | 2) 加入RT-Thread 20 | 先将得到的components文件夹覆盖RTT根目录 21 | 然后若要使用BBB板测试GDB,就用BSP/beaglebone和libpcu/am335x覆盖RTT下的同名文件夹 22 | 23 | 若要使用STM32F407测试GDB,就用BSP/stm32F4xx覆盖RTT下的同名文件夹,同时更改编译器为gcc 24 | 25 | 3) 宏 26 | 打开RT_USING_GDB 27 | 28 | 三 宏配置说明 29 | 30 | 1) RT_GDB_HAVE_HWBP 31 | 1硬件断点 32 | 33 | 2) RT_GDB_HAVE_SWBP 34 | 1软件断点 35 | 36 | 3) RT_GDB_MAX_BREAKPOINTS 37 | 最大软件断点数量 38 | 不加默认20 39 | 40 | 4) RT_GDB_ICACHE 41 | 是否使用ICACHE 42 | 若使用了ICACHE则要开启此宏,保证断点覆盖后及时刷新 43 | 44 | 5) RT_GDB_DEBUG 45 | 测试开发用 46 | 会打印GDB收发信息到默认串口上,以供获取数据 47 | 48 | 四 使用说明 49 | 50 | 1) 设置serial设备 51 | 首先需要调用 52 | void gdb_set_device(const char* device_name); (gdb_stub.h) 53 | 设置相应的GDB通信端口 54 | PS: 55 | 首先serial的驱动不能是中断 56 | 其次收发函数最好是poll的,要不就是9600,不然可能会出现问题 57 | 若出现问题,请打开 RT_GDB_DEBUG ,观察收发是否正常。 58 | 59 | 2) 进入GDB stub 60 | 调用 61 | void gdb_start(); (gdb_stub.h) 62 | 触发异常,即可进入等待状态 等待GDB连接 63 | 也可以将该函数加入按键中断中,可以实现外部打断程序的效果(条件有限,未测试) 64 | 65 | 3) pc连接 66 | 确认GCC 打开-g选项后编译 67 | 然后arm-none-eabi-gdb xxxx.elf or axf 68 | 进如GDB界面后 69 | set serial baud 115200(or 9600) 70 | target remote /dev/ttyUSB0(linux) or COM1 (windows) 71 | 即可实现GDB对接 72 | 73 | PS: 74 | BBB板默认uart4作为GDB通信口 75 | STM32F407默认uart6作GDB通信 76 | 77 | 五 移植说明 78 | 79 | 若要移植到不同架构上 80 | 软件实现请参考gdb/libcpu/arm下的文件 81 | 硬件实现请参考gdb/libcpu/cortexm下的文件 82 | 需要rsp协议的话 请参考https://www.sourceware.org/gdb/current/onlinedocs/gdb/Remote-Protocol.html 83 | 84 | 若要移植到已有架构的芯片上 85 | 1) arm9,11以及cortexA 86 | 修改udef和dabt的函数,在/libcpu/arm/am335x/trap.c里,加入ifdef GDB的内容 87 | 将libcpu/arm/am335x/start_gcc.s的相关异常向量汇编复制到自己的undef和dabt异常向量里 88 | 分配足够的栈空间给undef 89 | 90 | 2) cortexM3以及M4 91 | 删除已有的debugmon_handler 92 | 优先级分组有变化的话,重定义宏GDB_CORTEXM_PRIORITY_MAX,就是basepri的设置值,满足屏蔽中断的同时不屏蔽debugmon 93 | 使用有需要的话,重定义cortexm_stub.c的data_acess数组,也就是允许GDB访问的地址空间 94 | 增大_system_stack_size,也就是MSP栈的大小 95 | 96 | 97 | 六 易错或者bug(出错了看这里) 98 | 99 | 编译器选项是否打开-g,是否使用GCC编译 100 | 硬件断点使用超过(max-1)个后,单步可能会出现不正常 101 | 检查串口通信是否正常,可以打开RT_GDB_DEBUG 102 | 堆栈大小是否设置合适(因为gdb要在handler模式下运行,所需要的栈大小比较大,大概0x200) 103 | cm系列切记如果优先级分组不同于默认设置,就要重定义宏GDB_CORTEXM_PRIORITY_MAX,使抢占优先级等于1,不然单步可能会出现问题(被中断抢占) 104 | cm系列在中断里设置断点会出现错误(目测程序还是正常工作,就是压栈的寄存器还是进入中断前的,所以返回的寄存器信息有误) 105 | cm系列可能会因为访问不可访问的地址造成出错,有需求自己手动修改cortexm_stub.c的data_acess数组(没找到好的办法,falut后寄存器全乱了) 106 | 107 | 108 | ## 109 | 嫌速度慢的话就把串口速度9600改成115200 110 | 不过如此就要把注册的驱动里的getc改成阻塞的,不然会收不到 111 | 类似 112 | while(!(UART_LSR_REG(uart->base) & 0x01)); 113 | ch = UART_RHR_REG(uart->base) & 0xff; 114 | 原先是 115 | if (UART_LSR_REG(uart->base) & 0x01) 116 | { 117 | ch = UART_RHR_REG(uart->base) & 0xff; 118 | } 119 | -------------------------------------------------------------------------------- /libcpu/arm/am335x/start_gcc.S: -------------------------------------------------------------------------------- 1 | /* 2 | * File : start_gcc.S 3 | * This file is part of RT-Thread RTOS 4 | * COPYRIGHT (C) 2013, RT-Thread Development Team 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 2 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License along 17 | * with this program; if not, write to the Free Software Foundation, Inc., 18 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 19 | * 20 | * Change Logs: 21 | * Date Author Notes 22 | * 2013-07-05 Bernard the first version 23 | */ 24 | 25 | .equ Mode_USR, 0x10 26 | .equ Mode_FIQ, 0x11 27 | .equ Mode_IRQ, 0x12 28 | .equ Mode_SVC, 0x13 29 | .equ Mode_ABT, 0x17 30 | .equ Mode_UND, 0x1B 31 | .equ Mode_SYS, 0x1F 32 | 33 | .equ I_Bit, 0x80 @ when I bit is set, IRQ is disabled 34 | .equ F_Bit, 0x40 @ when F bit is set, FIQ is disabled 35 | 36 | .equ UND_Stack_Size, 0x00000200 37 | .equ SVC_Stack_Size, 0x00000100 38 | .equ ABT_Stack_Size, 0x00000000 39 | .equ FIQ_Stack_Size, 0x00000000 40 | .equ IRQ_Stack_Size, 0x00000100 41 | .equ USR_Stack_Size, 0x00000100 42 | 43 | #define ISR_Stack_Size (UND_Stack_Size + SVC_Stack_Size + ABT_Stack_Size + \ 44 | FIQ_Stack_Size + IRQ_Stack_Size) 45 | 46 | /* stack */ 47 | .globl stack_start 48 | .globl stack_top 49 | 50 | stack_start: 51 | .rept ISR_Stack_Size 52 | .long 0 53 | .endr 54 | stack_top: 55 | 56 | /* reset entry */ 57 | .globl _reset 58 | _reset: 59 | /* set the cpu to SVC32 mode and disable interrupt */ 60 | mrs r0, cpsr 61 | bic r0, r0, #0x1f 62 | orr r0, r0, #0x13 63 | msr cpsr_c, r0 64 | 65 | /* setup stack */ 66 | bl stack_setup 67 | 68 | /* clear .bss */ 69 | mov r0,#0 /* get a zero */ 70 | ldr r1,=__bss_start /* bss start */ 71 | ldr r2,=__bss_end /* bss end */ 72 | 73 | bss_loop: 74 | cmp r1,r2 /* check if data to clear */ 75 | strlo r0,[r1],#4 /* clear 4 bytes */ 76 | blo bss_loop /* loop until done */ 77 | 78 | /* call C++ constructors of global objects */ 79 | ldr r0, =__ctors_start__ 80 | ldr r1, =__ctors_end__ 81 | 82 | ctor_loop: 83 | cmp r0, r1 84 | beq ctor_end 85 | ldr r2, [r0], #4 86 | stmfd sp!, {r0-r1} 87 | mov lr, pc 88 | bx r2 89 | ldmfd sp!, {r0-r1} 90 | b ctor_loop 91 | ctor_end: 92 | 93 | /* start RT-Thread Kernel */ 94 | ldr pc, _rtthread_startup 95 | _rtthread_startup: 96 | .word rtthread_startup 97 | 98 | stack_setup: 99 | ldr r0, =stack_top 100 | 101 | @ Enter Undefined Instruction Mode and set its Stack Pointer 102 | msr cpsr_c, #Mode_UND|I_Bit|F_Bit 103 | mov sp, r0 104 | sub r0, r0, #UND_Stack_Size 105 | 106 | @ Enter Abort Mode and set its Stack Pointer 107 | msr cpsr_c, #Mode_ABT|I_Bit|F_Bit 108 | mov sp, r0 109 | sub r0, r0, #ABT_Stack_Size 110 | 111 | @ Enter FIQ Mode and set its Stack Pointer 112 | msr cpsr_c, #Mode_FIQ|I_Bit|F_Bit 113 | mov sp, r0 114 | sub r0, r0, #FIQ_Stack_Size 115 | 116 | @ Enter IRQ Mode and set its Stack Pointer 117 | msr cpsr_c, #Mode_IRQ|I_Bit|F_Bit 118 | mov sp, r0 119 | sub r0, r0, #IRQ_Stack_Size 120 | 121 | @ Enter Supervisor Mode and set its Stack Pointer 122 | msr cpsr_c, #Mode_SVC|I_Bit|F_Bit 123 | mov sp, r0 124 | sub r0, r0, #SVC_Stack_Size 125 | 126 | @ Enter User Mode and set its Stack Pointer 127 | mov sp, r0 128 | sub sl, sp, #USR_Stack_Size 129 | bx lr 130 | 131 | /* exception handlers: undef, swi, padt, dabt, resv, irq, fiq */ 132 | .align 5 133 | .globl vector_undef 134 | vector_undef: 135 | sub sp, sp, #72 136 | stmia sp, {r0 - r12} @/* Calling r0-r12 */ 137 | add r8, sp, #60 138 | 139 | mrs r1, cpsr 140 | mrs r2, spsr 141 | orr r2,r2, #I_Bit|F_Bit 142 | msr cpsr_c, r2 143 | mov r0, r0 144 | stmdb r8, {sp, lr} @/* Calling SP, LR */ 145 | msr cpsr_c, r1 @/* return to Undefined Instruction mode */ 146 | 147 | str lr, [r8, #0] @/* Save calling PC */ 148 | mrs r6, spsr 149 | str r6, [r8, #4] @/* Save CPSR */ 150 | str r0, [r8, #8] @/* Save OLD_R0 */ 151 | mov r0, sp 152 | 153 | bl rt_hw_trap_udef 154 | 155 | ldmia sp, {r0 - r12} @/* Calling r0 - r2 */ 156 | mov r0, r0 157 | ldr lr, [sp, #60] @/* Get PC */ 158 | add sp, sp, #72 159 | movs pc, lr @/* return & move spsr_svc into cpsr */ 160 | 161 | .align 5 162 | .globl vector_swi 163 | vector_swi: 164 | bl rt_hw_trap_swi 165 | 166 | .align 5 167 | .globl vector_pabt 168 | vector_pabt: 169 | bl rt_hw_trap_pabt 170 | 171 | .align 5 172 | .globl vector_dabt 173 | vector_dabt: 174 | sub sp, sp, #72 175 | stmia sp, {r0 - r12} @/* Calling r0-r12 */ 176 | add r8, sp, #60 177 | stmdb r8, {sp, lr} @/* Calling SP, LR */ 178 | str lr, [r8, #0] @/* Save calling PC */ 179 | mrs r6, spsr 180 | str r6, [r8, #4] @/* Save CPSR */ 181 | str r0, [r8, #8] @/* Save OLD_R0 */ 182 | mov r0, sp 183 | 184 | bl rt_hw_trap_dabt 185 | 186 | ldmia sp, {r0 - r12} @/* Calling r0 - r2 */ 187 | mov r0, r0 188 | ldr lr, [sp, #60] @/* Get PC */ 189 | add sp, sp, #72 190 | movs pc, lr @/* return & move spsr_svc into cpsr */ 191 | 192 | .align 5 193 | .globl vector_resv 194 | vector_resv: 195 | b . 196 | 197 | .align 5 198 | .globl vector_fiq 199 | vector_fiq: 200 | stmfd sp!,{r0-r7,lr} 201 | bl rt_hw_trap_fiq 202 | ldmfd sp!,{r0-r7,lr} 203 | subs pc,lr,#4 204 | 205 | .globl rt_interrupt_enter 206 | .globl rt_interrupt_leave 207 | .globl rt_thread_switch_interrupt_flag 208 | .globl rt_interrupt_from_thread 209 | .globl rt_interrupt_to_thread 210 | 211 | .globl rt_current_thread 212 | .globl vmm_thread 213 | .globl vmm_virq_check 214 | 215 | .globl vector_irq 216 | vector_irq: 217 | stmfd sp!, {r0-r12,lr} 218 | 219 | bl rt_interrupt_enter 220 | bl rt_hw_trap_irq 221 | bl rt_interrupt_leave 222 | 223 | @ if rt_thread_switch_interrupt_flag set, jump to 224 | @ rt_hw_context_switch_interrupt_do and don't return 225 | ldr r0, =rt_thread_switch_interrupt_flag 226 | ldr r1, [r0] 227 | cmp r1, #1 228 | beq rt_hw_context_switch_interrupt_do 229 | 230 | ldmfd sp!, {r0-r12,lr} 231 | subs pc, lr, #4 232 | 233 | rt_hw_context_switch_interrupt_do: 234 | mov r1, #0 @ clear flag 235 | str r1, [r0] 236 | 237 | ldmfd sp!, {r0-r12,lr}@ reload saved registers 238 | stmfd sp, {r0-r2} @ save r0-r2 239 | 240 | mrs r0, spsr @ get cpsr of interrupt thread 241 | 242 | sub r1, sp, #4*3 243 | sub r2, lr, #4 @ save old task's pc to r2 244 | 245 | @ switch to SVC mode with no interrupt 246 | msr cpsr_c, #I_Bit|F_Bit|Mode_SVC 247 | 248 | stmfd sp!, {r2} @ push old task's pc 249 | stmfd sp!, {r3-r12,lr}@ push old task's lr,r12-r4 250 | ldmfd r1, {r1-r3} @ restore r0-r2 of the interrupt thread 251 | stmfd sp!, {r1-r3} @ push old task's r0-r2 252 | stmfd sp!, {r0} @ push old task's cpsr 253 | 254 | ldr r4, =rt_interrupt_from_thread 255 | ldr r5, [r4] 256 | str sp, [r5] @ store sp in preempted tasks's TCB 257 | 258 | ldr r6, =rt_interrupt_to_thread 259 | ldr r6, [r6] 260 | ldr sp, [r6] @ get new task's stack pointer 261 | 262 | ldmfd sp!, {r4} @ pop new task's cpsr to spsr 263 | msr spsr_cxsf, r4 264 | 265 | ldmfd sp!, {r0-r12,lr,pc}^ @ pop new task's r0-r12,lr & pc, copy spsr to cpsr 266 | -------------------------------------------------------------------------------- /libcpu/arm/am335x/trap.c: -------------------------------------------------------------------------------- 1 | /* 2 | * File : trap.c 3 | * This file is part of RT-Thread RTOS 4 | * COPYRIGHT (C) 2006, RT-Thread Develop Team 5 | * 6 | * The license and distribution terms for this file may be 7 | * found in the file LICENSE in this distribution or at 8 | * http://www.rt-thread.org/license/LICENSE 9 | * 10 | * Change Logs: 11 | * Date Author Notes 12 | * 2011-09-23 Bernard first version 13 | */ 14 | 15 | #include 16 | #include 17 | 18 | #include "am33xx.h" 19 | #include "interrupt.h" 20 | 21 | #ifdef RT_USING_GDB 22 | #include "gdb_stub.h" 23 | #endif 24 | 25 | /** 26 | * @addtogroup AM33XX 27 | */ 28 | /*@{*/ 29 | 30 | extern struct rt_thread *rt_current_thread; 31 | #ifdef RT_USING_FINSH 32 | extern long list_thread(void); 33 | #endif 34 | 35 | /** 36 | * this function will show registers of CPU 37 | * 38 | * @param regs the registers point 39 | */ 40 | 41 | void rt_hw_show_register (struct rt_hw_register *regs) 42 | { 43 | rt_kprintf("Execption:\n"); 44 | rt_kprintf("r00:0x%08x r01:0x%08x r02:0x%08x r03:0x%08x\n", regs->r0, regs->r1, regs->r2, regs->r3); 45 | rt_kprintf("r04:0x%08x r05:0x%08x r06:0x%08x r07:0x%08x\n", regs->r4, regs->r5, regs->r6, regs->r7); 46 | rt_kprintf("r08:0x%08x r09:0x%08x r10:0x%08x\n", regs->r8, regs->r9, regs->r10); 47 | rt_kprintf("fp :0x%08x ip :0x%08x\n", regs->fp, regs->ip); 48 | rt_kprintf("sp :0x%08x lr :0x%08x pc :0x%08x\n", regs->sp, regs->lr, regs->pc); 49 | rt_kprintf("cpsr:0x%08x\n", regs->cpsr); 50 | } 51 | 52 | /** 53 | * When ARM7TDMI comes across an instruction which it cannot handle, 54 | * it takes the undefined instruction trap. 55 | * 56 | * @param regs system registers 57 | * 58 | * @note never invoke this function in application 59 | */ 60 | void rt_hw_trap_udef(struct rt_hw_register *regs) 61 | { 62 | 63 | #ifdef RT_USING_GDB 64 | regs->pc -= 4; //lr in undef is pc + 4 65 | if (gdb_undef_hook(regs)) 66 | return; 67 | #endif 68 | 69 | rt_hw_show_register(regs); 70 | 71 | rt_kprintf("undefined instruction\n"); 72 | rt_kprintf("thread %.*s stack:\n", RT_NAME_MAX, rt_current_thread->name); 73 | 74 | #ifdef RT_USING_FINSH 75 | list_thread(); 76 | #endif 77 | rt_hw_cpu_shutdown(); 78 | } 79 | 80 | /** 81 | * The software interrupt instruction (SWI) is used for entering 82 | * Supervisor mode, usually to request a particular supervisor 83 | * function. 84 | * 85 | * @param regs system registers 86 | * 87 | * @note never invoke this function in application 88 | */ 89 | void rt_hw_trap_swi(struct rt_hw_register *regs) 90 | { 91 | rt_hw_show_register(regs); 92 | 93 | rt_kprintf("software interrupt\n"); 94 | rt_hw_cpu_shutdown(); 95 | } 96 | 97 | /** 98 | * An abort indicates that the current memory access cannot be completed, 99 | * which occurs during an instruction prefetch. 100 | * 101 | * @param regs system registers 102 | * 103 | * @note never invoke this function in application 104 | */ 105 | void rt_hw_trap_pabt(struct rt_hw_register *regs) 106 | { 107 | rt_hw_show_register(regs); 108 | 109 | rt_kprintf("prefetch abort\n"); 110 | rt_kprintf("thread %.*s stack:\n", RT_NAME_MAX, rt_current_thread->name); 111 | 112 | #ifdef RT_USING_FINSH 113 | list_thread(); 114 | #endif 115 | rt_hw_cpu_shutdown(); 116 | } 117 | 118 | /** 119 | * An abort indicates that the current memory access cannot be completed, 120 | * which occurs during a data access. 121 | * 122 | * @param regs system registers 123 | * 124 | * @note never invoke this function in application 125 | */ 126 | void rt_hw_trap_dabt(struct rt_hw_register *regs) 127 | { 128 | 129 | #ifdef RT_USING_GDB 130 | if (gdb_mem_fault_handler) { 131 | regs->pc = (unsigned long)gdb_mem_fault_handler; 132 | return; 133 | } 134 | #endif 135 | rt_hw_show_register(regs); 136 | 137 | rt_kprintf("data abort\n"); 138 | rt_kprintf("thread %.*s stack:\n", RT_NAME_MAX, rt_current_thread->name); 139 | 140 | #ifdef RT_USING_FINSH 141 | list_thread(); 142 | #endif 143 | rt_hw_cpu_shutdown(); 144 | } 145 | 146 | void rt_hw_trap_irq() 147 | { 148 | void *param; 149 | unsigned long ir; 150 | rt_isr_handler_t isr_func; 151 | extern struct rt_irq_desc isr_table[]; 152 | 153 | ir = rt_hw_interrupt_get_active(INT_IRQ); 154 | if (ir == 127) 155 | { 156 | /* new IRQ generation */ 157 | rt_hw_interrupt_ack(INT_IRQ); 158 | ir = rt_hw_interrupt_get_active(INT_IRQ); 159 | if (ir == 127) 160 | { 161 | /* still spurious interrupt, get out */ 162 | /*rt_kprintf("still spurious interrupt\n");*/ 163 | return; 164 | } 165 | /*rt_kprintf("new IRQ: %d\n", ir);*/ 166 | } 167 | 168 | /* get interrupt service routine */ 169 | isr_func = isr_table[ir].handler; 170 | param = isr_table[ir].param; 171 | 172 | /* turn to interrupt service routine */ 173 | if (isr_func != RT_NULL) 174 | isr_func(ir, param); 175 | 176 | /* new IRQ generation */ 177 | rt_hw_interrupt_ack(INT_IRQ); 178 | } 179 | 180 | void rt_hw_trap_fiq() 181 | { 182 | void *param; 183 | unsigned long ir; 184 | rt_isr_handler_t isr_func; 185 | extern struct rt_irq_desc isr_table[]; 186 | 187 | ir = rt_hw_interrupt_get_active(INT_FIQ); 188 | 189 | /* get interrupt service routine */ 190 | isr_func = isr_table[ir].handler; 191 | param = isr_table[ir].param; 192 | 193 | /* turn to interrupt service routine */ 194 | isr_func(ir, param); 195 | 196 | /* new FIQ generation */ 197 | rt_hw_interrupt_ack(INT_FIQ); 198 | } 199 | 200 | /*@}*/ 201 | -------------------------------------------------------------------------------- /readme-zh.txt: -------------------------------------------------------------------------------- 1 | 说明: 2 | 3 | 一 当前版本进度 4 | 5 | 1).分类 6 | 考虑到arm各种版本的调试寄存器地址和种类都有很大不同 7 | 所以分为两个版本,均只在GCC下编译 8 | 9 | 1.基础ARM(软件断点(使用undef指令的办法),需要ram运行,模拟单步) 10 | 2.cortex M系列(不支持M0,基于寄存器操作,支持硬件断点,数据观察点,硬件单步) 11 | 12 | 理论上cortexA系列和cortexM的调式单元是一样的,有需要的话也可以在基础arm版本里单独为cortexA做出可选的数据断点,硬件单步 13 | 14 | 二 安装说明 15 | 16 | 1) 下载 17 | 下载最新RT-THREAD GDB STUB代码,并解压 18 | 19 | 2) 加入RT-Thread 20 | 先将得到的components文件夹覆盖RTT根目录 21 | 然后若要使用BBB板测试GDB,就用BSP/beaglebone和libpcu/am335x覆盖RTT下的同名文件夹 22 | 23 | 若要使用STM32F407测试GDB,就用BSP/stm32F4xx覆盖RTT下的同名文件夹,同时更改编译器为gcc 24 | 25 | 3) 宏 26 | 打开RT_USING_GDB 27 | 28 | 三 宏配置说明 29 | 30 | 1) RT_GDB_HAVE_HWBP 31 | 1硬件断点 32 | 33 | 2) RT_GDB_HAVE_SWBP 34 | 1软件断点 35 | 36 | 3) RT_GDB_MAX_BREAKPOINTS 37 | 最大软件断点数量 38 | 不加默认20 39 | 40 | 4) RT_GDB_ICACHE 41 | 是否使用ICACHE 42 | 若使用了ICACHE则要开启此宏,保证断点覆盖后及时刷新 43 | 44 | 5) RT_GDB_DEBUG 45 | 测试开发用 46 | 会打印GDB收发信息到默认串口上,以供获取数据 47 | 48 | 四 使用说明 49 | 50 | 1) 设置serial设备 51 | 首先需要调用 52 | void gdb_set_device(const char* device_name); (gdb_stub.h) 53 | 设置相应的GDB通信端口 54 | PS: 55 | 首先serial的驱动不能是中断 56 | 其次收发函数最好是poll的,要不就是9600,不然可能会出现问题 57 | 若出现问题,请打开 RT_GDB_DEBUG ,观察收发是否正常。 58 | 59 | 2) 进入GDB stub 60 | 调用 61 | void gdb_start(); (gdb_stub.h) 62 | 触发异常,即可进入等待状态 等待GDB连接 63 | 也可以将该函数加入按键中断中,可以实现外部打断程序的效果(条件有限,未测试) 64 | 65 | 3) pc连接 66 | 确认GCC 打开-g选项后编译 67 | 然后arm-none-eabi-gdb xxxx.elf or axf 68 | 进如GDB界面后 69 | set serial baud 115200(or 9600) 70 | target remote /dev/ttyUSB0(linux) or COM1 (windows) 71 | 即可实现GDB对接 72 | 73 | PS: 74 | BBB板默认uart4作为GDB通信口 75 | STM32F407默认uart6作GDB通信 76 | 77 | 五 移植说明 78 | 79 | 若要移植到不同架构上 80 | 软件实现请参考gdb/libcpu/arm下的文件 81 | 硬件实现请参考gdb/libcpu/cortexm下的文件 82 | 需要rsp协议的话 请参考https://www.sourceware.org/gdb/current/onlinedocs/gdb/Remote-Protocol.html 83 | 84 | 若要移植到已有架构的芯片上 85 | 1) arm9,11以及cortexA 86 | 修改udef和dabt的函数,在/libcpu/arm/am335x/trap.c里,加入ifdef GDB的内容 87 | 将libcpu/arm/am335x/start_gcc.s的相关异常向量汇编复制到自己的undef和dabt异常向量里 88 | 分配足够的栈空间给undef 89 | 90 | 2) cortexM3以及M4 91 | 删除已有的debugmon_handler 92 | 优先级分组有变化的话,重定义宏GDB_CORTEXM_PRIORITY_MAX,就是basepri的设置值,满足屏蔽中断的同时不屏蔽debugmon 93 | 使用有需要的话,重定义cortexm_stub.c的data_acess数组,也就是允许GDB访问的地址空间 94 | 增大_system_stack_size,也就是MSP栈的大小 95 | 96 | 97 | 六 易错或者bug(出错了看这里) 98 | 99 | 编译器选项是否打开-g,是否使用GCC编译 100 | 硬件断点使用超过(max-1)个后,单步可能会出现不正常 101 | 检查串口通信是否正常,可以打开RT_GDB_DEBUG 102 | 堆栈大小是否设置合适(因为gdb要在handler模式下运行,所需要的栈大小比较大,大概0x200) 103 | cm系列切记如果优先级分组不同于默认设置,就要重定义宏GDB_CORTEXM_PRIORITY_MAX,使抢占优先级等于1,不然单步可能会出现问题(被中断抢占) 104 | cm系列在中断里设置断点会出现错误(目测程序还是正常工作,就是压栈的寄存器还是进入中断前的,所以返回的寄存器信息有误) 105 | cm系列可能会因为访问不可访问的地址造成出错,有需求自己手动修改cortexm_stub.c的data_acess数组(没找到好的办法,falut后寄存器全乱了) 106 | 107 | 108 | ## 109 | 嫌速度慢的话就把串口速度9600改成115200 110 | 不过如此就要把注册的驱动里的getc改成阻塞的,不然会收不到 111 | 类似 112 | while(!(UART_LSR_REG(uart->base) & 0x01)); 113 | ch = UART_RHR_REG(uart->base) & 0xff; 114 | 原先是 115 | if (UART_LSR_REG(uart->base) & 0x01) 116 | { 117 | ch = UART_RHR_REG(uart->base) & 0xff; 118 | } 119 | --------------------------------------------------------------------------------