前段时间搞GPRS,为了实现同时上网和通话短信,移植了MUX驱动和UniModem驱动。移植完后出现了一个状况,USB无法与PC同步,CE上提示“端口不可用,请关闭其它正在使用的程序”之类的。当时一直没留意这个玩意,今天抽空看了下,发现这个问题既然是由移植后的UniModem驱动引起的。
这个无法同步有点奇怪,只要没有接上GPRS模块,MUX初始化失败后就会导致USB无法同步。如果接上GPRS模块,MUX可以初始化成功后,是可以正常使用USB同步的。
同步使用的是USB CABLE这个端口,跟踪发现这个具体配置USB同步的在common.reg中有配置:
[HKEY_LOCAL_MACHINE\Drivers\USB\FunctionDrivers\Serial_Class] "Dll"="serialusbfn.dll" "DeviceName"="USBFNS1:" "Prefix"="COM" "DeviceArrayIndex"=dword:0 "RxBufferSize"=dword:4000 "IClass"="{CC5195AC-BA49-48a0-BE17-DF6D1B0173DD}" ; idVendor must be changed. 045E belongs to Microsoft and is only to be used for ; prototype devices in your labs. Visit http://www.usb.org to obtain a vendor id. "idVendor"=dword:045E "Manufacturer"="Generic Manufacturer (PROTOTYPE--Remember to change idVendor)" "idProduct"=dword:00ce "Product"="Generic Serial (PROTOTYPE--Remember to change idVendor)" "bcdDevice"=dword:0 "Tsp"="Unimodem.dll" "DeviceType"=dword:0 [HKEY_LOCAL_MACHINE\Drivers\USB\FunctionDrivers\USBSER_Class] "Dll"="serialusbfn.dll" "DeviceName"="USBFNS2:" "Prefix"="COM" "DeviceArrayIndex"=dword:1 "RxBufferSize"=dword:4000 "IClass"=multi_sz:"{CC5195AC-BA49-48a0-BE17-DF6D1B0173DD}","{C375C787-B721-4b8e-B67F-A112D5C0A404}" ; idVendor must be changed. 045E belongs to Microsoft and is only to be used for ; prototype devices in your labs. Visit http://www.usb.org to obtain a vendor id. "idVendor"=dword:045E "Manufacturer"="Generic Manufacturer (PROTOTYPE--Remember to change idVendor)" "idProduct"=dword:0079 "Product"="Generic Serial (PROTOTYPE--Remember to change idVendor)" "bcdDevice"=dword:90 "Tsp"="Unimodem.dll" "DeviceType"=dword:0
在这两个键中有引用到UniModem.dll。
这样一看,就大概明白应该是当时移植UniModem驱动,把其中两次打开同一个串口的修改成了打开两个串口导致的。
现有一解决办法,那就是同步的时候使用原来的Unimodem.dll,而GPRS拨号上网那个就使用移植后的Unimodem.dll。
经过测试,这个办法可行,一切正常。USB可以正常同步了。
修改方法如下:
1、把原来的unimodem.dll放到一个驱动的目录下,并重命名为unimodem1.dll(名字随你起)
2、然后在common.bib中引用这个unimodem1.dll
3、在common.reg中把上面贴出的这两段注册表信息中的"Tsp"="Unimodem.dll"修改成"Tsp"="unimodem1.dll"
4、上面3步都完成后,则进行sysgen,之后就可以了
但是,这样修改有一个缺点:
如果我在同一个工程中即使用GPRS模块又使用3G模块,3G模块使用的是自带的unimodem驱动,那么这个3G就有可能无法进行拨号上网。
不知道谁有没有更好的办法,欢迎来讨论~~
PS: Unimodem驱动中如果不修改成打开两个串口,而是采用原来的打开同一个串口两次,这样会有问题,导致无法正常使用。打开的串口都是MUX那里虚拟出来的串口,我这里虚拟出来三个串口,一个用于通话、短信的AT指令,一个用于拨号上网,剩下的一个用于第二次打开串口这里。
NVIC中断优先级的理解
CM3支持硬件中断嵌套,分为抢占式优先级和亚优先级,使用规则主要有,抢占优先级高级别的可以打断低级别的,同一级别的抢占优先级同时发生时,亚当优先级高的先发生中断,若是相同,则按硬件排列顺序发生。若是有一个亚优先级正在执行中断,同一级别的其它亚优先级发生时,则先挂起,等此中断执行完再执行!
从库函数中找到优先级分组模式:
#define NVIC_PriorityGroup_0 ((uint32_t)0x700) /* 0 bits for pre-emption priority
4 bits for subpriority */
#define NVIC_PriorityGroup_1 ((uint32_t)0x600) /* 1 bits for pre-emption priority
3 bits for subpriority */
#define NVIC_PriorityGroup_2 ((uint32_t)0x500) /* 2 bits for pre-emption priority
2 bits for subpriority */
#define NVIC_PriorityGroup_3 ((uint32_t)0x400) /* 3 bits for pre-emption priority
1 bits for subpriority */
#define NVIC_PriorityGroup_4 ((uint32_t)0x300) /* 4 bits for pre-emption priority
0 bits for subpriority */
从中可以看出第一组只有一个级别,16个亚优先级,我可以这样理解,若是分配成这个组里,不能发生嵌套中断,同时发生中断时,亚优先级高的先发生,若有中断执行时,必须等中断执行完才能执行下一个中断。最后一组正好相反,有15个级别,若是执行一个中断,可以最多嵌套15个中断执行一个中断。看下面的例子:
NVIC_InitTypeDef NVIC_InitStructure; //定义中断初始化类型结构体变量
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1); //配置优先级分组1 2个两个抢占优先级 8个亚优先级
NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn; //开口外部中断0
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;//配置0号抢占式优先级
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;//亚优先级配置为0号
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//使能通道
NVIC_Init(&NVIC_InitStructure); //对外部中断0进行初始化配置
NVIC_InitStructure.NVIC_IRQChannel = EXTI9_5_IRQn; //开口外部中断5到9
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;//配置1号抢占式优先级
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;//亚优先级配置为1号
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//使能通道
NVIC_Init(&NVIC_InitStructure); //对外部中断0进行初始化配置
NVIC_InitStructure.NVIC_IRQChannel = ADC1_2_IRQn; //ADC1中断
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;//配置1号抢占式优先级
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;//亚优先级配置为1号
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//使能通道
NVIC_Init(&NVIC_InitStructure); //对外部中断0进行初始化配置
从上面的配置来看,外部中断0的优先级最高,可以打断ADC和外部5到9的中断,也就说可以嵌套发生,当ADC中断和外部5到9中断同时发生时,它们的抢占优先级别相同,亚优先级别也相同,因为ADC1硬件排在更靠前,则先发生ADC中断,若是两者任何一个中断正在执行,则等此中断执行完,再去执行另一个中断。
有些变量只需要初始化一次(如从文件中读取配置参数,读取设备型号等等),可以使用dispatch_once来进行读取优化,保证只调用API一次,以后就只要直接访问变量即可
范例如下:
static BOOL isTestMode;
+ (BOOL)isTestMode
{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
NSNumber* obj = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFResourceTest"];
isTestMode = [obj boolValue];
});
return isTestMode;
}