this works with pyocd (but not openocd)
This commit is contained in:
179
src/rtt_io.c
179
src/rtt_io.c
@@ -71,12 +71,12 @@ typedef struct {
|
||||
|
||||
typedef struct { // see SEGGER_RTT_CB
|
||||
char acID[16]; // Initialized to "SEGGER RTT"
|
||||
// int MaxNumUpBuffers; // Initialized to SEGGER_RTT_MAX_NUM_UP_BUFFERS (type. 2)
|
||||
// int MaxNumDownBuffers; // Initialized to SEGGER_RTT_MAX_NUM_DOWN_BUFFERS (type. 2)
|
||||
int MaxNumUpBuffers; // Initialized to SEGGER_RTT_MAX_NUM_UP_BUFFERS (type. 2)
|
||||
int MaxNumDownBuffers; // Initialized to SEGGER_RTT_MAX_NUM_DOWN_BUFFERS (type. 2)
|
||||
} EXT_SEGGER_RTT_CB_HEADER;
|
||||
|
||||
#define TARGET_RAM_START g_board_info.target_cfg->ram_regions[0].start
|
||||
#define TARGET_RAM_END g_board_info.target_cfg->ram_regions[0].end
|
||||
#define TARGET_RAM_START (g_board_info.target_cfg->ram_regions[0].start)
|
||||
#define TARGET_RAM_END (g_board_info.target_cfg->ram_regions[0].end)
|
||||
|
||||
#define STREAM_RTT_SIZE 128
|
||||
#define STREAM_RTT_TRIGGER 1
|
||||
@@ -101,6 +101,7 @@ static TaskHandle_t task_rtt_from_target_thread = NULL;
|
||||
static StreamBufferHandle_t stream_rtt_console_to_target; // small stream for host->probe->target console communication
|
||||
static EventGroupHandle_t events;
|
||||
static TimerHandle_t timer_rtt_cb_verify;
|
||||
static TimerHandle_t timer_dap_connected;
|
||||
|
||||
#if INCLUDE_SYSVIEW
|
||||
#define RTT_CHANNEL_SYSVIEW 1
|
||||
@@ -122,7 +123,7 @@ static uint32_t check_buffer_for_rtt_cb(uint8_t *buf, uint32_t buf_size, uint32_
|
||||
{
|
||||
uint32_t rtt_cb = 0;
|
||||
|
||||
for (uint32_t ndx = 0; ndx <= buf_size - sizeof(seggerRTT); ndx += segger_alignment) {
|
||||
for (uint32_t ndx = 0; ndx <= buf_size - sizeof(rtt_cb_header); ndx += segger_alignment) {
|
||||
if (memcmp(buf + ndx, seggerRTT, sizeof(seggerRTT)) == 0) {
|
||||
memcpy( &rtt_cb_header, buf + ndx, sizeof(rtt_cb_header));
|
||||
rtt_cb = base_addr + ndx;
|
||||
@@ -134,6 +135,29 @@ static uint32_t check_buffer_for_rtt_cb(uint8_t *buf, uint32_t buf_size, uint32_
|
||||
|
||||
|
||||
|
||||
static bool rtt_check_control_block_header(uint32_t rtt_cb)
|
||||
{
|
||||
bool ok = false;
|
||||
EXT_SEGGER_RTT_CB_HEADER rtt_cb_header_buf;
|
||||
|
||||
if (rtt_cb < TARGET_RAM_START || rtt_cb > TARGET_RAM_END - sizeof(EXT_SEGGER_RTT_CB_HEADER)) {
|
||||
// -> out of range
|
||||
}
|
||||
else if (memcmp(seggerRTT, rtt_cb_header.acID, sizeof(seggerRTT)) != 0) {
|
||||
// -> rtt_cb_header is not yet valid
|
||||
}
|
||||
else {
|
||||
// printf("..a1 %d\n", ok);
|
||||
ok = swd_read_memory(rtt_cb, (uint8_t *)&rtt_cb_header_buf, sizeof(rtt_cb_header_buf));
|
||||
// printf("..a2 %d\n", ok);
|
||||
ok = ok && memcmp( &rtt_cb_header, &rtt_cb_header_buf, sizeof(rtt_cb_header_buf)) == 0;
|
||||
// printf("..a3 %d\n", ok);
|
||||
}
|
||||
return ok;
|
||||
} // rtt_check_control_block_header
|
||||
|
||||
|
||||
|
||||
static bool is_target_ok(uint32_t addr)
|
||||
/**
|
||||
* Check if the target is still ok (after an attach)
|
||||
@@ -162,16 +186,14 @@ static uint32_t search_for_rtt_cb(uint32_t prev_rtt_cb)
|
||||
uint32_t rtt_cb = 0;
|
||||
|
||||
// check parameter
|
||||
if ((prev_rtt_cb != 0 && prev_rtt_cb < TARGET_RAM_START) || prev_rtt_cb > TARGET_RAM_END - sizeof(seggerRTT)) {
|
||||
if ((prev_rtt_cb != 0 && prev_rtt_cb < TARGET_RAM_START) || prev_rtt_cb > TARGET_RAM_END - sizeof(EXT_SEGGER_RTT_CB_HEADER)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (prev_rtt_cb != 0) {
|
||||
// fast search, saves a little SW traffic and a few ms
|
||||
ok = swd_read_memory(prev_rtt_cb, buf, sizeof(seggerRTT));
|
||||
if (ok) {
|
||||
rtt_cb = check_buffer_for_rtt_cb(buf, sizeof(seggerRTT), prev_rtt_cb);
|
||||
}
|
||||
// fast search, saves a little SW traffic and a few ms
|
||||
ok = rtt_check_control_block_header(prev_rtt_cb);
|
||||
if (ok) {
|
||||
rtt_cb = prev_rtt_cb;
|
||||
}
|
||||
|
||||
if (rtt_cb == 0) {
|
||||
@@ -194,18 +216,6 @@ static uint32_t search_for_rtt_cb(uint32_t prev_rtt_cb)
|
||||
|
||||
|
||||
|
||||
static bool rtt_check_control_block_header(uint32_t rtt_cb)
|
||||
{
|
||||
bool ok;
|
||||
EXT_SEGGER_RTT_CB_HEADER rtt_cb_header_buf;
|
||||
|
||||
ok = swd_read_memory(rtt_cb, (uint8_t *)&rtt_cb_header_buf, sizeof(rtt_cb_header_buf));
|
||||
ok = ok && memcmp( &rtt_cb_header, &rtt_cb_header_buf, sizeof(rtt_cb_header_buf)) == 0;
|
||||
return ok;
|
||||
} // rtt_check_control_block_header
|
||||
|
||||
|
||||
|
||||
static bool rtt_check_channel_from_target(uint32_t rtt_cb, uint16_t channel, EXT_SEGGER_RTT_BUFFER_UP *extRttBuf, bool *found)
|
||||
/**
|
||||
* Check if there is a valid buffer from target for this channel.
|
||||
@@ -474,20 +484,25 @@ static void do_rtt_io(uint32_t rtt_cb, bool with_alive_check)
|
||||
bool net_sysview_was_connected = false;
|
||||
bool working_sysview = false;
|
||||
#endif
|
||||
bool ok = true;
|
||||
bool ok;
|
||||
|
||||
static_assert(sizeof(uint32_t) == sizeof(unsigned int), "uint32_t/unsigned int mix up"); // why doesn't segger use uint32_t?
|
||||
|
||||
if (rtt_cb < TARGET_RAM_START || rtt_cb >= TARGET_RAM_END) {
|
||||
if (rtt_cb < TARGET_RAM_START || rtt_cb > TARGET_RAM_END - sizeof(EXT_SEGGER_RTT_CB_HEADER)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (with_alive_check) {
|
||||
xTimerReset(timer_rtt_cb_verify, 100);
|
||||
}
|
||||
if (dap_is_connected()) {
|
||||
xTimerReset(timer_dap_connected, 100);
|
||||
}
|
||||
// picoprobe_info("yy %08x %d %d\n", (unsigned int)rtt_cb, with_alive_check, dap_is_connected());
|
||||
|
||||
// do operations
|
||||
rtt_console_running = true;
|
||||
ok = true;
|
||||
while (ok) { // && !sw_unlock_requested()) {
|
||||
bool probe_rtt_cb;
|
||||
|
||||
@@ -495,6 +510,7 @@ static void do_rtt_io(uint32_t rtt_cb, bool with_alive_check)
|
||||
|
||||
#if OPT_TARGET_UART
|
||||
{
|
||||
#if INCLUDE_SYSVIEW
|
||||
static TickType_t lastTimeWorked;
|
||||
|
||||
if ( !working_uart && xTaskGetTickCount() - lastTimeWorked < pdMS_TO_TICKS(RTT_CONSOLE_POLL_INT_MS)) {
|
||||
@@ -502,8 +518,10 @@ static void do_rtt_io(uint32_t rtt_cb, bool with_alive_check)
|
||||
// pause console IO for a longer time to let SysView the interface
|
||||
//
|
||||
}
|
||||
else {
|
||||
working_uart = false;
|
||||
else
|
||||
#endif
|
||||
{
|
||||
// working_uart = false;
|
||||
|
||||
if (ok_console_from_target)
|
||||
ok = ok && rtt_from_target(&aUpConsole, cdc_uart_write, false, &working_uart);
|
||||
@@ -513,7 +531,9 @@ static void do_rtt_io(uint32_t rtt_cb, bool with_alive_check)
|
||||
|
||||
probe_rtt_cb = probe_rtt_cb && !working_uart;
|
||||
|
||||
#if INCLUDE_SYSVIEW
|
||||
lastTimeWorked = xTaskGetTickCount();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -537,15 +557,19 @@ static void do_rtt_io(uint32_t rtt_cb, bool with_alive_check)
|
||||
}
|
||||
#endif
|
||||
|
||||
//printf("%d %d\n", ok, probe_rtt_cb);
|
||||
// printf("aa %d %d\n", ok, probe_rtt_cb);
|
||||
if (ok && probe_rtt_cb) {
|
||||
// did nothing -> check if RTT channels appeared
|
||||
// printf("%8x %d %d %d %d %d\n", (unsigned int)rtt_cb, ok, probe_rtt_cb, working_uart, ok_console_from_target, ok_console_to_target);
|
||||
// did nothing -> check if RTT channels (dis)appeared
|
||||
ok = ok && rtt_check_control_block_header(rtt_cb);
|
||||
// printf("ab %d\n", ok);
|
||||
#if OPT_TARGET_UART
|
||||
if ( !ok_console_from_target)
|
||||
ok = ok && rtt_check_channel_from_target(rtt_cb, RTT_CHANNEL_CONSOLE, &aUpConsole, &ok_console_from_target);
|
||||
// printf("ac %d\n", ok);
|
||||
if ( !ok_console_to_target)
|
||||
ok = ok && rtt_check_channel_to_target(rtt_cb, RTT_CHANNEL_CONSOLE, &aDownConsole, &ok_console_to_target);
|
||||
// printf("ad %d\n", ok);
|
||||
#endif
|
||||
#if INCLUDE_SYSVIEW
|
||||
if ( !ok_sysview_from_target)
|
||||
@@ -557,37 +581,39 @@ static void do_rtt_io(uint32_t rtt_cb, bool with_alive_check)
|
||||
// -> delay
|
||||
xEventGroupWaitBits(events, EV_RTT_TO_TARGET, pdTRUE, pdFALSE, pdMS_TO_TICKS(RTT_POLL_INT_MS));
|
||||
}
|
||||
// printf("az %d\n", ok);
|
||||
|
||||
if (with_alive_check && !rtt_cb_alive && !xTimerIsTimerActive(timer_rtt_cb_verify)) {
|
||||
// nothing happens here after some time -> timeout and do a new search
|
||||
picoprobe_info("xx !alive\n");
|
||||
ok = false;
|
||||
}
|
||||
|
||||
if (dap_connected()) {
|
||||
static uint32_t cnt;
|
||||
|
||||
if (sw_unlock_requested() && (++cnt & 0x3f) == 0) {
|
||||
// picoprobe_info("xx %d\n", cnt);
|
||||
break;
|
||||
if (dap_is_connected()) {
|
||||
if (sw_unlock_requested() && !xTimerIsTimerActive(timer_dap_connected)) {
|
||||
picoprobe_info("xx DAP timeout\n");
|
||||
ok = false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (sw_unlock_requested()) {
|
||||
break;
|
||||
picoprobe_info("xx unlock requested\n");
|
||||
ok = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
rtt_console_running = false;
|
||||
xTimerStop(timer_rtt_cb_verify, 100);
|
||||
xTimerStop(timer_dap_connected, 100);
|
||||
} // do_rtt_io
|
||||
|
||||
|
||||
|
||||
static bool target_connect(void)
|
||||
/**
|
||||
* Connect to the target, but let the target run
|
||||
* \return true -> connected to target
|
||||
*/
|
||||
static bool target_connect(void)
|
||||
{
|
||||
bool r = false;
|
||||
|
||||
@@ -609,6 +635,42 @@ static void target_disconnect(void)
|
||||
|
||||
|
||||
|
||||
static void rtt_print_target_info(void)
|
||||
/**
|
||||
* Print target board information
|
||||
*/
|
||||
{
|
||||
picoprobe_info("\n");
|
||||
picoprobe_info("++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n");
|
||||
picoprobe_info("Target vendor : %s\n", g_board_info.target_cfg->target_vendor);
|
||||
picoprobe_info("Target part : %s\n", g_board_info.target_cfg->target_part_number);
|
||||
|
||||
if (g_board_info.target_cfg->flash_regions[0].start == g_board_info.target_cfg->flash_regions[0].end)
|
||||
{
|
||||
picoprobe_error("Flash : NO FLASH DETECTED\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
picoprobe_info("Flash : 0x%08x.. 0x%08x (%uK)\n",
|
||||
(unsigned)g_board_info.target_cfg->flash_regions[0]. start,
|
||||
(unsigned)(g_board_info.target_cfg->flash_regions[0]. end - 1),
|
||||
(unsigned)((g_board_info.target_cfg->flash_regions[0]. end -
|
||||
g_board_info.target_cfg->flash_regions[0]. start) / 1024));
|
||||
}
|
||||
|
||||
picoprobe_info("RAM : 0x%08x..0x%08x (%uK)\n",
|
||||
(unsigned)g_board_info.target_cfg->ram_regions[0].start,
|
||||
(unsigned)(g_board_info.target_cfg->ram_regions[0].end - 1),
|
||||
(unsigned)((g_board_info.target_cfg->ram_regions[0].end -
|
||||
g_board_info.target_cfg->ram_regions[0]. start) / 1024));
|
||||
picoprobe_info("SWD frequency : %ukHz\n", (unsigned)probe_get_swclk_freq_khz());
|
||||
picoprobe_info("SWD max frequency : %ukHz\n", g_board_info.target_cfg->rt_max_swd_khz);
|
||||
picoprobe_info("++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n");
|
||||
picoprobe_info("\n");
|
||||
} // rtt_print_target_info
|
||||
|
||||
|
||||
|
||||
void rtt_io_thread(void *ptr)
|
||||
{
|
||||
uint32_t rtt_cb = 0;
|
||||
@@ -618,10 +680,12 @@ void rtt_io_thread(void *ptr)
|
||||
sw_lock(E_SWLOCK_RTT);
|
||||
// post: we have the interface
|
||||
|
||||
if (dap_connected()) {
|
||||
#if 1
|
||||
if (dap_is_connected()) {
|
||||
//
|
||||
// do RTT while debugging until a DAP command arrives
|
||||
//
|
||||
vTaskDelay(pdMS_TO_TICKS(20));
|
||||
do {
|
||||
if ( !is_target_ok(0)) {
|
||||
break;
|
||||
@@ -631,37 +695,14 @@ void rtt_io_thread(void *ptr)
|
||||
sw_unlock(E_SWLOCK_RTT);
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
|
||||
if ( !target_online) {
|
||||
if (g_board_info.prerun_board_config != NULL) {
|
||||
g_board_info.prerun_board_config();
|
||||
}
|
||||
if (g_board_info.target_cfg->rt_board_id != NULL) {
|
||||
picoprobe_info("\n");
|
||||
picoprobe_info("++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n");
|
||||
//picoprobe_info("Target family : 0x%04x\n", g_target_family->family_id);
|
||||
picoprobe_info("Target vendor : %s\n", g_board_info.target_cfg->target_vendor);
|
||||
picoprobe_info("Target part : %s\n", g_board_info.target_cfg->target_part_number);
|
||||
//picoprobe_info("Board vendor : %s\n", g_board_info.board_vendor);
|
||||
//picoprobe_info("Board name : %s\n", g_board_info.board_name);
|
||||
if (g_board_info.target_cfg->flash_regions[0].start == g_board_info.target_cfg->flash_regions[0].end) {
|
||||
picoprobe_error("Flash : NO FLASH DETECTED\n");
|
||||
}
|
||||
else {
|
||||
picoprobe_info("Flash : 0x%08x..0x%08x (%uK)\n",
|
||||
(unsigned)(g_board_info.target_cfg->flash_regions[0].start),
|
||||
(unsigned)(g_board_info.target_cfg->flash_regions[0].end - 1),
|
||||
(unsigned)((g_board_info.target_cfg->flash_regions[0].end - g_board_info.target_cfg->flash_regions[0].start) / 1024));
|
||||
}
|
||||
picoprobe_info("RAM : 0x%08x..0x%08x (%uK)\n",
|
||||
(unsigned)(g_board_info.target_cfg->ram_regions[0].start),
|
||||
(unsigned)(g_board_info.target_cfg->ram_regions[0].end - 1),
|
||||
(unsigned)((g_board_info.target_cfg->ram_regions[0].end - g_board_info.target_cfg->ram_regions[0].start) / 1024));
|
||||
picoprobe_info("SWD frequency : %ukHz\n", (unsigned)probe_get_swclk_freq_khz());
|
||||
picoprobe_info("SWD max frequency : %ukHz\n", g_board_info.target_cfg->rt_max_swd_khz);
|
||||
picoprobe_info("++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n");
|
||||
picoprobe_info("\n");
|
||||
rtt_cb_alive = false;
|
||||
rtt_print_target_info();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -727,13 +768,18 @@ void rtt_io_thread(void *ptr)
|
||||
vTaskDelay(pdMS_TO_TICKS(200)); // some guard time after disconnect
|
||||
}
|
||||
sw_unlock(E_SWLOCK_RTT);
|
||||
vTaskDelay(pdMS_TO_TICKS(300)); // give the other task the opportunity to catch sw_lock();
|
||||
vTaskDelay(pdMS_TO_TICKS(100)); // give the other task the opportunity to catch sw_lock();
|
||||
}
|
||||
} // rtt_io_thread
|
||||
|
||||
|
||||
|
||||
bool rtt_console_cb_exists(void)
|
||||
/**
|
||||
* Check if RTT console is available
|
||||
*
|
||||
* @return true if console RTT channel is active
|
||||
*/
|
||||
{
|
||||
return rtt_console_running && ok_console_to_target;
|
||||
} // rtt_console_cb_exists
|
||||
@@ -774,8 +820,6 @@ void rtt_console_send_byte(uint8_t ch)
|
||||
void rtt_sysview_send_byte(uint8_t ch)
|
||||
/**
|
||||
* Send a byte to the SysView channel of the target
|
||||
*
|
||||
* TODO currently this is disabled because this aborts SysView operation. Has to be investigated.
|
||||
*/
|
||||
{
|
||||
rtt_send_byte(stream_rtt_sysview_to_target, RTT_CHANNEL_SYSVIEW, ch, true);
|
||||
@@ -803,6 +847,7 @@ void rtt_console_init(uint32_t task_prio)
|
||||
#endif
|
||||
|
||||
timer_rtt_cb_verify = xTimerCreate("RTT_CB verify timeout", pdMS_TO_TICKS(1000), pdFALSE, NULL, rtt_cb_verify_timeout);
|
||||
timer_dap_connected = xTimerCreate("RTT DAP connected timeout", pdMS_TO_TICKS(100), pdFALSE, NULL, rtt_cb_verify_timeout);
|
||||
|
||||
xTaskCreate(rtt_io_thread, "RTT-IO", configMINIMAL_STACK_SIZE, NULL, task_prio, &task_rtt_console);
|
||||
if (task_rtt_console == NULL)
|
||||
|
||||
Reference in New Issue
Block a user