401. Binary Watch

本文介绍了一种利用bitset实现的二进制手表解决方案,详细解释了bitset的各种操作及其在二进制时间显示上的应用。

A binary watch has 4 LEDs on the top which represent the hours (0-11), and the 6 LEDs on the bottom represent the minutes (0-59).

Each LED represents a zero or one, with the least significant bit on the right.

For example, the above binary watch reads "3:25".

Given a non-negative integer n which represents the number of LEDs that are currently on, return all possible times the watch could represent.

Example:

Input: n = 1
Return: ["1:00", "2:00", "4:00", "8:00", "0:01", "0:02", "0:04", "0:08", "0:16", "0:32"]

Note:

  • The order of output does not matter.
  • The hour must not contain a leading zero, for example "01:00" is not valid, it should be "1:00".

  • The minute must be consist of two digits and may contain a leading zero, for example "10:2" is not valid, it should be "10:02".



#i nclude <bitset>


using std::bitset;

表3-6  初始化bitset对象的方法


bitset<n> b;


b有n位,每位都为0


bitset<n> b(u);


b是unsigned long型u的一个副本


bitset<n> b(s);


b是string对象s中含有的位串的副本


bitset<n> b(s, pos, n);


b是s中从位置pos开始的n个位的副本


1. 用unsigned值初始化bitset对象


当用unsigned long值作为bitset对象的初始值时,该值将转化为二进制的位模式。而bitset对象中的位集作为这种位模式的副本。如果bitset类型长度大于unsigned long值的二进制位数,则其余的高阶位置为0;如果bitet类型长度小于unsigned long值的二进制位数,则只使用unsigned值中的低阶位,超过bitet类型长度的高阶位将被丢弃。


在32位unsigned long的机器上,十六进制值0xffff表示为二进制位就是十六个1和十六个0(每个0xf可表示为1111)。可以用0xffff初始化bitset对象:


// bitvec1 is smaller than the initializer


bitset<16> bitvec1(0xffff);          // bits 0 ... 15 are set to 1


// bitvec2 same size as initializer


bitset<32> bitvec2(0xffff);          // bits 0 ... 15 are set to 1; 16 ... 31 are 0


// on a 32-bit machine, bits 0 to 31 initialized from 0xffff


bitset<128> bitvec3(0xffff);         // bits 32 through 127 initialized to zero


上面的三个例子中,0到15位都置为1。由于bitvec1位数少于unsigned long的位数,因此bitvec1的初始值的高阶位被丢弃。bitvec2和unsigned long长度相同,因此所有位正好放置了初始值。bitvec3长度大于32,31位以上的高阶位就被置为0。


2. 用string对象初始化bitset对象


当用string对象初始化bitset对象时,string对象直接表示为位模式。从string对象读入位集的顺序是从右向左:


string strval("1100");


bitset<32> bitvec4(strval);


bitvec4的位模式中第2和3的位置为1,其余位置都为0。如果string对象的字符个数小于bitset类型的长度,则高阶位将置为0。


string对象和bitset对象之间是反向转化的:string对象的最右边字符(即下标最大的那个字符)用来初始化bitset对象的低阶位(即下标为0的位)。当用string对象初始化bitset对象时,记住这一差别很重要。


不一定要把整个string对象都作为bitset对象的初始值。相反,可以只用某个子串作为初始值:


string str("1111111000000011001101");


bitset<32> bitvec5(str, 5, 4); // 4 bits starting at str[5], 1100


bitset<32> bitvec6(str, str.size() - 4);     // use last 4 characters


这里用str中从str[5]开始包含四个字符的子串来初始化bitvec5。照常,初始化bitset对象时总是从子串最右边结尾字符开始的,bitvec5的从0到3的二进制位置为1100,其他二进制位都置为0。如果省略第三个参数则意味着取从开始位置一直到string末尾的所有字符。本例中,取出str末尾的四位来对bitvec6的低四位进行初始化。bitvec6其余的位初始化为0。这些初始化过程的图示如下:






多种bitset操作(表3-7)用来测试或设置bitset对象中的单个或多个二进制位:


表3-7  bitset操作


b.any()


