From 35371df671e3677d896fcde516eaec3a899b5d8f Mon Sep 17 00:00:00 2001 From: William Wilgus Date: Tue, 1 Sep 2020 03:22:48 -0400 Subject: XduooX3 Debug Menu -- HW_info add scrolling for clocks and such moved to a switch based structure.. this ends up a lot cleaner Change-Id: I940506c4b8dc73f0b776d20810780527cbf7e0d4 --- firmware/target/mips/ingenic_jz47xx/debug-jz4760.c | 467 +++++++++++++++------ 1 file changed, 339 insertions(+), 128 deletions(-) (limited to 'firmware') diff --git a/firmware/target/mips/ingenic_jz47xx/debug-jz4760.c b/firmware/target/mips/ingenic_jz47xx/debug-jz4760.c index 301f72a12e..567c1798c7 100644 --- a/firmware/target/mips/ingenic_jz47xx/debug-jz4760.c +++ b/firmware/target/mips/ingenic_jz47xx/debug-jz4760.c @@ -7,6 +7,7 @@ * \/ \/ \/ \/ \/ * * Copyright (C) 2018 by Solomon Peachy + * Copyright (C) 2020 by William Wilgus * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -31,14 +32,19 @@ #ifndef BOOTLOADER #include "action.h" +#include "list.h" +static bool is_done = false; static int line = 0; +static int maxlines = 0; /* * Clock Generation Module */ -#define TO_MHZ(x) ((x)/1000000), ((x)%1000000)/10000 -#define TO_KHZ(x) ((x)/1000), ((x)%1000)/10 +#define DBG_FREQ_FMT "%s:%3d.%02d %cHz" /*IDSTR, 000 HZ INT, 00HZ FRAC, _/K/M */ +#define TO_MHZ(x) ((x)/1000000), ((x)%1000000)/10000, 'M' +#define TO_KHZ(x) ((x)/1000), ((x)%1000)/10, 'K' + #define DEBUG_CANCEL ACTION_STD_CANCEL #define DEBUG_NEXT ACTION_STD_NEXT @@ -50,126 +56,259 @@ static int line = 0; #define ON "Enabled" #define OFF "Disabled" +#define STOPPED "Stopped" +#define RUNNING "Running" static bool dbg_btn(bool *done, int *x) { bool cont = !*done; if (cont) { - lcd_update(); int button = get_action(CONTEXT_STD,HZ/10); switch(button) { case DEBUG_CANCEL: *done = true; + case DEBUG_NEXT: cont = false; case DEBUG_LEFT_JUSTIFY: - (*x) = 0; + if (x){(*x) = 0;} sleep(HZ/5); break; case DEBUG_LEFT_SCROLL: - (*x)--; + if(x){(*x)--;} + break; } } + return cont; +} + +static bool dbg_btn_update(bool *done, int *x) +{ + bool cont = !*done; + if (cont) + { + lcd_update(); + cont = dbg_btn(done, x); + } lcd_clear_display(); return cont; } -static void display_clocks(void) +static inline unsigned int read_cp0_15 (void) +{ + /* CPUID Cp0 Register 15 Select 0 */ + unsigned int cp_val; + asm volatile("mfc0 %0, $15\n" : "=r" (cp_val)); + return (cp_val); +} + +static bool display_clocks(void) { unsigned int cppcr0 = REG_CPM_CPPCR0; /* PLL Control Register */ unsigned int cppcr1 = REG_CPM_CPPCR1; /* PLL Control Register */ unsigned int div[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32}; unsigned int od[4] = {1, 2, 4, 8}; - lcd_putsf(0, line++, "CPPCR0:0x%08x", cppcr0); - if (cppcr0 & CPPCR0_PLLEN) { - lcd_putsf(0, line++, "PLL0 :%3d.%02d MHz", TO_MHZ(__cpm_get_pllout())); - lcd_putsf(0, line++, "m:n:o :%d:%d:%d", - __cpm_get_pllm(), - __cpm_get_plln(), - od[__cpm_get_pllod()] - ); - } - lcd_putsf(0, line++, "CPPCR1:0x%08x", cppcr1); - if (cppcr1 & CPPCR1_PLL1EN) { - lcd_putsf(0, line++, "PLL1 :%3d.%02d MHz", TO_MHZ(__cpm_get_pll1out())); - lcd_putsf(0, line++, "m:n:o :%d:%d:%d", - __cpm_get_pll1m(), - __cpm_get_pll1n(), - od[__cpm_get_pll1od()] - ); + int x = 0; + int cur_item = -1; + bool is_last_item = false; + + while(!is_done) + { + lcd_clear_display(); + + if (is_last_item || cur_item < 0) + cur_item = 0; + else if (cur_item >= 0) + cur_item += maxlines; + + is_last_item = false; + + while(dbg_btn(&is_done, &x)) + { + lcd_clear_display(); + line = 0; + switch(cur_item) + { + case 0: + lcd_putsf(x, line++, "[%s]", "Clocks"); + case 1: + lcd_putsf(x, line++, "CPPCR0:0x%08x", cppcr0); + case 2: + if (cppcr0 & CPPCR0_PLLEN) { + lcd_putsf(x, line++, DBG_FREQ_FMT, "PLL0 ", + TO_MHZ(__cpm_get_pllout())); + lcd_putsf(x, line++, "m:n:o :%d:%d:%d", + __cpm_get_pllm(), + __cpm_get_plln(), + od[__cpm_get_pllod()] + ); + } + else if (cur_item == 2) + cur_item++; + case 3: + lcd_putsf(x, line++, "CPPCR1:0x%08x", cppcr1); + case 4: + if (cppcr1 & CPPCR1_PLL1EN) { + lcd_putsf(x, line++, DBG_FREQ_FMT, "PLL1 ", + TO_MHZ(__cpm_get_pll1out())); + lcd_putsf(x, line++, "m:n:o :%d:%d:%d", + __cpm_get_pll1m(), + __cpm_get_pll1n(), + od[__cpm_get_pll1od()] + ); + } + else if (cur_item == 3) + cur_item++; + case 5: + lcd_putsf(x, line++, "C:H:M:P:%d:%d:%d:%d", + div[__cpm_get_cdiv()], + div[__cpm_get_hdiv()], + div[__cpm_get_mdiv()], + div[__cpm_get_pdiv()] + ); + case 6: + lcd_putsf(x, line++, "I:P:M : %d:%d:%d", + __cpm_get_i2sdiv()+1, + __cpm_get_pixdiv()+1, + __cpm_get_mscdiv()+1 + ); + case 7: + lcd_putsf(x, line++, DBG_FREQ_FMT, "CCLK ", + TO_MHZ(__cpm_get_cclk())); + case 8: + lcd_putsf(x, line++, DBG_FREQ_FMT, "HCLK ", + TO_MHZ(__cpm_get_hclk())); + case 9: + lcd_putsf(x, line++, DBG_FREQ_FMT, "MCLK ", + TO_MHZ(__cpm_get_mclk())); + case 10: + lcd_putsf(x, line++, DBG_FREQ_FMT, "PCLK ", + TO_MHZ(__cpm_get_pclk())); + case 11: + lcd_putsf(x, line++, DBG_FREQ_FMT, "PIXCLK ", + TO_KHZ(__cpm_get_pixclk())); + case 12: + lcd_putsf(x, line++, DBG_FREQ_FMT, "I2SCLK ", + TO_MHZ(__cpm_get_i2sclk())); + case 13: + lcd_putsf(x, line++, DBG_FREQ_FMT, "MSCCLK ", + TO_MHZ(__cpm_get_mscclk())); + case 14: + lcd_putsf(x, line++, DBG_FREQ_FMT, "XTALCLK ", + TO_MHZ(__cpm_get_extalclk())); + case 15: + lcd_putsf(x, line++, DBG_FREQ_FMT, "RTCCLK ", + TO_KHZ(__cpm_get_rtcclk())); + default: + if (line <= maxlines + 1) + is_last_item = true; + } + lcd_update(); + } } - lcd_putsf(0, line++, "C:H:M:P:%d:%d:%d:%d", - div[__cpm_get_cdiv()], - div[__cpm_get_hdiv()], - div[__cpm_get_mdiv()], - div[__cpm_get_pdiv()] - ); - lcd_putsf(0, line++, "I:P:M : %d:%d:%d", - __cpm_get_i2sdiv()+1, - __cpm_get_pixdiv()+1, - __cpm_get_mscdiv()+1 - ); - lcd_putsf(0, line++, "CCLK :%3d.%02d MHz", TO_MHZ(__cpm_get_cclk())); - lcd_putsf(0, line++, "HCLK :%3d.%02d MHz", TO_MHZ(__cpm_get_hclk())); - lcd_putsf(0, line++, "MCLK :%3d.%02d MHz", TO_MHZ(__cpm_get_mclk())); - lcd_putsf(0, line++, "PCLK :%3d.%02d MHz", TO_MHZ(__cpm_get_pclk())); - lcd_putsf(0, line++, "PIXCLK:%6d.%02d KHz", TO_KHZ(__cpm_get_pixclk())); - lcd_putsf(0, line++, "I2SCLK:%3d.%02d MHz", TO_MHZ(__cpm_get_i2sclk())); - lcd_putsf(0, line++, "MSCCLK:%3d.%02d MHz", TO_MHZ(__cpm_get_mscclk())); - lcd_putsf(0, line++, "EXTALCLK:%3d.%02d MHz", TO_MHZ(__cpm_get_extalclk())); - lcd_putsf(0, line++, "RTCCLK:%3d.%02d KHz", TO_KHZ(__cpm_get_rtcclk())); + return true; } -static void display_enabled_clocks(void) +static bool display_enabled_clocks(void) { unsigned long lcr = REG_CPM_LCR; unsigned long clkgr0 = REG_CPM_CLKGR0; + int x = 0; + int cur_item = -1; + bool is_last_item = false; + + while(!is_done) + { + lcd_clear_display(); + + if (is_last_item || cur_item < 0) + cur_item = 0; + else if (cur_item >= 0) + cur_item += maxlines; - lcd_putsf(0, line++, "Low Power Mode : %s", - ((lcr & LCR_LPM_MASK) == LCR_LPM_IDLE) ? - "IDLE" : (((lcr & LCR_LPM_MASK) == LCR_LPM_SLEEP) ? "SLEEP" : "HIBERNATE") - ); - - lcd_putsf(0, line++, "Doze Mode : %s", - (lcr & LCR_DOZE) ? "ON" : "OFF"); - if (lcr & LCR_DOZE) - lcd_putsf(0, line++, " duty : %d", (int)((lcr & LCR_DUTY_MASK) >> LCR_DUTY_LSB)); - - lcd_putsf(0, line++, "IPU : %s", - (clkgr0 & CLKGR0_IPU) ? "stopped" : "running"); - lcd_putsf(0, line++, "DMAC : %s", - (clkgr0 & CLKGR0_DMAC) ? "stopped" : "running"); - lcd_putsf(0, line++, "UHC : %s", - (clkgr0 & CLKGR0_UHC) ? "stopped" : "running"); - lcd_putsf(0, line++, "LCD : %s", - (clkgr0 & CLKGR0_LCD) ? "stopped" : "running"); - lcd_putsf(0, line++, "CIM : %s", - (clkgr0 & CLKGR0_CIM) ? "stopped" : "running"); - lcd_putsf(0, line++, "SADC : %s", - (clkgr0 & CLKGR0_SADC) ? "stopped" : "running"); - lcd_putsf(0, line++, "MSC0 : %s", - (clkgr0 & CLKGR0_MSC0) ? "stopped" : "running"); - lcd_putsf(0, line++, "MSC1 : %s", - (clkgr0 & CLKGR0_MSC1) ? "stopped" : "running"); - lcd_putsf(0, line++, "MSC2 : %s", - (clkgr0 & CLKGR0_MSC2) ? "stopped" : "running"); - lcd_putsf(0, line++, "AIC : %s", - (clkgr0 & CLKGR0_AIC) ? "stopped" : "running"); - lcd_putsf(0, line++, "SSI1 : %s", - (clkgr0 & CLKGR0_SSI1) ? "stopped" : "running"); - lcd_putsf(0, line++, "SSI2 : %s", - (clkgr0 & CLKGR0_SSI2) ? "stopped" : "running"); - lcd_putsf(0, line++, "I2C0 : %s", - (clkgr0 & CLKGR0_I2C0) ? "stopped" : "running"); - lcd_putsf(0, line++, "I2C1 : %s", - (clkgr0 & CLKGR0_I2C1) ? "stopped" : "running"); - lcd_putsf(0, line++, "UART1 : %s", - (clkgr0 & CLKGR0_UART1) ? "stopped" : "running"); - lcd_putsf(0, line++, "UART0 : %s", - (clkgr0 & CLKGR0_UART0) ? "stopped" : "running"); + is_last_item = false; + + while(dbg_btn(&is_done, &x)) + { + lcd_clear_display(); + line = 0; + switch(cur_item) + { + case 0: + lcd_putsf(x, line++, "[%s]", "Enabled Clocks"); + case 1: + lcd_putsf(x, line++, "Low Power Mode : %s", + ((lcr & LCR_LPM_MASK) == LCR_LPM_IDLE) ? + "IDLE" : (((lcr & LCR_LPM_MASK) == LCR_LPM_SLEEP) ? "SLEEP" : "HIBERNATE") + ); + case 2: + lcd_putsf(x, line++, "Doze Mode : %s", + (lcr & LCR_DOZE) ? "ON" : "OFF"); + case 3: + if (lcr & LCR_DOZE) + lcd_putsf(x, line++, " duty : %d", + (int)((lcr & LCR_DUTY_MASK) >> LCR_DUTY_LSB)); + else if (cur_item == 2) + cur_item++; + case 4: + lcd_putsf(x, line++, "IPU : %s", + (clkgr0 & CLKGR0_IPU) ? STOPPED : RUNNING); + case 5: + lcd_putsf(x, line++, "DMAC : %s", + (clkgr0 & CLKGR0_DMAC) ? STOPPED : RUNNING); + case 6: + lcd_putsf(x, line++, "UHC : %s", + (clkgr0 & CLKGR0_UHC) ? STOPPED : RUNNING); + case 7: + lcd_putsf(x, line++, "LCD : %s", + (clkgr0 & CLKGR0_LCD) ? STOPPED : RUNNING); + case 8: + lcd_putsf(x, line++, "CIM : %s", + (clkgr0 & CLKGR0_CIM) ? STOPPED : RUNNING); + case 9: + lcd_putsf(x, line++, "SADC : %s", + (clkgr0 & CLKGR0_SADC) ? STOPPED : RUNNING); + case 10: + lcd_putsf(x, line++, "MSC0 : %s", + (clkgr0 & CLKGR0_MSC0) ? STOPPED : RUNNING); + case 11: + lcd_putsf(x, line++, "MSC1 : %s", + (clkgr0 & CLKGR0_MSC1) ? STOPPED : RUNNING); + case 12: + lcd_putsf(x, line++, "MSC2 : %s", + (clkgr0 & CLKGR0_MSC2) ? STOPPED : RUNNING); + case 13: + lcd_putsf(x, line++, "AIC : %s", + (clkgr0 & CLKGR0_AIC) ? STOPPED : RUNNING); + case 14: + lcd_putsf(x, line++, "SSI1 : %s", + (clkgr0 & CLKGR0_SSI1) ? STOPPED : RUNNING); + case 15: + lcd_putsf(x, line++, "SSI2 : %s", + (clkgr0 & CLKGR0_SSI2) ? STOPPED : RUNNING); + case 16: + lcd_putsf(x, line++, "I2C0 : %s", + (clkgr0 & CLKGR0_I2C0) ? STOPPED : RUNNING); + case 17: + lcd_putsf(x, line++, "I2C1 : %s", + (clkgr0 & CLKGR0_I2C1) ? STOPPED : RUNNING); + case 18: + lcd_putsf(x, line++, "UART1 : %s", + (clkgr0 & CLKGR0_UART1) ? STOPPED : RUNNING); + case 19: + lcd_putsf(x, line++, "UART0 : %s", + (clkgr0 & CLKGR0_UART0) ? STOPPED : RUNNING); + default: + if (line <= maxlines + 1) + is_last_item = true; + } + lcd_update(); + } + } + return true; } bool dbg_ports(void) @@ -191,10 +330,10 @@ bool dbg_ports(void) while(!done) { i = 0; - while(dbg_btn(&done, &x)) + while(dbg_btn_update(&done, &x)) { i %= last_port; /*PORT: A B C D E F */ - while(dbg_btn(&done, &x)) + while(dbg_btn_update(&done, &x)) { line = 0; lcd_puts(x, line++, "[GPIO Vals and Dirs]"); @@ -218,50 +357,11 @@ bool dbg_ports(void) } lcd_setfont(FONT_UI); -#endif +#endif /* CONFIG_CPU ==JZ4760B */ return false; } -extern uint32_t irqstackend,irqstackbegin; - -bool dbg_hw_info(void) -{ - int btn = 0; -#ifdef HAVE_TOUCHSCREEN - int touch; -#endif - struct tm *cur_time; - - lcd_setfont(FONT_SYSFIXED); - while(btn ^ BUTTON_POWER) - { - lcd_clear_display(); - line = 0; - - uint32_t *ptr = &irqstackbegin; - for ( ; ptr < &irqstackend && *ptr == 0xDEADBEEF; ptr++) {} - - lcd_putsf(0, line++, "IRQ stack max: %d", (uint32_t)&irqstackend - (uint32_t)ptr); - - display_clocks(); - display_enabled_clocks(); -#ifdef HAVE_TOUCHSCREEN - btn = button_read_device(&touch); - lcd_putsf(0, line++, "X: %d Y: %d BTN: 0x%X", touch>>16, touch&0xFFFF, btn); -#else - btn = button_read_device(); -#endif - cur_time = get_time(); - lcd_putsf(0, line++, "%02d/%02d/%04d %02d:%02d:%02d", cur_time->tm_mday, - cur_time->tm_mon, cur_time->tm_year, cur_time->tm_hour, - cur_time->tm_min, cur_time->tm_sec); - lcd_update(); - sleep(HZ/16); - } - lcd_setfont(FONT_UI); - return true; -} #endif #ifdef BOOTLOADER @@ -370,3 +470,114 @@ void serial_dump_data(unsigned char* data, int len) serial_putc( '\n' ); } #endif + +#ifndef BOOTLOADER +static const struct { + unsigned char *desc; /* string or ID */ + bool (*function) (void); /* return true if USB was connected */ +} hwinfo_items[] = { + { "", NULL }, /*RTC*/ + { "", NULL }, /*CPUID*/ + { "", NULL }, /*IRQSTACKMAX*/ + { "Clocks", display_clocks}, + { "Enabled Clocks", display_enabled_clocks}, + { "", NULL}, /*TOUCH/BTN*/ + +}; + +static int hw_info_menu_action_cb(int btn, struct gui_synclist *lists) +{ + static long last_refresh = 0; + int selection = gui_synclist_get_sel_pos(lists); + if (btn == ACTION_STD_OK) + { + FOR_NB_SCREENS(i) + viewportmanager_theme_enable(i, false, NULL); + if (hwinfo_items[selection].function) + { + is_done = false; + hwinfo_items[selection].function(); + } + btn = ACTION_REDRAW; + FOR_NB_SCREENS(i) + viewportmanager_theme_undo(i, false); + } + else if (btn == ACTION_STD_CONTEXT) + { + } + else if (btn == 0 && TIME_AFTER(current_tick, last_refresh + HZ / 2)) + { + last_refresh = current_tick; + btn = ACTION_REDRAW; + /* to make menu items update */ + } + return btn; +} + +static const char* hw_info_menu_get_name(int item, void * data, + char *buffer, size_t buffer_len) +{ + (void)data; + struct tm *cur_time; + uint32_t *stackptr; + extern uint32_t irqstackend,irqstackbegin; + int btn; +#ifdef HAVE_TOUCHSCREEN + int touch; +#endif + + switch(item) + { + /* create your dynamic items here */ + case 0:/*RTC*/ + cur_time = get_time(); + snprintf(buffer, buffer_len, "%02d/%02d/%04d %02d:%02d:%02d", + cur_time->tm_mday,cur_time->tm_mon, cur_time->tm_year, + cur_time->tm_hour, cur_time->tm_min, cur_time->tm_sec); + return buffer; + case 1: /*cpuID*/ + snprintf(buffer, buffer_len, "CPUID %X:%d", + read_cp0_15(), (REG_CPM_CLKGR0 & BIT31) >> 31); + return buffer; + case 2: /*IRQstack*/ + stackptr = &irqstackbegin; + for ( ; stackptr < &irqstackend && *stackptr == 0xDEADBEEF; stackptr++) {} + snprintf(buffer, buffer_len, "IRQ stack max: %lu", + (uint32_t)&irqstackend - (uint32_t)stackptr); + return buffer; + case 5: /*Touch/BTN*/ +#ifdef HAVE_TOUCHSCREEN + btn = button_read_device(&touch); + snprintf(buffer, buffer_len, "X: %d Y: %d BTN: 0x%X", + touch>>16, touch&0xFFFF, btn); +#else + btn = button_read_device(); + snprintf(buffer, buffer_len, "BTN: 0x%X", btn); +#endif + return buffer; + default: /* static items -- default */ + return hwinfo_items[item].desc; + } + return "???"; +} + +static int hw_info_debug_menu(void) +{ + int h; + lcd_setfont(FONT_SYSFIXED); + lcd_getstringsize((unsigned char *)"A", NULL, &h); + maxlines = LCD_HEIGHT / h - 1; + is_done = false; + struct simplelist_info info; + + simplelist_info_init(&info, "Hw Info", ARRAYLEN(hwinfo_items), NULL); + info.action_callback = hw_info_menu_action_cb; + info.get_name = hw_info_menu_get_name; + return (simplelist_show_list(&info)) ? 1 : 0; +} + +bool dbg_hw_info(void) +{ + return hw_info_debug_menu() > 0; +} +#endif -- cgit v1.2.3