转载请标明是引用于 http://blog.csdn.net/chenyujing1234
欢迎大家拍砖!
平时在查看代码中做的笔记,主要涉及嵌入式开发中的代码风格编译方法、技巧等。希望对大家有帮助。
1、把32位的数反转(高低位对调)
今天在查看TrueCrypt工程源码时(参考我的文章<<TrueCrypt简介、在VS2008下的编译过程>>)看到位操作的算法,觉得很巧妙,这里做个总结。
unsigned __int32 MirrorBytes32 (unsigned __int32 x)
{
unsigned __int32 n = (unsigned __int8) x;
n <<= 8; n |= (unsigned __int8) (x >> 8);
n <<= 8; n |= (unsigned __int8) (x >> 16);
return (n << 8) | (unsigned __int8) (x >> 24);
}
如下图所求,传进来的x是32位的ABCD(假设A为8位、B为8位、C为8位、D为8位),经过运算后得到DCBA。
2、自己封装memset函数
由于在一些小型的嵌入式设备上(如uc/OSII 或STM32)用C语言写程序,很多C语言中的API不能用,或者效率过低,得自己封装一些函数。
下面介绍我们常用的memset的实现:
/*
*********************************************************************************************************
* CLEAR A SECTION OF MEMORY
*
* Description: This function is called by other uC/OS-II services to clear a contiguous block of RAM.
*
* Arguments : pdest is the start of the RAM to clear (i.e. write 0x00 to)
*
* size is the number of bytes to clear.
*
* Returns : none
*
* Notes : 1) This function is INTERNAL to uC/OS-II and your application should not call it.
* 2) Note that we can only clear up to 64K bytes of RAM. This is not an issue because none
* of the uses of this function gets close to this limit.
* 3) The clear is done one byte at a time since this will work on any processor irrespective
* of the alignment of the destination.
*********************************************************************************************************
*/
void OS_MemClr (INT8U *pdest, INT16U size)
{
while (size > 0) {
*pdest++ = (INT8U)0;
size--;
}
}
用法:
OS_EXT OS_EVENT OSEventTbl[OS_MAX_EVENTS];/* Table of EVENT control blocks */
#endif
OS_MemClr((INT8U *)&OSEventTbl[0], sizeof(OSEventTbl)); /* Clear the event table */
以上能实现是因sizeof()计算出来的大小是以INT8U为单位的。
3、
typedef LONG
(*PINTERRUPTSYNCROUTINE)
(
IN PVOID DynamicContext
);
这样才能进行 PINTERRUPTSYNCROUTINE pp; 变量的声明
4、
(*(volatile unsignedchar *const)(reg)) =
const和volatile放在一起的意义在于:
(1)本程序段中不能对reg作修改,任何修改都是非法的,或者至少是粗心,编译器应该报错,防止这种粗心;
(2)另一个程序段(如硬件)则完全有可能修改,因此编译器最好不要做太激进的优化。
5、这里的union后面可以加上union的名字
/* */
/* 混合控制器*/
/* */
/* */
typedef struct tMIXERCONTROL {
DWORD cbStruct; /* MIXERCONTROL的大小*/
DWORD dwControlID; /* 为混频器的唯一的控制id */
DWORD dwControlType; /* MIXERCONTROL_CONTROLTYPE_xxx */
DWORD fdwControl; /* MIXERCONTROL_CONTROLF_xxx */
DWORD cMultipleItems; /* if MIXERCONTROL_CONTROLF_MULTIPLE set */
TCHAR szShortName[MIXER_SHORT_NAME_CHARS];
TCHAR szName[MIXER_LONG_NAME_CHARS];
union
{
struct
{
LONG lMinimum; /* 此控制器标记的最小*/
LONG lMaximum; /* 此控制器标记的最大*/
};
struct
{
DWORD dwMinimum; /* 此控制器未标记的最小*/
DWORD dwMaximum; /* 此控制器未标记的最大*/
};
DWORD dwReserved[6];
} Bounds;
union
{
DWORD cSteps; /* 在最小和最大间的步数*/
DWORD cbCustomData; /* 通用数据的bytes大小*/
DWORD dwReserved[6]; /* !!! needed? we have cbStruct.... */
} Metrics;
} MIXERCONTROL, *PMIXERCONTROL, FAR *LPMIXERCONTROL;
6、
分配多个变量大小的区域,然后根据区域大小分配给各自使用
PCSP_PIN pCsPin = NULL;
PCSMULTIPLE_ITEM pCSDataRangeItems = NULL;
PCS_DATARANGE_VIDEO pCSDataRangeVideo = NULL;
DWORD dwStructSize = sizeof(CSP_PIN) + sizeof(CSMULTIPLE_ITEM) + sizeof(CS_DATARANGE_VIDEO);
pCsPin = (PCSP_PIN) malloc(dwStructSize);
if (NULL == pCsPin)
{
RETAILMSG(CAMAPP_ERROR_MSG, (TEXT("ChangeResolution: Malloc memory failed!\r\n")));
bRetVal = FALSE;
goto __exit;
}
pCsPin->Property = IOCTLInput;
pCsPin->PinId = pinId;
pCSDataRangeItems = (PCSMULTIPLE_ITEM) (pCsPin + 1);
pCSDataRangeItems->Count = 1;
pCSDataRangeItems->Size = sizeof(CSMULTIPLE_ITEM) + sizeof(CS_DATARANGE_VIDEO);
pCSDataRangeVideo = (PCS_DATARANGE_VIDEO) (pCSDataRangeItems + 1);
memcpy(pCSDataRangeVideo, pPinDataRange, sizeof(CS_DATARANGE_VIDEO));
7、请注意X86时的给寄存器赋值的方法
VOID WRITE_PORT_UCHAR(
PUCHAR Port,
UCHAR Value
)
{
#if defined(x86)
__asm {
mov dx, word ptr Port
mov al, Value
out dx, al
}
#else
*(volatile UCHAR * const)Port = Value;
#endif
}
8、
Register I = rEP3_DMA_CON;
For(I = 0; I < 10; i++);
Register是variable的一种存储类型,叫做寄存器型号。
一个变量要是被定义为这种类型,他就会被存储在通用寄存器中,所以存储速度快。
9、通过读回来来强制出现写, 当循环重启时提供更多时间
static void
maebsa_reset (PDRVCONTEXT pDrv, int reset)
{
AU13XX_VSSCTRL *vss = pDrv->vss;
volatile uint32 junk;
if (reset)
{
vss->bsa.clkrst = 3;
}
else
{
vss->bsa.clkrst = 2;
}
// 通过读回来来强制出现写, 当循环重启时提供更多时间
junk = vss->bsa.clkrst;
}
10、
// pSMB->evnt =pSMB->evnt;
static
BOOL WriteData( PDEVICE_INSTANCE DeviceInstance,
SMBUS_TRANSFER *pTransfer )
{
PSC_SMB *pSMB = DeviceInstance->pSMB;
ULONG i;
BOOL status = FALSE;
EnterCriticalSection(&DeviceInstance->ControlMutex);
// 清除之前的状态
pSMB->evnt = pSMB->evnt;
11、在宏里定义了一个禁用警告,再把警告打开
第一点:
// 在宏里定义了一个禁用警告,再把警告打开
第二点:像下面的语句就会产生4309警告。
编译后提示为:warning C4309: “初始化”: 截断常量值
原因是因为特定的类型转换操作导致常量超出被分配的空间,需要使用更大的数据类型来保存该常量.
int main()
{
char c = 128;
char x = (char)128;
return 0;
}
// #pragma warning(default: 4309) 把警告打开
#if EDID_SAMPLE
#pragma warning(disable: 4309)
static char edid_sample[] =
{
0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x22,0x64,0x0B,0x19,0x48,0x07,0x00,0x00,
0x2A,0x12,0x01,0x03,0x80,0x3B,0x25,0x78,0xEA,0x9E,0x71,0xA6,0x54,0x4C,0x9F,0x24,
0x10,0x51,0x57,0xBF,0xEF,0x80,0xD1,0x00,0xB3,0x00,0xA9,0x40,0x95,0x00,0x90,0x40,
0x81,0x80,0x81,0x40,0x71,0x4F,0x28,0x3C,0x80,0xA0,0x70,0xB0,0x23,0x40,0x30,0x20,
0x36,0x00,0x62,0x5E,0x21,0x00,0x00,0x1A,0x00,0x00,0x00,0xFF,0x00,0x31,0x38,0x36,
0x34,0x0A,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x00,0x00,0x00,0xFD,0x00,0x38,
0x4B,0x18,0x50,0x0F,0x00,0x0A,0x20,0x20,0x20,0x20,0x20,0x20,0x00,0x00,0x00,0xFC,
0x00,0x48,0x46,0x32,0x38,0x39,0x48,0x0A,0x20,0x20,0x20,0x20,0x20,0x20,0x01,0xD4
};
#pragma warning(default: 4309) // disable warning for "no return value"
#endif
11、
设置VS2008文本编辑中高亮显示相关的变量的颜色的设置:
选项->字体和颜色->VA X Find Reference-》
注:前提是你装了VS助手
12、 32 bit 对齐宏
// 32 bit 对齐宏
#define ALIGN(size) ((size & 0xfffffffc) + ((size & 3) ? 4 : 0))
pHTTPSession = (P_HTTP_SESSION)malloc(ALIGN(sizeof(HTTP_SESSION)));
/*
0xfffffffc : 1111 1111 1111 1111 1111 1111 1111 1100
3 : 0000 0000 0000 0000 0000 0000 0000 0011
*/
13、在except中用GetExceptionCode()来决断异常类型
在KavteP51中有serialhw.c文件中有
try
{
//USR1
OUTREG32(&pHWHead->pUartReg->USR1,
CSP_BITFVAL(UART_USR1_PARITYERR, UART_USR1_PARITYERR_SET) |
CSP_BITFVAL(UART_USR1_RTSD, UART_USR1_RTSD_SET) |
CSP_BITFVAL(UART_USR1_ESCF, UART_USR1_ESCF_SET) |
CSP_BITFVAL(UART_USR1_FRAMERR, UART_USR1_FRAMERR_SET) |
CSP_BITFVAL(UART_USR1_AGTIM, UART_USR1_AGTIM_SET) |
CSP_BITFVAL(UART_USR1_DTRD, UART_USR1_DTRD_SET) |
CSP_BITFVAL(UART_USR1_AIRINT, UART_USR1_AIRINT_SET) |
CSP_BITFVAL(UART_USR1_AWAKE, UART_USR1_AWAKE_SET));
//USR2
OUTREG32(&pHWHead->pUartReg->USR2,
CSP_BITFVAL(UART_USR2_ADET, UART_USR2_ADET_SET) |
CSP_BITFVAL(UART_USR2_DTRF, UART_USR2_DTRF_SET) |
CSP_BITFVAL(UART_USR2_IDLE,UART_USR2_IDLE_SET) |
CSP_BITFVAL(UART_USR2_ACST, UART_USR2_IDLE_SET) |
CSP_BITFVAL(UART_USR2_RIDELT, UART_USR2_RIDELT_SET) |
CSP_BITFVAL(UART_USR2_IRINT, UART_USR2_IRINT_SET) |
CSP_BITFVAL(UART_USR2_WAKE, UART_USR2_WAKE_SET) |
CSP_BITFVAL(UART_USR2_DCDDELT, UART_USR2_DCDDELT_SET) |
CSP_BITFVAL(UART_USR2_RTSF, UART_USR2_RTSF_SET) |
CSP_BITFVAL(UART_USR2_BRCD, UART_USR2_BRCD_SET) |
CSP_BITFVAL(UART_USR2_ORE, UART_USR2_ORE_SET));
}
except(GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
13、
在Platform\KavteP51\SRC\DRIVERS\BLOCK\NANDFMD\dll\sources文件中有
TARGETLIBS=\
$(_SYSGENSDKROOT)\lib\$(_CPUINDPATH)\coredll.lib \
$(_SYSGENOAKROOT)\lib\$(_CPUINDPATH)\ceddk.lib \
$(_TARGETPLATROOT)\lib\$(_CPUDEPPATH)\cspddk.lib
即会链接到这些以上 lib文件中.所以如果在
C:\WINCE600\PUBLIC\COMMON\OAK\LIB\ARMV4I\RETAIL下没有coredll.lib文件时编译会报:
不知怎么编译coredll.lib
--------- \WINCE600\OSDesigns\OSKavteP51\OSKavteP51\Wince600中的文件是可以从类似于C:\WINCE600\PUBLIC\COMMON\OAK\LIB\ARMV4I\RETAIL这样的public编出来的
14、
BOOL SHInitExtraControls(void);
CAygshellHelper::CAygshellHelper(void )
{
if( m_hAygshellDLL = LoadLibrary( L"aygshell.dll" ) )
{
BOOL (*SHInitExtraControls)() =NULL; // 把函数指针置空
15、按以下方式定义字符串
const char c_szASXHeaderFormat[] = "<ASX version = \"3.0\">\n"
" <PARAM name = \"Last Entry\" value = \"%d\"/>\n"
" <PARAM name = \"Generator\" value = \"CEPlayer\"/>\n";
16、以下的判断方法挺好的
bool IsBadFilenameChar(TCHAR c)
{
if (c < 32 || NULL != _tcschr(TEXT("\"/\\[]:;|=,?*<>"), c))
{
return true;
}
return false;
}
17、
请注意以下红色的地方:类CplaylistMgr中的结构体list_t中的成员是类CplaylistMgr中的成员
class CPlaylistMgr
{
// two-way linked list manages playlists
struct list_t
{
list_t() :
pPlaylist(NULL),
pNext(NULL),
pPrev(NULL),
pDupNames(NULL)
{ }
~list_t()
{
RemoveDupName();
delete pPlaylist;
pNext = NULL;
pPrev = NULL;
pDupNames = NULL;
}
CPlaylist * pPlaylist;
list_t * pNext;
list_t * pPrev;
duplist_t * pDupNames;
18、
通过定义结构体中的类型为 volatile 来使此结构体变量为可变的
#ifndef ASSEMBLER
typedef volatile struct
{
uint32 rxdata;
uint32 txdata;
uint32 inten;
uint32 intcause;
uint32 fifoctrl;
uint32 linectrl;
uint32 mdmctrl;
uint32 linestat;
uint32 mdmstat;
uint32 reserved0;
uint32 clkdiv;
uint32 reserved1[53];
uint32 enable;
uint32 mdmen;
uint32 bidir;
} AU1X00_UART;
#endif
19、
#pragma warning 指令允许有选择性的修改编译器的警告消息的行为,格式如下:
#pragma warning( arning-specifier : warning_number-list[; warning
#pragma warning(push [ , n])
#pragma warning (pop)
主要用到的警告表示有如下:
Once : 只显示一次(警告/错误)消息
Default: 重置编译器的警告行为到默认状态
1,2,3, 4: 四个警告级别
Disable:禁用指定的警告信息
Error: 将指定的警告信息作为错误报告
Eg:
#pragma warning(once:4385) // 4385号警告信息仅报告一次
#pragma warning(error:164) // 把164号警告信息作为一个错误。
#pragma warning( push )//保存所有警告信息的现有的警告状态。
#pragma warning( push, n)//保存所有警告信息的现有的警告状态,并且把全局警告等级设定为n。
#pragma warning( pop )//向栈中弹出最后一个警告信息,在入栈和出栈之间所作的一切改动取消。
#pragma warning(push)
#pragma warning(disable: 4115 4201 4204 4214)
#include <windows.h>
#pragma warning(pop)
20、采用下面的方法来查看写进去的数据是否起效了
data = *psrc;
flash[0x555] = 0x00AA;
flash[0x2AA] = 0x0055;
flash[0x555] = 0x00A0;
*pdst = data;
while (*pdst != data && (--timeout)) ;
21、在source insight中把字体改为中文后写中文就不会空一个空格了
22、通过指针指向的数据的大小来新建空间,并把地址返回给此指针
pci = (PCODECINST)LocalAlloc(LPTR, sizeof(*pci));