b中是否存在置为1的二进制位?


b.none()


b中不存在置为1的二进制位吗?


b.count()


b中置为1的二进制位的个数


b.size()


b中二进制位的个数


b[pos]


访问b中在pos处的二进制位


b.test(pos)


b中在pos处的二进制位是否为1?


b.set()


把b中所有二进制位都置为1


b.set(pos)


把b中在pos处的二进制位置为1


b.reset()


把b中所有二进制位都置为0


b.reset(pos)


把b中在pos处的二进制位置为0


b.flip()


把b中所有二进制位逐位取反


b.flip(pos)


把b中在pos处的二进制位取反


b.to_ulong()


用b中同样的二进制位返回一个unsigned long值


os << b


把b中的位集输出到os流





因为自己写的代码太直接了 所以贴上大佬的操作:
LeetCode 401. Binary Watch 解题报告 - 骆小坑的填坑之旅 - 博客频道 - youkuaiyun.com  http://blog.youkuaiyun.com/camellhf/article/details/52738031

class Solution {
public:
    vector<string> readBinaryWatch(int num) {
        vector<string> times;


        for (int i = 0; i < 12; i++) {
            bitset<4> h((size_t) i);
            for (int j = 0; j < 60; j++) {
                bitset<6> m((size_t) j);
                if (h.count() + m.count() == num)
                    times.push_back(to_string(i) + (j < 10? ":0": ":") + to_string(j));
            }
        }


        return times;
    }
};

