/* set voltage internal voltage to 1.8V */ RCC->APB1ENR |= RCC_APB1ENR_PWREN; PWR->CR = PWR_CR_VOS_0; phal_clk_init(); /* enable peripheral and GPIO clocks */ RCC->IOPENR |= GPIO_CLOCKS; RCC->APB1ENR |= APB1_CLOCKS; RCC->APB2ENR |= APB2_CLOCKS; RCC->AHBENR |= AHB_CLOCKS; phal_timer_init(); #if (USE_DMA_FOR_UART_TX == IOL_FEATURE_ENABLED) phal_dma_init(); #endif #if (AL_TRIGGER == AL_FROM_INTERRUPT) phal_al_sw_interrupt_setup(); #endif
时间: 2023-04-09 21:03:56 浏览: 305
这段代码的作用是将内部电压设置为1.8V,然后初始化时钟和定时器,并启用外设和GPIO时钟。其中,RCC代表时钟控制寄存器,PWR代表电源控制寄存器,APB1ENR、APB2ENR、AHBENR分别代表不同的时钟总线。GPIO_CLOCKS、APB1_CLOCKS、APB2_CLOCKS、AHB_CLOCKS则是不同的外设和GPIO时钟。
相关问题
while ((PWR->CSR1 & PWR_CSR1_ACTVOSRDY) == 0U)我在用debug的时候在这句话有*** error 65: access violation at 0x58024804 : no 'read' permission错误
<think>嗯,用户在使用调试器的时候遇到了一个错误:*** error 65: access violation at 0x58024804 : no 'read' permission。这个问题发生在代码中的while循环语句:while ((PWR->CSR1 & PWR_CSR1_ACTVOSRDY) == 0U)。首先,我需要理解这个错误的具体原因,以及如何解决它。
首先,访问冲突错误通常意味着程序试图访问一个它没有权限的内存地址。这里的地址是0x58024804,看起来像是某个外设的寄存器地址。用户提到的PWR->CSR1,应该是STM32中的电源控制寄存器(PWR模块的CSR1寄存器)。在STM32中,外设寄存器的访问通常需要特定的权限,特别是在调试或运行时。
接下来,我需要考虑几个可能的原因:
1. **寄存器地址错误**:可能PWR->CSR1的地址不正确,或者该寄存器在该型号的MCU中不存在。比如,不同系列的STM32可能有不同的寄存器布局,用户可能在使用的MCU型号中,这个寄存器的地址不同,或者根本没有这个寄存器。
2. **时钟未启用**:访问外设寄存器前,通常需要先使能对应的外设时钟。例如,PWR模块的时钟可能没有被启用,导致无法访问其寄存器。用户需要检查是否在代码中正确启用了PWR的时钟,比如通过RCC->APB1ENR或类似的寄存器。
3. **权限问题**:在某些情况下,特别是在调试时,MCU可能处于某种低功耗模式或调试状态,导致某些寄存器的访问被禁止。或者,内存保护单元(MPU)的设置可能阻止了对该地址的读取访问。
4. **硬件连接问题**:调试器连接不稳定,或者目标板供电异常,导致无法正确读取寄存器。
5. **代码优化问题**:编译器优化可能会影响寄存器的访问,比如优化掉某些必要的读取操作,但这种情况可能较少导致访问冲突。
接下来,我需要针对这些可能性逐一分析,并提供解决方案:
首先,用户需要确认使用的MCU型号是否与代码中的寄存器定义匹配。例如,STM32H7系列中的PWR模块可能有不同的寄存器结构,而用户可能错误地引用了不存在的寄存器。比如,CSR1可能在特定系列中存在,而在其他系列中不存在,或者名称不同。
其次,检查时钟配置。例如,在访问PWR寄存器之前,必须确保已经通过RCC(复位和时钟控制)模块启用了PWR的时钟。例如,在STM32中,通常需要使用RCC->APB1ENR1或类似的寄存器来使能PWR时钟。例如,用户可能需要添加类似__HAL_RCC_PWR_CLK_ENABLE()的语句(如果使用HAL库)或者直接设置对应的RCC寄存器位。
另外,如果用户使用的是调试器,可能需要检查调试配置是否正确,比如是否在调试会话中正确暂停了MCU,是否有足够的权限来访问内存区域。有时候,在调试时如果MCU处于低功耗模式,某些外设可能被关闭,导致无法访问其寄存器。此时,可能需要确保在访问寄存器之前,MCU处于运行模式,并且相关外设已正确初始化。
此外,用户还需要检查链接器脚本和启动文件是否正确配置,确保所有的外设寄存器区域被正确映射,并且具有可读权限。如果使用了MPU,可能需要调整内存区域的权限设置,允许调试器读取该地址。
最后,用户可以通过直接读取内存地址来验证是否可以访问该寄存器。例如,在调试器中尝试手动读取0x58024804地址的值,如果仍然出现访问冲突,说明问题可能出在硬件配置、权限或寄存器不存在上。如果手动读取成功,则可能是代码中的其他问题,比如变量定义错误或编译器优化导致的问题。
总结来说,用户需要逐步排查寄存器地址的正确性、时钟使能状态、调试器权限以及硬件连接等问题,以解决访问冲突错误。</think>在调试中遇到 `*** error 65: access violation at 0x58024804 : no 'read' permission` 错误时,说明程序试图访问一个 **无读取权限的内存地址**(此处是电源控制寄存器 `PWR->CSR1`)。以下是逐步分析和解决方案:
---
### **1. 根本原因分析**
- **地址权限问题**:`0x58024804` 是 `PWR->CSR1` 的物理地址,但当前代码或调试环境无法读取它。
- **可能原因**:
- 未启用 `PWR` 外设时钟。
- 寄存器地址与芯片型号不匹配(例如使用了错误的头文件)。
- 调试器权限不足(如未正确连接或配置)。
- 芯片处于低功耗模式,外设被关闭。
---
### **2. 解决方案**
#### **步骤1:确认芯片型号与寄存器定义**
- 检查数据手册或参考手册,确认当前芯片的 `PWR_CSR1` 寄存器是否存在,且地址 `0x58024804` 正确。
- **示例**:
- STM32H7 系列中 `PWR->CSR1` 有效,但某些旧型号(如 STM32F4)可能无此寄存器。
#### **步骤2:启用 PWR 外设时钟**
- 访问外设寄存器前,必须通过 RCC 使能时钟:
```c
// 使用 HAL 库(推荐):
__HAL_RCC_PWR_CLK_ENABLE();
// 直接操作寄存器(针对 STM32):
RCC->APB1ENR |= RCC_APB1ENR_PWREN; // 具体寄存器名需根据芯片型号调整
```
#### **步骤3:检查调试器配置**
- 确保调试器(如 ST-Link)已正确连接,且权限允许读取外设寄存器。
- 在调试工具(如 STM32CubeIDE)中,确认:
- 调试配置选择正确的芯片型号。
- 没有启用“禁止外设访问”等保护选项。
#### **步骤4:验证芯片状态**
- 若芯片处于低功耗模式(如 Sleep/Stop 模式),外设可能被关闭。尝试:
- 复位芯片后立即执行代码。
- 退出低功耗模式后再访问寄存器。
#### **步骤5:手动读取寄存器(调试器验证)**
- 在调试器中直接读取 `0x58024804`:
- 若仍报错:说明权限或硬件问题。
- 若可读取:检查代码逻辑(如变量映射、编译器优化)。
---
### **3. 代码示例(STM32H7)**
```c
// 使能 PWR 时钟
__HAL_RCC_PWR_CLK_ENABLE();
// 等待 ACTVOSRDY 标志置位
while ((PWR->CSR1 & PWR_CSR1_ACTVOSRDY) == 0U) {
// 超时处理(可选)
if (timeout_expired) {
Error_Handler();
}
}
```
---
### **4. 扩展排查**
- **检查链接脚本和启动文件**:确保外设内存区域(如 `0x5802_0000`)被正确映射。
- **MPU 配置**:若启用内存保护单元(MPU),需允许对该地址的读取。
- **硬件问题**:检查供电和调试器连接是否稳定。
---
通过以上步骤,应能定位并解决 `access violation` 错误。如果问题持续,建议提供芯片型号和完整代码片段以进一步分析。
static __IO uint32_t delay_ms_ticks; static inline void delay_init(void) { SysTick_Config(SystemCoreClock/1000); } static inline void delay_ms(uint16_t ms) { delay_ms_ticks = ms; while(delay_ms_ticks); } __weak void SysTick_Handler() { if (delay_ms_ticks > 0) { delay_ms_ticks--; } }改为使用外部32.768KHz晶振的延时函数
首先,需要明确的是使用外部32.768KHz晶振的延时函数需要使用RTC定时器,因为RTC定时器使用的是低速外部晶振。以下是修改后的代码:
```c
static __IO uint32_t delay_ms_ticks;
static inline void delay_init(void) {
RCC->APB1ENR1 |= RCC_APB1ENR1_PWREN; // Enable power interface clock
PWR->CR1 |= PWR_CR1_DBP; // Enable access to RTC, backup and power registers
RCC->BDCR |= RCC_BDCR_RTCEN; // Enable RTC clock
RCC->BDCR |= RCC_BDCR_RTCSEL_LSE; // Select low speed external oscillator as RTC clock
RTC->WPR = 0xCA; // Unlock write protection
RTC->WPR = 0x53;
RTC->ISR |= RTC_ISR_INIT; // Enter initialization mode
while (!(RTC->ISR & RTC_ISR_INITF)); // Wait for initialization flag to be set
RTC->PRER = (127 << 16) | (255); // Set prescaler values for 32.768KHz oscillator
RTC->ISR &= ~RTC_ISR_INIT; // Exit initialization mode
RTC->WPR = 0xFF; // Lock write protection
}
static inline void delay_ms(uint16_t ms) {
delay_ms_ticks = ms;
while (delay_ms_ticks);
}
__weak void RTC_WKUP_IRQHandler() {
if (delay_ms_ticks > 0) {
delay_ms_ticks--;
}
}
```
在上述代码中,我们首先使能了PWR、RTC和BKP的时钟,并且解锁了RTC写保护。然后选择了低速外部晶振作为RTC时钟源,并且设置了对应的预分频器值。最后,我们将写保护锁定,并在RTC的WKUP中断句柄中进行延时操作。需要注意的是,在这里我们使用了RTC的WKUP中断而不是SysTick中断来进行延时,因为我们现在使用的是RTC定时器。
阅读全文
相关推荐
















