C 将函数分离到不同文件时数据损坏
这个问题使我烦恼。我正在用C语言为基于LPC15XX系列微控制器的定制传感器板进行裸机编程。该平台相当于一组I2C传感器和一个连接到其中一个UART的蓝牙发射器。这不是LPCxpresso(或类似)板之一;它是定制设计的 直到今天,所有的测试代码都在一个单片文件中,一切都按预期工作。随着代码的增长,我决定将主要功能部分分解为单独的源文件,以便于管理。不幸的是,我一这么做,程序就开始出错了 正在移动的代码是原始单片文件的复制+粘贴。我已经通过社会福利署的链接使用了GDB。看来,我的一个用于命中内部ROM驱动程序的静态变量正在被置零。稍后取消对此的引用将导致故障 在静态变量上设置一个watch,我可以看到在I2C初始化例程中有一行代码将其放大。问题在于init是使用NXP提供的ROM驱动程序例程完成的。此外,当这些代码都在同一个文件中时,它们就可以正常工作了 问题C 将函数分离到不同文件时数据损坏,c,corruption,bare-metal,lpc,C,Corruption,Bare Metal,Lpc,这个问题使我烦恼。我正在用C语言为基于LPC15XX系列微控制器的定制传感器板进行裸机编程。该平台相当于一组I2C传感器和一个连接到其中一个UART的蓝牙发射器。这不是LPCxpresso(或类似)板之一;它是定制设计的 直到今天,所有的测试代码都在一个单片文件中,一切都按预期工作。随着代码的增长,我决定将主要功能部分分解为单独的源文件,以便于管理。不幸的是,我一这么做,程序就开始出错了 正在移动的代码是原始单片文件的复制+粘贴。我已经通过社会福利署的链接使用了GDB。看来,我的一个用于命中内部
- 什么会像那样破坏文件级静态变量?据我所知,变量不应该在堆栈上,因此我看不到导致此问题的缓冲区溢出
- 为什么在文件之间移动代码会暴露这一点?它不应该被编译并链接到一个名称空间吗
在uart\u实例
中定义一次,并且仅在调用usart.c
uart\u设置时直接(按名称)写入一次
- 同样地,
在i2c\u实例
中定义(我还没有移动i2c函数)。是静态的,声明与uart\U实例相同。我已经更新了下面的代码,以包含这两个文件中的所有静态变量main.c
- 在调用
pI2CApi->i2c\u set\u比特率(hI2C,基本时钟,i2c\u波特)时,指针实际上为空代码>,通过在相关内存上设置手表确定
- 我不能直接跟踪任何ROM驱动程序例程。它们由uC提供,并通过固定内存地址处提供的双指针进行访问。我已经检查了这些指针对象(
和hUart
),它们保留了正确的值;只有pUartApi
被关闭uart\u实例
- 我为这个应用程序创建并转储了地图文件;它不包含对
(或任何静态变量)的引用。奇怪。我可以根据要求发布全部内容(有点长)uart\u实例
int setupUSART0(int系统时钟,int波特率){
UART\u CONFIG\u T CONFIG;
uint32\u t frg\u val=0;
uint32大小单位为字节;
//启用USART0时钟
LPC_SYSCON->SYSAHBCLKCTRL1 |=((1UL UARTCLKDIV=(uint8)USART_PERIPH_PRESCALE);
//配置USART0引脚
LPC_SWM->PINASSIGN0=0;
LPC|u SWM->PINSassign0|=((uint8|t)18)PINSassign0|=((uint8|t)13)PINSassign0|=((uint8|t)0xFF)PINSassign0|=((uint8|t)0xFF)uart获取内存大小();
if(10<(大小单位为字节/4))返回-1;
hUart=pUartApi->uart_设置(LPC_USART0_基础,(uint8_t*)和uart_实例);//uart_初始化(hUart,&配置)FRGCTRL=frg_val;
//在NVIC中启用USART0
NVIC->ISER0 |=((1UL INTENSET |=((1UL SYSAHBCLKCTRL1 |=((1UL DIV=0x0078;//120十进制)
LPC_I2C0->MSTTIME=0x00;//SCL高/低=每个时钟2个
//调试
LPC_SWM->PINENABLE1=0x00;
//启用中断
NVIC->ISER0 |=((1UL INTENSET |=((1UL INTENSET |=((1UL i2c|U设置(LPC|U I2C0|U基础,(uint32|t*)和i2c|U实例);
//这会以某种方式使uart_实例为空
//设置比特率
err=pI2CApi->i2c\u设置\u比特率(hI2C,基本时钟,i2c\u波特率);
//设置主模式
LPC_I2C0->CFG=((1UL我认为上面的代码没有任何错误
通常,通过将代码拆分为多个文件而意外引入的错误是静态变量的重复。例如,main.c和usart.c中都可能存在static UART\u HANDLE\u T UART\u实例;
(甚至在这两个文件所包含的某些.h中都存在).一切都将编译并链接正常,但是main.c和usart.c中的函数将使用不相关的变量,并且程序逻辑将随着数据损坏的可能性而改变
现在,这是一个与您的代码没有直接关系的通用注释。它可能会有帮助…祝您好运找到bug!您能转储i2c\u set\u比特率的程序集吗?
i2c\u设置中可能有什么东西设置了segfault?i2c\u实例是静态的吗?您在中使用uart\u实例吗其他带有extern
声明的文件?我做的另一件事是查看链接器映射文件-查看附近的变量..除了@Abhi编写的内容外,还有哪一行setupI2C()为空?我想可能是对i2c_setup()的调用。设置变量i2c_实例。如果此变量声明不正确,它可能会覆盖相邻的全局内存,从而影响uart_实例。如果链接器没有吐出静态变量,请删除静态声明。因为您在别处的注释表明没有其他uart_实例
。某些链接器具有指令su如“--mapfile\u contents=sym\u defs
”,可以查看其中的静态变量
static UARTD_API_T* pUartApi; // USART API function addr table
static UART_HANDLE_T uart_instance; // Raw storage for USART API
static UART_HANDLE_T* hUart; // Handle to USART API
static I2CD_API_T* pI2CApi; // I2C API function addr table
static I2C_HANDLE_T i2c_instance; // Raw storage for I2C API
static I2C_HANDLE_T* hI2C; // Handle to I2C API
int setupUSART0(int sys_clock, int baud) {
UART_CONFIG_T config;
uint32_t frg_val = 0;
uint32_t size_in_bytes;
// Enable USART0 clock
LPC_SYSCON->SYSAHBCLKCTRL1 |= ((1UL << 17));
// Configure USART clock divider
LPC_SYSCON->UARTCLKDIV = (uint8_t)USART_PERIPH_PRESCALE;
// Configure USART0 pins
LPC_SWM->PINASSIGN0 = 0;
LPC_SWM->PINASSIGN0 |= ((uint8_t)18) << 0; // PIO0_18, tx
LPC_SWM->PINASSIGN0 |= ((uint8_t)13) << 8; // PIO0_13, rx
LPC_SWM->PINASSIGN0 |= ((uint8_t)0xFF) << 16; // Not wired, rts
LPC_SWM->PINASSIGN0 |= ((uint8_t)0xFF) << 24; // Not wired, cts
// Get handle to USART API
pUartApi = getUartDriver();
// Initialize memory for UART API
size_in_bytes = pUartApi->uart_get_mem_size();
if (10 < (size_in_bytes / 4)) return -1;
hUart = pUartApi->uart_setup(LPC_USART0_BASE, (uint8_t*)&uart_instance); // <- uart_instance initialized here
// Initialize USART API
config.sys_clk_in_hz = sys_clock / USART_PERIPH_PRESCALE;
config.baudrate_in_hz = baud;
config.config = 1; // 8N1
config.sync_mod = 0;
config.error_en = 0;
frg_val = (pUartApi->uart_init(hUart, &config) << 8) | 0xFF;
// Configure USART fractional divider
if (!frg_val) return -1;
LPC_SYSCON->FRGCTRL = frg_val;
// Enable USART0 in NVIC
NVIC->ISER0 |= ((1UL << 21));
// Enable UART0 interrupts
LPC_USART0->INTENSET |= ((1UL << 0));
return 0;
}
ErrorCode_t setupI2C() {
ErrorCode_t err;
// Enable I2C clock
LPC_SYSCON->SYSAHBCLKCTRL1 |= ((1UL << 13));
LPC_I2C0->DIV = 0x0078; // 120 decimal
LPC_I2C0->MSTTIME = 0x00; // SCL high / low = 2 clocks each
//DEBUG
LPC_SWM->PINENABLE1 = 0x00;
// Enable interrupts
NVIC->ISER0 |= ((1UL << 24)); // ISE_I2C0
LPC_I2C0->INTENSET |= ((1UL << 0)); // MSTPENDINGEN
LPC_I2C0->INTENSET |= ((1UL << 8)); // SLVPENDINGEN
// Get handle to I2C API
pI2CApi = getI2CDriver();
// Initialize memory for UART API
hI2C = pI2CApi->i2c_setup(LPC_I2C0_BASE, (uint32_t*)&i2c_instance);
// This NULLS uart_instance somehow
// Set bitrate
err = pI2CApi->i2c_set_bitrate(hI2C, BASE_CLOCK, I2C_BAUD);
// Set master mode
LPC_I2C0->CFG = ((1UL << 0)); // MSTEN
return err;
}