一、背景
接了个代码。编译450多个警告。真的是教科书啊。挨个处理并记录。接手这种代码真的是倒大霉了。也不知道这个代码是怎么运行的起来的。
二、解决过程
waring: #1
warning: #1-D: last line of file ends without a newline
文件末尾少一行。结尾给个回车,当然你也可以屏蔽
屏蔽警告的方法如下:Misc Controls 狂框里面填写 --diag_suppress=186,550,1296,177 =号后面的是需要屏蔽掉的警告编号
waring: #1215
.\device\include\usbResetPin.h(18): warning: #1215-D: #warning directive: "This Project is designed for FlowCytometry!"
#warning "This Project is designed for FlowCytometry!"
代码是这样的,自己写的提示。屏蔽掉代码就解决的警告问题。
waring: #940
main.c(90): warning: #940-D: missing return statement at end of non-void function "BaselineCheck"
}
这个是说,BaselineCheck();这个函数没有返回值。需要在函数结尾加个return 0; 返回一下
或者把函数返回类型改为void类型。
waring: #223
device\source\usbCommand.c(1196): warning: #223-D: function "SilenceBeep" declared implicitly
SilenceBeep();
说这个函数是隐私声明SilenceBeep(); 声明一下就行,如果声明了。可能是没添加这个.h 文件
为了避免.h被漏引用,建议写个类似于这样的.h 把想要的都添加进来,免得.h满天飞
waring: #167
device\source\CANProtocol.c(708): warning: #167-D: argument of type "volatile CAN_MSG_Type *" is incompatible with parameter of type "CAN_MSG_Type *"
if(CANReadFromFIFOIn(&CANReceiveMsgCheckPublic,&CANReceiveMsgPublic)==SUCCESS)
这个警告说的是,类型参数不匹配.
函数原型是这样的
Status CANReadFromFIFOIn(CAN_MSG_Type *pReceiveMsg, CAN_MSG_Type *pReceiveMsgCheck)
参数定义是这样的
volatile CAN_MSG_Type CANReceiveMsgPublic,CANReceiveMsgCheckPublic;
问题就出在CANReceiveMsgCheckPublic 、 CANReceiveMsgPublic 在定义的时候,前面加了个volatile ,然后编译器就不知道&CANReceiveMsgCheckPublic 、&CANReceiveMsgPublic 是什么类型了。
这个是老代码。不知道去掉volatile会有什么影响。所以我的解决办法是 强转类型为 CAN_MSG_Type*
if(CANReadFromFIFOIn((CAN_MSG_Type*)&CANReceiveMsgCheckPublic,(CAN_MSG_Type*)&CANReceiveMsgPublic)==SUCCESS)
waring: #111
device\source\usbCommand.c(2871): warning: #111-D: statement is unreachable
switch(usbExecuteState())
这个是说。这个你行代码永远都执行不到。这种警告要非常注意,这种代码基本不会按照预期的结果运行
举例:下图圈出来的这一句永远不会执行。
举例:这个圈出来的,是个switch 嵌套switch 圈出来的这一句数据,一个case 下面的。但是前面有个break。 都退出了。。怎么执行。这种代码。。能正常运行?????真TMD 。。。哎。。
解决办法:只能花很长的时间撸上下文。然后根据他的逻辑去改。代码太长了,也不能全部贴出来。所以,还请哥哥们苦练基础,不要写出这种代码,祸害别个。
waring: #188
device\source\usbCommand.c(467): warning: #188-D: enumerated type mixed with another type
pCahnnelSelect->mFL4.mTime = 0;
pCahnnelSelect->mFL4.mTime是个枚举。直接给0报枚举类型不对。强转一下咯改为
pCahnnelSelect->mFL4.mTime = (FunctionCTLType)0;
另外一种waring#188 使用函数时这么写 I2C_IntCmd(i2cId, 1);报waring#188.解决办法,强转类型 I2C_IntCmd(i2cId, (Bool)1);
void I2C_IntCmd (uint8_t i2cId, Bool NewState)
{
IRQn_Type irq;
switch (i2cId)
{
case I2C_0:
irq = I2C0_IRQn;
break;
case I2C_1:
irq = I2C1_IRQn;
break;
case I2C_2:
irq = I2C2_IRQn;
break;
default:
return;
}
if (NewState)
{
NVIC_EnableIRQ(irq);
}
else
{
NVIC_DisableIRQ(irq);
}
return;
}
waring: #68
177x_8x_PDL_110602\Drivers\source\lpc177x_8x_mci.c(1906): warning: #68-D: integer conversion resulted in a change of sign
retval = MCI_FUNC_NOT_READY;
typedef enum mci_func_error
{
MCI_FUNC_OK = 0,
MCI_FUNC_FAILED = -1,
MCI_FUNC_BAD_PARAMETERS = -2,
MCI_FUNC_BUS_NOT_IDLE = -3,
MCI_FUNC_TIMEOUT = -3,
MCI_FUNC_ERR_STATE = -4,
MCI_FUNC_NOT_READY = -5,
}en_Mci_Func_Error;
/******************************************************************************
** Function name: MCI_Cmd_SendAcmdBusWidth
**
** Descriptions: ACMD6, SET_BUS_WIDTH, if it's SD card, we can
** use the 4-bit bus instead of 1-bit. This cmd
** can only be called during TRANS state.
** Since it's a ACMD, CMD55 APP_CMD needs to be
** sent out first.
**
** parameters: Bus width value, 1-bit is 0, 4-bit is 10
** Returned value: true or false, true if the card is still in the
** TRANS state after the cmd.
**
******************************************************************************/
uint32_t MCI_Cmd_SendAcmdBusWidth( uint32_t buswidth )
{
uint32_t i, retryCount;
uint32_t respStatus;
uint32_t respValue[4];
uint32_t retval = MCI_FUNC_FAILED;
retryCount = 0x20; /* reset retry counter */
while ( retryCount > 0 )
{
if (MCI_Cmd_SendACMD() == MCI_FUNC_OK)
{
respStatus = MCI_CmdResp(CMD6_SET_ACMD_BUS_WIDTH, buswidth, EXPECT_SHORT_RESP, (uint32_t *)&respValue[0], 0);
if(respStatus)
{
retval = MCI_FUNC_FAILED;
}
else if(!(respValue[0] & _SHIFT(MCI_CARDSTATUS_READYFORDATA_P0S)))
{
retval = MCI_FUNC_NOT_READY;
}
else if((CARDSTATEOF(respValue[0]) != MCI_CARDSTATE_TRAN))
{
retval = MCI_FUNC_ERR_STATE;
}
else
{
return MCI_FUNC_OK;
}
}
for ( i = 0; i < 0x20; i++ );
retryCount--;
}
return retval;
}
retval = MCI_FUNC_NOT_READY; retval 是个uint32_t MCI_FUNC_NOT_READY是个负数,所以报了警告,整数转换导致了符号的改变.. 这个应该是lpc 1788原厂的代码吧。怎么会有这种问题。真的是烦恼啊。这个代码里面。 MCI_FUNC_BUS_NOT_IDLE = -3, MCI_FUNC_TIMEOUT = -3, 两个负3
waring: #1441
177x_8x_PDL_110602\Drivers\source\lpc177x_8x_eeprom.c(109): warning: #1441-D: nonstandard cast on lvalue
LPC_EEPROM -> WDATA = *(((uint8_t *)data)++);
非标强制转换
waring: #61
177x_8x_PDL_110602\Drivers\source\lpc177x_8x_can.c(1567): warning: #61-D: integer operation result is out of range
pCan->TFI1 |= (1 << 31); //set bit FF
出现上面的警告是说我们定义的 整数运范围超出结果,可以在定义的数值前加强制转换解决
waring: #520
main.c(174): warning: #520-D: initialization with "{...}" expected for aggregate object
UNS_16* base_line_buff[5] = 0;
这个。。。。。。5个人你给一个苹果,怎么分。编译器当场懵逼。正确写法如下
UNS_16* buffer_add[11] = {0,0,0,0,0,0,0,0,0,0,0}; //缓存寄存器的地址
waring: #1295
.\device\include\samplevolumemodel.h(8): warning: #1295-D: Deprecated declaration disableVolume - give arg types
extern UNS_16 disableVolume();
不推荐的声明xxxxx-需要给定参数类型。是因为你的函数没有参数的话,需要定义和声明的时候添加void 所以改成这样就可以了
extern UNS_16 disableVolume(viod);
waring: #69
device\source\extEEPROM.c(62): warning: #69-D: integer conversion resulted in truncation
PINSEL_SetI2CMode(0, 11, IOCON_I2CMODE_FASTPLUS);
整型数据被截断了,这种情况下,定义变量的大小和赋值的大小不一致导致的。最终变量实际的值,可能和赋进去的不一样。
函数原型是这样的。
typedef enum
{
/** Fast mode (400 kHz clock rate) and standard (100 kHz clock rate) */
PINSEL_I2CMODE_FAST_STANDARD = 0,
/** Open drain I/O (not I2C). No glitch filter, 3 mA typical output drive */
PINSEL_I2CMODE_OPENDRAINIO,
/** Fast Mode Plus I2C. This includes a filter for <50 ns glitches */
PINSEL_I2CMODE_FASTMODEPLUS,
/** High drive open drain I/O (not I2C). No glitch filter, 20 mA typical output drive */
PINSEL_I2CMODE_HIDRIVE_OPENDRAIN
}PinSel_I2cMode;
void PINSEL_SetI2CMode(uint8_t portnum, uint8_t pinnum, PinSel_I2cMode I2CMode)
{
uint32_t *pPIN = NULL;
pPIN = PIN_GetPointer(portnum, pinnum);
*(uint32_t *)pPIN &= ~(PINSEL_I2C_MODE_BITMASK<< PINSEL_I2C_MODE_POS);
*(uint32_t *)pPIN |= (I2CMode << PINSEL_I2C_MODE_POS);
}
赋值参数是这样的
#define IOCON_I2CMODE_FASTPLUS ((2<<8))
我就搞不懂。。直接赋值PINSEL_I2CMODE_FASTMODEPLUS 不好吗?
改成这样
PINSEL_SetI2CMode(0, 11, PINSEL_I2CMODE_FASTMODEPLUS);
waring: #69
device\source\extEEPROM.c(62): warning: #69-D: integer conversion resulted in truncation
PINSEL_SetI2CMode(0, 11, IOCON_I2CMODE_FASTPLUS);
整型数据被截断了,这种情况下,定义变量的大小和赋值的大小不一致导致的。最终变量实际的值,可能和赋进去的不一样。
函数原型是这样的。
typedef enum
{
/** Fast mode (400 kHz clock rate) and standard (100 kHz clock rate) */
PINSEL_I2CMODE_FAST_STANDARD = 0,
/** Open drain I/O (not I2C). No glitch filter, 3 mA typical output drive */
PINSEL_I2CMODE_OPENDRAINIO,
/** Fast Mode Plus I2C. This includes a filter for <50 ns glitches */
PINSEL_I2CMODE_FASTMODEPLUS,
/** High drive open drain I/O (not I2C). No glitch filter, 20 mA typical output drive */
PINSEL_I2CMODE_HIDRIVE_OPENDRAIN
}PinSel_I2cMode;
void PINSEL_SetI2CMode(uint8_t portnum, uint8_t pinnum, PinSel_I2cMode I2CMode)
{
uint32_t *pPIN = NULL;
pPIN = PIN_GetPointer(portnum, pinnum);
*(uint32_t *)pPIN &= ~(PINSEL_I2C_MODE_BITMASK<< PINSEL_I2C_MODE_POS);
*(uint32_t *)pPIN |= (I2CMode << PINSEL_I2C_MODE_POS);
}
赋值参数是这样的
#define IOCON_I2CMODE_FASTPLUS ((2<<8))
我就搞不懂。。直接赋值PINSEL_I2CMODE_FASTMODEPLUS 不好吗?
改成这样
PINSEL_SetI2CMode(0, 11, PINSEL_I2CMODE_FASTMODEPLUS);
waring: #513
device\source\extEEPROM.c(98): warning: #513-D: a value of type "Status (*)()" cannot be assigned to an entity of type "void (*)(void)"
pMessR->callback = rwEEPROMComplete;
pMessR->callback 是void * 类型的。。rwEEPROMComplete是 Status *类型的。解决办法就是改成类型一致或者强制转换
pMessR->callback = (void*))rwEEPROMComplete;
waring: #815
device\source\CANProtocol.c(17): warning: #815-D: type qualifier on return type is meaningless
volatile UNS_32 (*DriverProcess[4])(void);
在这里,我将volatile关键字移到括号前面,以解决警告 #815-D,因为在返回类型上使用类型限定符是没有意义的。这个警告信息表明你在函数的返回类型前使用了volatile关键字,但这种使用对返回类型来说是无意义的。volatile关键字通常用于告诉编译器一个变量的值可能会被意外地改变,比如操作系统、硬件或者其他线程等。当声明一个指针为volatile时,意味着指针本身是稳定的,但它指向的内容可能会改变。
解决这个警告的方法是移除函数返回类型前的volatile关键字。如果你的函数确实需要返回一个可变的值,那么你应该检查你的设计,确保这个值的变化是预期内的。如果函数返回类型不应该是可变的,那么移除volatile关键字。
UNS_32 (*volatile DriverProcess[4])(void);
waring: #144
device\source\usbCommand.c(64): warning: #144-D: a value of type "volatile DeviceDescriptionType *" cannot be used to initialize an entity of type "volatile PDeviceDescriptionType"
volatile PDeviceDescriptionType pDeviceDescription = &DeviceDescription;
waring: #174
device\source\usbCommand.c(88): warning: #174-D: expression has no effect
SAMPLEBOARD_EPROM_ERROR|SAMPLEBOARD_CAN_ERROR|SAMPLEBOARD_OVERSAMPLE_ERROR|SAMPLEBOARD_OTHER;//采集板一切未初始化。
警告 #174-D 表示表达式没有效果,可能是写代码的人忘记屏蔽掉了吧。
waring: #177
main.c(174): warning: #177-D: variable "buffer_add_2" was declared but never referenced
UNS_32* buffer_add_2[10] = {0,0,0,0,0};
就是说定义了。但是没用。这个可以屏蔽警告
waring: #186
177x_8x_PDL_110602\Drivers\source\lpc177x_8x_mcpwm.c(79): warning: #186-D: pointless comparison of unsigned integer with zero
if ((channelNum >= 0) && (channelNum <= 2))
channelNum变量是个uint32_t 的类型。肯定是>=0 的。channelNum >= 0这个表达式没意义。我这里LPC给的库里全是这种代码。只能屏蔽这个警告
waring: #550
device\source\extEEPROM.c(78): warning: #550-D: variable "m_pAddr" was set but never used
UNS_16 m_pAddr;
定义了但是没用的变量,删了吧。
waring: #1296
177x_8x_PDL_110602\Drivers\source\lpc177x_8x_gpdma.c(115): warning: #1296-D: extended constant initialiser used
((uint32_t)&LPC_TIM3->MR1), // MAT3.1
代码是这样的
const uint32_t GPDMA_LUTPerAddr[] =
{
0, // Reversed
((uint32_t)&LPC_MCI->FIFO), // SD Card
((uint32_t)&LPC_SSP0->DR), // SSP0 Tx
((uint32_t)&LPC_SSP0->DR), // SSP0 Rx
((uint32_t)&LPC_SSP1->DR), // SSP1 Tx
((uint32_t)&LPC_SSP1->DR), // SSP1 Rx
((uint32_t)&LPC_SSP2->DR), // SSP2 Tx
((uint32_t)&LPC_SSP2->DR), // SSP2 Rx
((uint32_t)&LPC_ADC->GDR), // ADC
((uint32_t)&LPC_DAC->CR), // DAC
((uint32_t)&LPC_UART0->/*RBTHDLR.*/THR), // UART0 Tx
((uint32_t)&LPC_UART0->/*RBTHDLR.*/RBR), // UART0 Rx
((uint32_t)&LPC_UART1->/*RBTHDLR.*/THR), // UART1 Tx
((uint32_t)&LPC_UART1->/*RBTHDLR.*/RBR), // UART1 Rx
((uint32_t)&LPC_UART2->/*RBTHDLR.*/THR), // UART2 Tx
((uint32_t)&LPC_UART2->/*RBTHDLR.*/RBR), // UART2 Rx
((uint32_t)&LPC_TIM0->MR0), // MAT0.0
((uint32_t)&LPC_TIM0->MR1), // MAT0.1
((uint32_t)&LPC_TIM1->MR0), // MAT1.0
((uint32_t)&LPC_TIM1->MR1), // MAT1.1
((uint32_t)&LPC_TIM2->MR0), // MAT2.0
((uint32_t)&LPC_TIM2->MR1), // MAT2.1
((uint32_t)&LPC_I2S->TXFIFO), // I2S Tx
((uint32_t)&LPC_I2S->RXFIFO), // I2S Rx
0, // Reverse
0, // Reverse
((uint32_t)&LPC_UART3->/*RBTHDLR.*/THR), // UART3 Tx
((uint32_t)&LPC_UART3->/*RBTHDLR.*/RBR), // UART3 Rx
((uint32_t)&LPC_UART4->/*RBTHDLR.*/THR), // UART4 Tx
((uint32_t)&LPC_UART4->/*RBTHDLR.*/RBR), // UART4 Rx
((uint32_t)&LPC_TIM3->MR0), // MAT3.0
((uint32_t)&LPC_TIM3->MR1), // MAT3.1
};
你使用了一个非常量表达式来初始化一个需要常量的地
三、警告不解决的危害
waring: #111
举例:写以下这个代码的人,可能是想在return 之前赋值吧。。可是,这一句根本不会执行。如果他认真处理的警告就不会出现这种问题。
waring: #223
- 隐式声明的函数默认返回 int 类型,并且可以接受任意数量和类型的参数。这可能会导致类型不匹配的问题,特别是当实际函数返回或接受不同类型的值时。
waring: #940
举例:一个函数的返回类型是uint32_t 但是函数里面没有写return 但是在调用这个函数的时候却判断了这个函数的返回值。这种情况下,函数执行完后返回值其实是随机的取决于函数执行结束后寄存器中的值或内存中的数据。所以不写return 是很危险的。
下面这个例子,主线程中等设备初始化,但是USB初始函数中没有return 。所以,多编译几次,你会发现,主线程可能会卡死。
UNS_32 IniUSBI2C(void)
{
uint8_t i = 0;
USB_RESET_ADD = 0xF0F0; //往FPGA中写F0F0,表示复位USB桥
USBIICDATA.tx_data =(uint8_t *)BinCode; //USB配置需要的数据
USBIICDATA.tx_length =0x927;
USBIICDATA.tx_count =0;
USBIICDATA.rx_data = (uint8_t *)BinData;
USBIICDATA.rx_length =0;
USBIICDATA.rx_count =0;
I2C_SlaveTransferData(I2C_0,&USBIICDATA,I2C_TRANSFER_POLLING); //IIC开始发送数据
}
main()
{
/*初始化USB芯片*/
while(ERROR==IniUSBI2C())
{
}
while(1);
}