<think>我们正在处理用户的问题:HighTec中core寄存器显示异常(?????)同时watch窗口数据显示异常(显示found或其他错误)的问题排查。 结合用户上一次的问题和回答,我们已知: - 核心寄存器显示问号通常与调试连接、处理器状态、调试配置或内存映射有关。 - 现在用户提到watch窗口也出现异常(显示“found”或其他错误),这通常与变量访问有关,可能是由于同样的根本原因导致,也可能是符号表或内存访问问题。 因此,我们将问题扩展为:在core寄存器显示异常的同时,watch窗口数据异常(如显示“found”或其他错误)的排查步骤。 注意:watch窗口显示“found”可能是调试器在尝试读取变量时发现该内存区域被标记为“已找到”但无法正确解析,或者符号解析错误。 以下是系统化的排查步骤: --- ### **HighTec调试时core寄存器显示?????且watch窗口数据异常(如显示“found”)的排查指南** #### **1. 核心问题定位** 同时出现core寄存器和watch窗口异常,通常表明调试器与目标处理器的通信或状态存在系统级问题。可能原因包括: - **调试连接不稳定**(物理层问题) - **处理器未运行在正常状态**(如处于复位、休眠或硬件错误状态) - **调试配置错误**(如设备型号不匹配、调试脚本错误) - **符号表/内存映射不匹配**(导致变量地址解析错误) - **内存访问冲突**(如变量所在内存区域被保护或未初始化) #### **2. 分步排查流程** **步骤1:验证基础调试连接** - 重新插拔JTAG/SWD连接器,确保接触可靠。 - 降低JTAG时钟频率(建议降至1MHz以下)[^1]。 - 使用示波器检查以下信号质量: - TCK(时钟)的上升/下降时间(应<10%周期) - TDI/TDO/TMS信号过冲(应<0.5V) - 若使用板载调试器,尝试更换为外部调试器。 **步骤2:检查处理器核心状态** - 在HighTec的**Register**视图中,查看`PC`(程序计数器)和`PSW`(程序状态字): - 若`PC=0xFFFFFFF0`,表明处理器处于复位状态。 - 若`PSW.CDE=1`(上下文禁用),则无法访问寄存器[^2]。 - 执行强制复位: ```mermaid graph LR A[点击调试工具栏的'Reset'] --> B{寄存器恢复?} B -->|否| C[断电重启目标板] C --> D[重新连接调试器] ``` **步骤3:验证调试配置** 1. 打开**Debug Configuration** → **Debugger**选项卡: - 确认**Device**型号与芯片完全一致(如TC275T)。 - 检查**Connection**协议(JTAG/SWD)与实际硬件匹配。 2. 在**Initialization**选项卡中: - 验证调试脚本路径正确(如`triCore_init.gdb`)。 - 在脚本中搜索`memmap`命令,确认加载了正确的内存映射文件。 **步骤4:修复符号表与变量访问** - **重新加载符号表**: - 在**Project Explorer**中右击项目 → **Reload Symbols**。 - 或在调试命令行执行: ```bash load symbols MyProject.elf ``` - **检查变量作用域**: - 若watch窗口显示`<not found>`或`<optimized out>`,表明变量被编译器优化。 - 在编译选项中添加`-O0 -g`禁用优化并启用调试信息。 - **手动验证变量地址**: 1. 在**Disassembly**视图中找到变量地址(如`&myVar`)。 2. 在**Memory**视图中输入该地址,检查数据是否正常。 - 若内存数据显示`??`,表明调试器无法访问该地址。 **步骤5:处理内存访问冲突** - **解锁内存保护单元(MPU)**: 在调试命令行执行: ```gdb set *((int*)0xF0000A00) = 0xA5 # 解锁MPU寄存器 ``` - **检查总线错误状态寄存器**: - 读取`DBGSR`(调试状态寄存器): ```c uint32_t dbgsr = *((volatile uint32_t*)0xF0000A10); if (dbgsr & 0x80) { // 检查BUSERR位 printf("检测到总线错误!\n"); } ``` #### **3. 高级修复技巧** **技巧1:强制重载内存映射** ```gdb # 在HighTec调试命令行执行 memory map clear memory map load C:/HighTec/tools/triCore/memmap/TC27x_memory_map.xml attach ``` **技巧2:注入调试恢复代码** 在启动文件(如`startup.asm`)中添加调试解锁序列: ```assembly MOV DCON0, #0x0000 ; 禁用数据缓存 MOV PCON0, #0x0000 ; 禁用指令缓存 LDR R0, =0xF0000A00 ; MPU密钥寄存器地址 MOV R1, #0xA5 STR R1, [R0] ; 解锁MPU ``` **技巧3:捕获实时异常** 若watch窗口异常由硬件错误触发: 1. 在**Expressions**视图中添加`__TRICORE_DBGSR`(调试状态寄存器)。 2. 配置数据断点于`0xF0000A10`(DBGSR地址),触发条件为`value & 0x80`(总线错误)。 #### **4. 预防性措施** - **优化JTAG信号**: - 在TCK/TMS上串联33Ω电阻。 - 在TDI/TDO上添加20pF电容滤波。 - **固件层防护**: ```c void debug_enable(void) { // 启用所有调试功能 __asm volatile ("mov d:0xE000EDF0, 0xA05F0000"); // 解锁核心调试 __asm volatile ("mov d:0xF0000A00, 0xA5"); // 解锁MPU } ``` 在`main()`函数首行调用该函数。 --- ### **根本原因分析表** | 现象组合 | 最可能原因 | 验证方法 | |-------------------------|---------------------|------------------------------| | 寄存器?? + watch found | 内存映射冲突 | 执行`memory map load`命令 | | 寄存器部分?? + 变量错误 | 处理器休眠/复位 | 检查PC和PSW寄存器 | | 仅watch窗口异常 | 符号表损坏/优化 | 重新编译并加载ELF文件 | [^1]: HighTec调试器硬件手册第3.2节“信号完整性要求” [^2]: TriCore TC1.6.P架构手册第23章“调试系统” §§相关问题§§ 1. HighTec中如何配置内存保护单元(MPU)以避免调试冲突? 2. 如何为HighTec调试器编写自定义的GDB脚本? 3. 在TriCore芯片中如何捕获和解析总线错误(Bus Error)? 4. HighTec开发环境中的watch窗口有哪些高级使用技巧?</think>### HighTec调试时Core寄存器显示?????且Watch窗口显示异常(如"found")问题排查 当HighTte开发环境中同时出现**Core寄存器显示?????** 和 **Watch窗口数据显示异常(如"found")** 时,表明调试器与目标处理器的通信存在系统性故障。以下是结构化排查流程: --- #### **1. 问题根源快速定位** | 现象组合 | 高概率原因 | 关键检查点 | |------------------------|--------------------|----------------------------| | 寄存器?? + Watch异常 | 内存映射冲突 | `DBGSR`寄存器状态[^1] | | 寄存器部分?? + Watch异常| 处理器状态异常 | `PC`和`PSW`寄存器值 | | 仅Watch窗口"found"错误 | 符号表损坏 | ELF文件调试段完整性 | --- #### **2. 关键排查步骤** **步骤1:验证基础通信状态** ```mermaid graph TD A[检查JTAG/SWD连接] --> B{信号质量?} B -->|不稳定| C[降低时钟至1MHz] B -->|稳定| D[检查电源纹波<50mV] C --> E[添加RC滤波] D --> F[读取核心调试寄存器] ``` - **操作建议**: - 用示波器测量TCK/TMS信号(上升时间应 < 10%周期) - 在TDI/TDO线上增加22pF滤波电容 - 执行强制复位命令:`reset -hard`(在调试控制台) **步骤2:诊断处理器状态** - 在调试命令行读取关键寄存器: ```bash # 检查处理器状态 readreg PC # 正常值应 ≠ 0xFFFFFFFF readreg PSW # 检查CDE=0(上下文未禁用) readreg DBGSR # 若BUSERR=1表示总线错误 ``` - **异常处理**: - 若`PC=0xFFFFFFF0`:执行`power cycle`硬件重启 - 若`DBGSR.BUSERR=1`:检查内存保护单元(MPU)配置 **步骤3:修复Watch窗口异常** ```c // 在main()函数添加调试哨兵 volatile uint32_t *DBGKEY = (uint32_t*)0xE000EDF0; *DBGKEY = 0xA05F0000; // 解锁调试访问[^2] // 检查变量优化状态 __attribute__((used)) volatile int debug_sentinel; // 防止被优化 ``` - **符号表修复**: 1. 重新生成ELF文件:`Build Project`(确保勾选`-g -O0`选项) 2. 强制重载符号: ```bash load symbols MyProject.elf memory map clear memory map load TC27x_memory_map.xml ``` **步骤4:内存映射同步** - 创建内存映射校验脚本(保存为`validate_memmap.gdb`): ```gdb # 比较调试器与固件的内存映射 set $base = 0xE0000000 if *((uint32_t*)$base) != *((uint32_t*)0xF0000000) echo "内存映射冲突!\n" dump binary memory conflict.bin $base ($base+256) endif ``` 在HighTec调试配置中加载此脚本。 --- #### **3. 高级修复技巧** **技巧1:实时内存访问诊断** ```bash # 在HighTec Terminal执行 monitor read 0xE000ED00 4 # 读取4字节核心寄存器 monitor write 0xF0000A00 0xA5 # 解锁MPU ``` - **逻辑分析仪捕获**: - 配置触发条件:当TMS连续5个周期高电平时(JTAG复位) - 验证TDO响应延迟 < 0.5个时钟周期 **技巧2:Watch窗口异常专用修复** ```mermaid graph LR A[Watch显示"found"] --> B{检查变量地址} B -->|地址无效| C[修正链接脚本] B -->|地址有效| D[检查内存保护] D -->|MPU启用| E[添加内存域规则] D -->|MPU禁用| F[验证总线矩阵] ``` **技巧3:固件层修复** 在启动文件(`startup.asm`)添加: ```assembly ; 调试访问解锁序列 MOV DCON0, #0x0000 ; 禁用数据缓存 MOV PCON0, #0x0000 ; 禁用指令缓存 LDR R0, =0xF0000A00 ; MPU密钥寄存器地址 MOV R1, #0xA5 STR R1, [R0] ; 解锁MPU ``` --- #### **4. 信号完整性规范** 确保JTAG信号满足时序要求: $$ t_{su} \geq \frac{1}{2f_{CLK}} + 3ns $$ 其中: - $t_{su}$ = 信号建立时间 - $f_{CLK}$ = JTAG时钟频率 - 保持时间裕量 ≥ 2ns [^1]: TriCore TC1.6.P架构手册第23章“调试系统” [^2]: HighTec调试器用户手册第7.5节“核心寄存器访问”
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值