学习笔记(无聊时的总结)
转载请标明是引用于 http://blog.csdn.net/chenyujing1234
欢迎大家拍砖!
平时在查看代码中做的笔记,主要涉及嵌入式开发中的代码风格编译方法、技巧等。希望对大家有帮助。
1、把32位的数反转(高低位对调)
今天在查看TrueCrypt工程源码时(参考我的文章<<>>)看到位操作的算法,觉得很巧妙,这里做个总结。
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 */#endifOS_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)另一个程序段(如硬件)则完全有可能修改,因此编译器最好不要做太激进的优化。
/* *//* 混合控制器*//* *//* */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 Portmov al, Valueout dx, al}#else*(volatile UCHAR * const)Port = Value;#endif}
Register I = rEP3_DMA_CON;For(I = 0; I < 10; i++);
Register是variable的一种存储类型,叫做寄存器型号。
一个变量要是被定义为这种类型,他就会被存储在通用寄存器中,所以存储速度快。
9、通过读回来来强制出现写, 当循环重启时提供更多时间
static voidmaebsa_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;
staticBOOL 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助手
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*/
在KavteP51中有serialhw.c文件中有
try{//USR1OUTREG32(&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));//USR2OUTREG32(&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编出来的
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";
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 ASSEMBLERtypedef 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)) ;
22、通过指针指向的数据的大小来新建空间,并把地址返回给此指针
pci = (PCODECINST)LocalAlloc(LPTR, sizeof(*pci));23、采用%a打印出来的是以科学计算法来计算的数字