- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I am trying to halt when a particular memory location gets set to a specific value. I'm not looking for a particular variable to change, but rather a word in the stack.
I know how to set a watchpoint to break on write access. That works fine, but it halts very frequently and I need it to halt only when a specific, invalid value is written.
I tried to add a "condition" to the memory access watchpoint, but this makes it either run so slowly that it never finishes timer interrupt handling, or it just locks up the debugger ("stop debugging" button in PSoC Creator button is ineffective). I read something about modifying the linker file to place a variable at a specific location, then watch that variable for changes, but I'm not clear on how that's different nor exactly how to do it.
This is the watchpoint condition I am using:
(*((volatile unsigned long *)0x20007b18))==0x00002b4F
Is there another way to do this? Is this slow behavior a bug in PSoC Creator, or maybe a limitation of the Cortex-M3?
Thanks!
-Will
Solved! Go to Solution.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Dear Will-san,
Today I borrowed a PSoC-5LP board from my colleague and ran tests using following main.c
==============================
#include "project.h"
#include <stdio.h>
char str[128] ; /* print buffer */
uint32_t count = 0 ;
// register uint32_t count asm("r6") ;
void init_hardware(void)
{
CyGlobalIntEnable; /* Enable global interrupts. */
UART_Start() ;
}
void UART_UartPutString(char *str)
{
while(str && *str) {
UART_PutChar(*str++) ;
}
}
int main(void)
{
uint32_t loop = 0 ;
volatile int flag = 0 ;
init_hardware() ;
sprintf(str, "DWT test program (%s %s)\r\n", __DATE__, __TIME__) ;
UART_UartPutString(str) ;
for(;;) {
if ((count % 0x10000) == 0) {
sprintf(str, "Loop %d\r\n", loop++ ) ;
UART_UartPutString(str) ;
count = 0 ;
flag = 0 ;
}
count++ ;
#if 0
if (count == 0x100) {
flag = 1 ;
}
#endif
}
}
==============================
(1) count is a usual global variable and #if is 0 at the end part of the main.
set Condition Break "count == 0x100" at the line of "count++"
It took about 63sec to hit the first break.
(2) count is a register variable and #if is 0 at the end part of the main.
set Condition Break "count == 0x100" at the line of "count++"
it took about 52sec to hit the first break.
(3) count is a usual global variable and #if if 1 at the end part of the main.
set Break at the line of "flag = 1"
it took less than a second to hit the first break.
So my current conclusion(s) are
1. Yes, using register variable makes the test faster but not quite.
2. Although modification to the source is required,
placing a trap routine makes the "cost" of time much smaller.
moto
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Firstly, not all the ram space can R/W by customer.
You need to guarantee that the space you can operate.
If you want to use the pointer to manipulate memory, I think you can do following below steps:
1: define a static variable:
2: use it in the while loop(if it is not be used, the complier will optimize the var.
3: debug it to find the storage address of the var.
4: comment it, and use the address. (You must guarantee that the address not be used by the system)
5: I use PSoC4200 kit to test, the core is M0, because I think the question is no related with the kind of the core.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
But I think use the pointer to operate the IC memory is not a good solution.
If you can use other flag to judge it, please use another way.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Ring,
Thank you for your input. Yes, the memory address is writable by me (it is in the stack RAM space).
Your technique is basically the same as what I am doing. My problem is that it is too slow for the rest of my program to operate.
Thanks,
-Will
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi,
I don't know if this works for your case,
but following is what I could think of this morning...
If you can extract the data you are watching as a register variable,
(I hope that) time required for watching the point may be reduced.
==================================
#include "project.h"
#include <stdio.h>
char str[128] ;
register uint32_t flag asm("r6") ;
int main(void)
{
uint32_t count = 0 ;
CyGlobalIntEnable; /* Enable global interrupts. */
UART_Start() ;
sprintf(str, "Test Program Started! (%s %s)\n", __DATE__, __TIME__) ;
UART_UartPutString(str) ;
for(;;) {
sprintf(str, "count = %d ", count) ;
UART_UartPutString(str) ;
if (count == 0xF) {
sprintf(str, "flag = %d ", flag) ;
UART_UartPutString(str) ;
flag++ ;
}
UART_UartPutString("\n") ;
count = (count + 1) % 0x10 ;
CyDelay(100) ;
}
}
==================================
I placed a break point at the line of
"if (count == 0xF) {"
with condition
"flag == 2".
to test.
Attached is my sample project using CY8CKIT-044
moto
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Moto,
That is an interesting idea. I will need to look at how the "register" directive gets implemented. I think this will change the code and not really let me watch the particular memory address I need to monitor.
Do you know if the Arm Cortex-M3 does data value checking in hardware (built into the CPU), or does the debugger itself need to read memory after the breakpoint is hit and decide to continue or halt?
Thanks,
-Will
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Dear Will-san,
> I think this will change the code and not really let me watch the particular memory address I need to monitor.
Yes, so this idea should be used only for debugging, but as far as we can "fool" the debugger
we may be able to catch the error value, or at least data watching must be faster than
accessing Flash Memory.
> Do you know if the Arm Cortex-M3 does data value checking in hardware (built into the CPU),
> or does the debugger itself need to read memory after the breakpoint is hit and decide to continue or halt?
Briefly reading the TRM of PSoC5LP (40 Cortex-M3 Debug and Trace), it seems to have ETM, ITM and DTW.
So (I think) from the hardware viewpoint, PSoC5LP should be able to provide functionality you want.
But meantime from the software viewpoint, I wonder if PSoC Creator is taking advantage of those facilities.
May be we need special debugger hardware with trace function and development tool which is supporting
such functions.
References
(1) Technical Reference Manual
http://www.cypress.com/products/32-bit-arm-cortex-m3-psoc-5lp
(2) Application Note 179, 4. Debugging with the Cortex-M3 (arm Developer)
moto
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Dear Will-san,
Today I borrowed a PSoC-5LP board from my colleague and ran tests using following main.c
==============================
#include "project.h"
#include <stdio.h>
char str[128] ; /* print buffer */
uint32_t count = 0 ;
// register uint32_t count asm("r6") ;
void init_hardware(void)
{
CyGlobalIntEnable; /* Enable global interrupts. */
UART_Start() ;
}
void UART_UartPutString(char *str)
{
while(str && *str) {
UART_PutChar(*str++) ;
}
}
int main(void)
{
uint32_t loop = 0 ;
volatile int flag = 0 ;
init_hardware() ;
sprintf(str, "DWT test program (%s %s)\r\n", __DATE__, __TIME__) ;
UART_UartPutString(str) ;
for(;;) {
if ((count % 0x10000) == 0) {
sprintf(str, "Loop %d\r\n", loop++ ) ;
UART_UartPutString(str) ;
count = 0 ;
flag = 0 ;
}
count++ ;
#if 0
if (count == 0x100) {
flag = 1 ;
}
#endif
}
}
==============================
(1) count is a usual global variable and #if is 0 at the end part of the main.
set Condition Break "count == 0x100" at the line of "count++"
It took about 63sec to hit the first break.
(2) count is a register variable and #if is 0 at the end part of the main.
set Condition Break "count == 0x100" at the line of "count++"
it took about 52sec to hit the first break.
(3) count is a usual global variable and #if if 1 at the end part of the main.
set Break at the line of "flag = 1"
it took less than a second to hit the first break.
So my current conclusion(s) are
1. Yes, using register variable makes the test faster but not quite.
2. Although modification to the source is required,
placing a trap routine makes the "cost" of time much smaller.
moto