转载请标明是引用于 http://blog.csdn.net/chenyujing1234
欢迎大家拍砖!
平时在查看代码中做的笔记,主要涉及嵌入式开发中的代码风格编译方法、技巧等。希望对大家有帮助。
今天在查看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。
由于在一些小型的嵌入式设备上(如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为单位的。
typedef LONG (*PINTERRUPTSYNCROUTINE) ( IN PVOID DynamicContext );
这样才能进行 PINTERRUPTSYNCROUTINE pp; 变量的声明
(*(volatile unsignedchar *const)(reg)) =
const和volatile放在一起的意义在于:
(1)本程序段中不能对reg作修改,任何修改都是非法的,或者至少是粗心,编译器应该报错,防止这种粗心;
(2)另一个程序段(如硬件)则完全有可能修改,因此编译器最好不要做太激进的优化。
/* */ /* 混合控制器*/ /* */ /* */ 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;
分配多个变量大小的区域,然后根据区域大小分配给各自使用
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));
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 }
Register I = rEP3_DMA_CON; For(I = 0; I < 10; i++);
Register是variable的一种存储类型,叫做寄存器型号。
一个变量要是被定义为这种类型,他就会被存储在通用寄存器中,所以存储速度快。
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; }
// 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;
第一点:
// 在宏里定义了一个禁用警告,再把警告打开
第二点:像下面的语句就会产生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
设置VS2008文本编辑中高亮显示相关的变量的颜色的设置:
选项->字体和颜色->VA X Find Reference-》
注:前提是你装了VS助手
// 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 */
在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)
在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编出来的
BOOL SHInitExtraControls(void);
CAygshellHelper::CAygshellHelper(void )
{
if( m_hAygshellDLL = LoadLibrary( L"aygshell.dll" ) )
{
BOOL (*SHInitExtraControls)() =NULL; // 把函数指针置空
const char c_szASXHeaderFormat[] = "<ASX version = \"3.0\">\n" " <PARAM name = \"Last Entry\" value = \"%d\"/>\n" " <PARAM name = \"Generator\" value = \"CEPlayer\"/>\n";
bool IsBadFilenameChar(TCHAR c) { if (c < 32 || NULL != _tcschr(TEXT("\"/\\[]:;|=,?*<>"), c)) { return true; } return false; }
请注意以下红色的地方:类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;
通过定义结构体中的类型为 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
#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)
data = *psrc; flash[0x555] = 0x00AA; flash[0x2AA] = 0x0055; flash[0x555] = 0x00A0; *pdst = data; while (*pdst != data && (--timeout)) ;
pci = (PCODECINST)LocalAlloc(LPTR, sizeof(*pci));