学习笔记(无聊时的总结)

转载请标明是引用于 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。

学习笔记(无聊时的总结)_第1张图片

 

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)) =

constvolatile放在一起的意义在于:
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++);

 

Registervariable的一种存储类型,叫做寄存器型号。

一个变量要是被定义为这种类型,他就会被存储在通用寄存器中,所以存储速度快。

 

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));

23、采用%a打印出来的是以科学计算法来计算的数字

你可能感兴趣的:(exception,list,struct,null,编译器,WinCE)