tftp Error on server : Access violation解决办法

本文介绍了解决TFTP上传文件时出现的Accessviolation错误的方法。通过创建同名文件并设置权限为777,可以成功执行put操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在执行tftp put操作时,可能遇到Access violation错误。

解决办法为:进入tftp的上传文件的目录,例如/tftpboot,新建一个于要上传文件同名的文件,并修改权限为777:

touch test.txt
chmod 777 test.txt
在执行put操作即可:

tftp 192.168.1.1 put test.txt



WS 1, `current_uA WS 1, `voltage_mV WS 1, `power_mW *** error 65: access violation at 0x7EFE80 : no 'read' permission *** error 65: access violation at 0x7EFE80 : no 'write' permission *** error 65: access violation at 0x7EFE82 : no 'write' permission *** error 65: access violation at 0x7EFE80 : no 'read' permission *** error 65: access violation at 0x7EFE80 : no 'write' permission *** error 65: access violation at 0x7EFE88 : no 'read' permission *** error 65: access violation at 0x7EFE88 : no 'write' permission *** error 65: access violation at 0x7EFE80 : no 'read' permission *** error 65: access violation at 0x7EFE80 : no 'write' permission *** error 65: access violation at 0x7EFE81 : no 'write' permission *** error 65: access violation at 0x7EFE82 : no 'read' permission *** error 65: access violation at 0x7EFE82 : no 'read' permission *** error 65: access violation at 0x7EFE82 : no 'read' permission *** error 65: access violation at 0x7EFE82 : no 'read' permission *** error 65: access violation at 0x7EFE82 : no 'read' permission *** error 65: access violation at 0x7EFE82 : no 'read' permission *** error 65: access violation at 0x7EFE82 : no 'read' permission *** error 65: access violation at 0x7EFE82 : no 'read' permission *** error 65: access violation at 0x7EFE82 : no 'read' permission *** error 65: access violation at 0x7EFE82 : no 'read' permission *** error 65: access violation at 0x7EFE82 : no 'read' permission *** error 65: access violation at 0x7EFE82 : no 'read' permission *** error 65: access violation at 0x7EFE82 : no 'read' permission *** error 65: access violation at 0x7EFE82 : no 'read' permission *** error 65: access violation at 0x7EFE82 : no 'read' permission *** error 65: access violation at 0x7EFE82 : no 'read' permission *** error 65: access violation at 0x7EFE82 : no 'read' permission *** error 65: access violation at 0x7EFE82 : no 'read' permission *** error 65: access violation at 0x7EFE82 : no 'read' permission *** error 65: access violation at 0x7EFE82 : no 'read' permission *** error 65: access violation at 0x7EFE82 : no 'read' permission
最新发布
07-18
<think>我们遇到了内存访问权限错误(access violation),错误地址集中在0x7EFE80附近。这些错误通常发生在尝试访问未分配或受保护的内存区域时。根据错误信息,这些地址位于扩展RAM区域(xdata),而STC32G的扩展RAM地址范围需要正确配置才能访问。 ### 问题分析 1. **错误地址分析**:0x7EFE80位于扩展RAM(xdata)的高地址区域(0x0000-0xFFFF)。STC32G的扩展RAM需要使能才能访问。 2. **可能原因**: - 扩展RAM未在启动文件中启用 - 内存区域未正确初始化 - 栈溢出或指针越界 ### 解决方案 #### 步骤1:启用扩展RAM 在STC32G的启动文件中,需要设置扩展RAM的使能位。修改启动文件(通常为`STARTUP.A51`): ```asm ; 在STARTUP.A51文件开头添加 NAME STARTUP ?STACK SEGMENT IDATA RSEG ?STACK DS 1 ; 使能扩展RAM EXTRN CODE (?C_STARTUP) PUBLIC ?C_STARTUP CSEG AT 0 LJMP STARTUP1 CSEG AT 0x1A3 ; 扩展RAM使能位地址 DB 0x00 ; 0x00: 禁止扩展RAM, 0x01: 使能扩展RAM RSEG ?C_STARTUP STARTUP1: ; 其他初始化代码... ``` #### 步骤2:检查内存分配 确保变量定义在正确的内存区域: ```c // 在定义全局变量时,指定存储区域 xdata struct ina219_value_t ina219_value; // 显式放入xdata // 或者使用编译器指令指定内存区域 #pragma xdata struct ina219_value_t ina219_value; ``` #### 步骤3:调整栈大小 如果栈溢出导致访问越界,需增加栈大小。在`STARTUP.A51`中: ```asm ; 设置栈大小(例如:256字节) ?STACK SEGMENT IDATA RSEG ?STACK DS 256 ``` #### 步骤4:检查指针使用 确保没有野指针或越界访问: ```c // 示例:安全访问函数 void safe_access(void) { // 使用前检查指针有效性(仅适用于已知内存范围) uint16_t *ptr = (uint16_t*)0x7EFE80; if ((uint32_t)ptr >= 0x7E00 && (uint32_t)ptr <= 0x7FFF) { *ptr = 0x1234; // 安全写入 } } ``` ### 完整修复代码示例 #### 修改启动文件(STARTUP.A51) ```asm ; 启用扩展RAM (0x7E00-0x7FFF) CSEG AT 0x1A3 DB 0x01 ; 使能扩展RAM ``` #### 显式指定变量存储区域 ```c // 在INA219.h中 #pragma xdata struct ina219_value_t { int16 voltage; int32 shunt; int32 current; int32 power; }; extern xdata struct ina219_value_t ina219_value; ``` #### 增加栈大小 在Keil工程配置中: 1. 打开“Target Options” 2. 在“Target”选项卡中,设置“Memory Model”为“Large: variables in XDATA” 3. 设置“XDATA Size”为0x2000(8KB) ### 错误原因解释 访问冲突错误(65)通常由以下原因引起: 1. **未初始化的扩展RAM**:STC32G默认关闭扩展RAM,需软件开启。 2. **内存模型不匹配**:若使用Small内存模型,编译器将变量放在data/idata,无法访问xdata高地址。 3. **栈溢出**:默认栈太小导致覆盖其他内存区域。 ### 验证方法 1. 在调试模式下观察SP寄存器值,确保栈在有效范围内。 2. 使用内存查看窗口检查0x7EFE80区域是否可读写。 §§相关问题§§: 1. 如何配置STC32G的扩展RAM区域? 2. Keil C51中xdata、idata、data的区别是什么? 3. 嵌入式系统中如何检测和防止栈溢出? 4. 在单片机编程中处理内存访问错误的最佳实践有哪些?</think>### 解决内存访问冲突错误 (Error 65) 您遇到的 `access violation` 错误表示程序试图访问没有读写权限的内存地址。这些错误集中在 `0x7EFE80` 和 `0x7EFE82` 地址,通常与内存映射、指针错误或内存保护机制相关。 ### 完整解决方案 #### 1. 检查内存映射配置(关键步骤) STC32G 的内存映射需要正确配置才能访问 XDATA 区域: ```c // 在系统初始化代码中添加内存配置 void SystemInit(void) { // 启用扩展RAM访问 EAXSFR(); // 允许访问扩展SFR P_SW2 |= 0x80; // 使能扩展RAM访问 // 配置内存映射 (0x7EFE80 在扩展RAM区域) XRAM_CTRL = 0x01; // 使能0x0000-0xFFFF扩展RAM访问 XRAM_TRIM = 0x00; // 不使用内存保护 // 其他初始化... } ``` #### 2. 修复全局变量定义 确保 `ina219_value` 结构体正确定义在可访问的内存区域: ```c // INA219.h #pragma location = 0x7EFE00 // 指定安全的内存区域 struct ina219_value_t { int16 voltage; int32 shunt; int32 current; int32 power; }; // 使用 __xdata 关键字确保变量放在扩展RAM extern __xdata struct ina219_value_t ina219_value; ``` #### 3. 修改访问函数 确保所有访问都使用安全的内存操作: ```c // INA219.c void ina219_process(void) { // 使用临时变量避免直接访问 int16 temp_voltage = ina219_GetBusVoltage_mV(); int32 temp_shunt = ina219_GetShuntVoltage_uV(); int32 temp_current = ina219_GetCurrent_uA(); int32 temp_power = ina219_GetPower_mW(); // 安全复制到全局结构 ina219_value.voltage = temp_voltage; ina219_value.shunt = temp_shunt; ina219_value.current = temp_current; ina219_value.power = temp_power; } // 修改读取函数,避免直接返回全局变量 int16 INA219_GetVoltage(void) { return ina219_value.voltage; } int32 INA219_GetCurrent(void) { return ina219_value.current; } int32 INA219_GetPower(void) { return ina219_value.power; } ``` #### 4. 内存保护检查 添加内存访问验证函数: ```c #include <stdint.h> // 内存地址验证函数 uint8_t is_valid_address(uint32_t addr) { // STC32G 扩展RAM范围: 0x0000-0xFFFF if (addr >= 0x0000 && addr <= 0xFFFF) { return 1; } return 0; } // 安全的内存写入函数 void safe_mem_write(uint32_t addr, uint8_t value) { if (is_valid_address(addr)) { *((__xdata uint8_t *)addr) = value; } else { // 错误处理 while(1); // 或记录错误日志 } } ``` #### 5. 链接器脚本修改(Keil特定) 在Keil中修改分散加载文件(.sct): ```scatter LR_IROM1 0x00000000 0x00010000 { ; 加载区域 ER_IROM1 0x00000000 0x00010000 { ; 代码区 *.o (RESET, +First) *(InRoot$$Sections) .ANY (+RO) } RW_IRAM1 0x00010000 0x00008000 { ; 内部RAM .ANY (+RW +ZI) } RW_XRAM1 0x007E0000 0x00020000 { ; 扩展RAM区域 (包含0x7EFE80) ina219.o (+RW) ; 强制INA219变量在此区域 } } ``` ### 错误原因分析 1. **内存权限问题**: - `0x7EFE80` 位于 STC32G 的扩展 RAM 区域 (XDATA) - 默认情况下该区域可能未启用或受保护 2. **常见根本原因**: - 未启用扩展 RAM 访问 (需要设置 SFR) - 内存保护单元 (MPU) 限制 - 变量未正确定义在可访问区域 - 栈溢出导致内存踩踏 - 野指针访问 3. **调试建议**: ```c // 调试代码:检查内存访问权限 printf("EAXFR bit: %d\n", (P_SW2 & 0x80) ? 1 : 0); printf("XRAM_CTRL: 0x%02X\n", XRAM_CTRL); printf("ina219_value addr: 0x%08X\n", (uint32_t)&ina219_value); ``` ### 预防措施 1. **内存初始化函数**: ```c void Memory_Init(void) { // 清零扩展RAM区域 __xdata uint8_t *p = (__xdata uint8_t *)0x7E0000; for (int i = 0; i < 0x2000; i++) { *p++ = 0; } // 设置内存保护 MPU_RNR = 0; // 区域0 MPU_RBAR = 0x7EFE00; // 基地址 MPU_RASR = (1 << 0) | (0xFF << 8); // 启用|全权限 } ``` 2. **栈溢出检测**: ```c // 在启动文件中添加栈检查 #pragma segment="CSTACK" extern uint32_t __stack_start = __sfe("CSTACK"); extern uint32_t __stack_end = __sfe("CSTACK") + __ssize("CSTACK"); void Stack_Check(void) { uint32_t used = __stack_start - (uint32_t)&used; if (used > (__stack_end - __stack_start) * 0.8) { // 栈使用超过80%,触发警告 } } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值