VxWorks下USB驱动总结2
3:USBD驱动详解
这一部分将要描述USBD(USB Host Driver)的典型应用。例如初始化,client注册,动态连接注册,设备配置,数据传输,同时还探讨了USBD内部设计的关键特性。这部分是VxWorks下USB驱动的核心。
1 初始化USBD:分为两步
(1)必须至少调用一次函数usbdInitialize()。在一个给定的系统中,usbdlnifialize()初始化内部USBD数据结构,并依次调用其它USB驱动栈模块的入口。usbdinitialize()可以在启动时调用一次,也可以对每一个设备各调用一次。USBD 自己记录了调用usbdInitialize()(‘+’)和usbdShutDown()(‘-’)的次数。只有大于等于1时才是真正初始化了,而等于0是关闭了。
...
/* Initialize the USBD. */
if (usbdInitialize () != OK)
return ERROR;
...
...
/* application code. */
...
...
/* Shut down the USBD. Note: we only execute this code if the return
* code from usbdInitialize() was OK. Note also that there’s really no
* reason to check the result of usbdShutdown().
*/
usbdShutdown ();
(2)用USBD 的lisbdHedAttaeh()函数来把至少一个HCD连接到USBD上。这一过程既可以在VxWorks启动时,也可以在运行时把HCD 连接到USBD 上去。后一种机制可以支持“热插拔”,而不用象前一种那样需要重新启动。
2 HCD的连接(attaching)与断开(detaching)
当HCD连接到USBD 时,调用者为usbdHedattaeh函数传递HCD执行入口(表HCD_EXEC_FUNC)和HCD连接参数(HCD attach parameter)。USBD用HCD FNC ATYACH 服务请求依次激活HCD的执行入口,传递同样的HCD attach参数。
需要强调虽然可以改变用HCD定义的参数,但是最好不应该有所改变。对于WindRiver提供的UHCI和OHCI的HCD,HCI attach参数是一个指向结构PCI_CFG_HEADER (定义在pciConstants.h) 的指针。
该结构用UHCI和OHCI主控制器的PCI配置头来初始化,而HCD用这个结构中的信息来定位,管理特定的主控制器。典型的,调用者用usbPeiClassFind ()和usbPciConfigHeaderGet()来得到想要的主控制器的PCI配置头- 这两个函数定义在usbPciLib 中(stubUsbarchPciLib.h中)。如果有UHCI或OHCI要连接到USBD,就要调用这些函数来获得每一个主控制器的PCI_CFG_HEADER。然后利用usbdHedAttaeh来激活已鉴别出的每一个主控制器。
注意:底层BSP可能不支持USB的HCD断开,因为当中断向量表重新使能时,如果还应用的是过期的向量表,会导致错误。
//挂接过程
UINT8 busNo;
UINT8 deviceNo;
UINT8 funcNo;
PCI_CFG_HEADER pciCfgHdr; /* PCI_CFG_HEADER defined in
pciConstants.h */
GENERIC_HANDLE uhciAttachToken; /* GENERIC_HANDLE defined in
usbHandleLib.h */
/* Locate the first (0th) UHCI controller. UHCI_CLASS, etc., are defined
* in usbUhci.h. The functions usbPciClassFind() and
* usbPciConfigHeaderGet() are exported by usbPciLib.
*/
if (!usbPciClassFind (UHCI_CLASS, UHCI_SUBCLASS, UHCI_PGMIF, 0,
&busNo, &deviceNo, &funcNo))
{
/* No UHCI controller was found. */
return ERROR;
}
usbPciConfigHeaderGet (busNo, deviceNo, funcNo, &pciCfgHdr);
/* Attach the UHCI HCD to the USBD. The function usbHcdUhciExec() is
* exported by usbHcdUhciLib.
*/
if (usbdHcdAttach (usbHcdUhciExec, &pciCfgHdr, &uhciAttachToken) != OK)
{
/* USBD failed to attach to UHCI HCD. */
return ERROR;
}
/* Attachment is complete. */
//取消挂接
/* Detach the UHCI HCD from the HCD. */
usbdHcdDetach (uhciAttachToken);
/* Detach is complete! */
3 启动顺序
必须在所有USBD函数前执行函数usbdInitialize()。存在以下两种调用方式:
(1)传统的“启动”初始化。执行顺序与其意义如下:
a.usbdInitialize();
b.usbdPciClassFind():定位一个USB主控制器;
c.usbdPeiConfigHeaderGet():读USB主控制器配置头;
d.usbdHedAttaeh():连接HCD,将其作为特定的主控制器:
e.调用USB class driver初始化入口点;
f.USB class driver调用usbdlnitialize()。
(2)“热插拔”调用。执行顺序与其意义如下:
Boot Code里调用:
a.USB class driver初始化入口点;
b.USB class driver调用usbdlnitialize();
Hot-Swap code调用:
c.Hot-Swap 鉴别USB主控制器的连接或断开;
d.Usbdlnitialize();
e.UsbdPciConfigHeaderGet():读USB主控制器配置头;
f.UsbdHedAttaeh():连接HCD,将其作为特定的主控制器。
因为热插拔可以在任何时刻发生,所以USBD和其Client都必须被写成可以动态识别USB设备被插入还是被拔出。当主控制器连接到系统时,USBD 自动地鉴别与其相连的设备,并通知相关的client;同样,拔出设备时,也要通知相关设备。重要的是,USBD 的client,比如USB class driver,在client初始化时,从不设想特定的设备已经出现;而在其他时候,这些驱动随时检查设备是否已经连接到系统上。
4 总线任务
对每一个连接到USBD 的主控制器,例如插入或拔出设备,USBD都会产生一个总线任务,来监控总线事件。一般情况下,这些任务是休眠的(不消耗CPU),只有当USB hub报告它的一个端口有变化时,它们才被唤醒。每一个USBD总线任务有VxWorks任务名:UsbdBus。
虽然HCD委托USBD来管理,但有可能HCD 亲自监视主控制器事件。例如WindRiver提供了UHCI和OHCI的HCD来创造这样的任务。对于WindRiver的UHCI模块(usbHcdUheiLib),后台任务只是被周期地唤醒,目的是为了检查超时IRP(用一个中断来通知OHCI根hub发生改变)。
用以在USBD和USB之问进行通信的client模块,除了调用usbdlnitialize()外,必须调用usbClientRegister()使其在USBD注册。当一个client注册到USBD时,USBD把每一个以后将要用到的client的数据结构定位,并跟踪那个client的请求。
对于每一个client,在client注册过程中,USBD还创建了一个callback任务。在成功注册client后,USBD返回一个句柄USBD_CLIENT_HANDLE。以下对USBD的调用,将会用到这个句柄。当所有句柄都不需要时,可以调用usbdClientUnregister()来释放每一个client的数据结构和callback任务。注意:此时所有client要求的任务都会被取消。
例如:注册一个叫USBD_TEST的client,再注销。
注册:usbdClientRegister("USBD_TEST,&usbdClientHandle);
注销:usbdClientUnregister(usbdClientHandle);
5 client回调(callback)任务
USB操作是严格遵守时序的。例如为使中断传输和同步传输正确工作.需要依靠时钟中断。在一个有几个不同client出现的主系统中.总是有可能出现一个client打断其它client传输事件的发生。WindRiver USBD建议用client callback任务来解决这个问题。许多USB事件可以导致一个USB client的callback任务。例如, 每当USBD 完成USB IRP后,client的IRP callback函数被激活。同样,当USBD识别出一个动态连接事件后,会激活一个或更多的动态attach
callback操作。但不是马上激活这些回调操作, 而是安排合适的相应的USBD client的回调任务来执行callback。
一般的情况下,每一个client的callback任务处于“休眠”态(阻塞态)。每一个client的callback,继承了usbdClientRegister()产生的VxWorks任务优先级。这确保了每一个callback按其client的任务优先级来执行,而且可以利用优先级来写client,保证对时间要求严格的USB传输。由于每一个client有它自己的callback任务,因此在callback期间,它们有很大的灵活性决定可以做什么。例如,允许在不破坏USBD或其它USBD client性能的条件下,使callback执行代码运行至阻塞态。
Client callback task有VxWorks任务名:tUsbdCln。
6 USBD内部Client
当第一次初始化USBD时,由USBD产生并注册一个内部client,以跟踪USB请求。
USBD 可以产生什么类型的USB请求呢? 所有USBD与USB设备的传输,均利用调用USBD client的形式来完成。例如, 当一个设备第一次连接到系统时.USBD用一个控制管道(control pipe) 自动地创建设备需要的所有的control pipe,即USBD client要用usbdPipeCreate()来创建一个与USB endpoint0通话的通道,然后所有USBD 内部、外部client通过这个管道来发送诸如usbdDescriptorGet()或usbdFeatureGet()等的函数,进行操作。
所以,USBD 的一个机制就是USBD 循环利用它自己的entry point,而内部chent跟踪这些请求。
7 动态连接的注册
每当一个特定类型的设备插入或拔出时,USBD client都通知上一层。利用调用usbdDynamicAttachRegister()操作,client可以指定一个callback操作,以便可以获取这样的通知。
USB设备类型用class,subclass,protocol来区别。标准的USB 类在usb.h 中定义为USB_CLASS_XXXX。Subclass和protocol根据class来定义, 因此这些常数根据特定的class在头文件中定义。
有时, 一个client当利用usbdDynamicAttachRegister()进行注册时,只对特定的class,subclass,protocol感兴趣。例如,USB键盘类驱动usbkeyboardLib, 注册了Human Device Interface (HID) 类,subclass 是USB_SUBCLASS_HID_ BOOT,protocol是USB_PROTOCOL_HID_BOOT _KEYBOARD。通过callback机制的响应,每当一个设备完全符合这样的标准, 从设备上插入或拔出时,SBD便通知给keyboard
class driver。而在其它情况下,client关注的范围更广泛了。常量USBD_NOTIFY(定义在usbdLib.h)可以替代任意的class,subclass,protocol。例如,USB打印机USB驱动,usbPrinterLib, 其class等于USB_CLASS_PRINTER,subclass 等于USB_SUBCLASS_PRINTER (usbPrinter.h),protocol等于USBD_ NOTIFY_ ALL。典型的,当一个client只调用一次usbdDynamicAttachRegister()时,对一个client能拥有的并发通知请求数目没有限制。
8 Node ID
USB设备一般用USBD_NODE_ID来区别。从其作用来看,USBD_ NODE_ ID 是USBD 用来跟踪一个设备的句柄。它与USB设备真正的USB地址无关。这表明client并不真正关心想要了解设备是物理上与哪一个USB主控制器相连。应用为每个设备抽象定义的Node ID, 使client可以不用考虑物理设备的连接细节以及USB地址分配, 并允许USBD 在其内部对这些进行详细的管理。
当一个client通知有一个设备连接或断开时,USBD经常通过USBD_NODE_ID来定位设备。同样,当一个client想通过USBD与一个特定的设备通信时,它必须向USBD传递那个设备的USBD_NODE_ID。
9 总线编号(bus enumeration)操作
usbdLib模块提供了usbdBusCountGet(),usbdRootNodeldGet(),usbdHubPortCountGet(),usbdNodldGet()操作。它们被一起称作总线编号操作。它们使USBD Client对连接到每一个主控制器上的设备进行编号。
这些操作对于诊断程序和测试工具很有用,例如usbTool(WindRiver提供的一个测试工具)。但是,利用它们编号之后,调用者无法知道USB的拓扑结构是否变化。因此, 建议USB class driver的开发者不要用这些操作。
10 数据传输
一旦client配置完成一个设备,就开始利用USBD提供的管道和传输功能与设备进行数据交换。为了和设备交换数据,client必须先创建管道。作为结果,USBD得到了一个USBD_PIPE_HANDLE,它被用于随后对这个管道的所有client操作。
当client企图创建一个管道时,USBD会检查是否有足够的可用带宽。对于中断和同步传输,带宽限制是必需的。USBD不允许把90% 以上的可用带宽分配给中断和同步管道;而对于控制和块传输,则没有带宽的限制。同时,保证至少10% 的带宽用于控制传输,对块传输则不保证会提供任何可用带宽。
数据传输的具体过程:
(1)创建pipe :usbdPipeCreate(usbdClient Handle,nodeld,endpoint,configvalue,interface,
USB_XFRTYPE_BULK,USB_ DIR_OUT,maxPacketSize,0,0,&outPipeHandle);
(2)定义callback:ourlrpCallback(pvoid P);
(3)初始化IRP的数据结构;
(4)发送IRP:usbdTransfer(usbdChentHandle,outPipeHandle,&irp)。
4、 VxWorks下USB驱动编写流程
4.1 生成bootable工程,添加以下组件(根据不同硬件定制):
hardware->buses->USB Hosts->OHCI
hardware->buses->USB Hosts->USB Host Stack
hardware->buses->USB Hosts->USB Host Init->OHCI Init
hardware->buses->USB Hosts->USB Host Init->USB Host Stack Init
此时编译后的内核在启动时如果出现Attach OHCI...OK,表示USB协议栈加载成功。
4.2 修改和检查config.h
/* USB Stuff */
#define INCLUDE_USB
#define INCLUDE_OHCI
#define INCLUDE_OHCI_INIT
#define INCLUDE_USB_INIT
#define INCLUDE_USB_MOUSE
#define INCLUDE_USB_KEYBOARD
#define INCLUDE_USB_MS_BULKONLY
#define INCLUDE_USB_MS_CBI
#define INCLUDE_USB_PRINTER
#define INCLUDE_USB_SPEAKER
//新增加,根据系统不同配制,可能不同
//IO 地址相关,该系统不采用动态PCI查找和影射
#define SL811H_IO_ADDR SL811H_MEMORY_START
#define SL811H_IO_ADDR_DATA ((SL811H_MEMORY_START) | 0x800000)
//中断相关
#define SL811H_INT_LVL INT_LVL_EXT_IRQ_0 /* PPC405GP UIC Interrupt 25 - External IRQ 0 */
#define SL811H_INT_VEC INT_VEC_EXT_IRQ_0 /* PPC405GP UIC Interrupt 25 - External IRQ 0 */
4.3 wrSbc405gp.h(特定系统配制文件)
#define SL811H_MEMORY_START 0x70000000
#define SL811H_MEMSIZE 0x10000000
4.4 sysLib.c,增加MMU属性配制
,{
(void *) SL811H_MEMORY_START,
(void *) SL811H_MEMORY_START,
SL811H_MEMSIZE,
VM_STATE_MASK_VALID | VM_STATE_MASK_WRITABLE | VM_STATE_MASK_CACHEABLE | VM_STATE_MASK_GUARDED,
VM_STATE_VALID | VM_STATE_WRITABLE | VM_STATE_CACHEABLE_NOT | VM_STATE_GUARDED
}
5.调用流程
5.1 USB Init
///////////////////////////////////////////////////////////////////////////////////////////
UINT16 cmdUsbInit()
{
UINT16 usbdVersion;
char usbdMfg [USBD_NAME_LEN+1];
UINT16 s;
/* if already initialized, just show a warning */
if (initialized)
{
printf( "Already initialized.\n");
return RET_CONTINUE;
}
/* Initialize the USBD */
s = usbdInitialize ();
printf( "usbdInitialize() returned %d\n", s);
if (s == OK)
{
/* Register ourselves with the USBD */
s = usbdClientRegister (PGM_NAME, &usbdClientHandle);
printf( "usbdClientRegister() returned %d\n", s);
if (s == OK)
{
printf( "usbdClientHandle = 0x%x\n", (UINT32) usbdClientHandle);
/* Display the USBD version */
if ((s = usbdVersionGet (&usbdVersion, usbdMfg)) != OK)
{
printf( "usbdVersionGet() returned %d\n", s);
}
else
{
printf( "USBD version = 0x%5.4x\n", usbdVersion);
printf( "USBD mfg = '%s'\n", usbdMfg);
}
if (s == OK)
initialized = TRUE;
}
}
if (s != OK)
{
printf( "initialization failed\n");
}
return RET_CONTINUE;
}
/////////////////////////////////////////////////////////////////////////////////////////////
5.2执行HCD挂接
SL811_IO_CFG sl811IOCfg = {
SL811H_IO_ADDR,
SL811H_IO_ADDR_DATA,
SL811H_INT_VEC,
SL811H_INT_LVL
};
进入usbdHcdAttach,
5.3 setups the expansion bus access profile.(硬件单板的总线连接方式不同而不同)
5.4硬件相关寄存器初始化(因为硬件不同,所以相关过程不一样)
5.5初始化中断处理进程
(pHost->intThread =
taskSpawn ("tSl811Int", 0, 0, 0x4000,
(FUNCPTR) intThread, (int) pHost,
0, 0, 0, 0, 0, 0, 0, 0, 0))==ERROR
5.6 挂接中断
*pResult = intConnect ((VOIDFUNCPTR *)INUM_TO_IVEC (pHost->sl811CfgHdr.intVec), \
routine, (int)arg); \
开中断;
有必要的话,复位硬件(大部分时候如此)
6:数据发送和接受过程
6.1写数据过程
A:bulkWrite
LOCAL UINT16 bulkWrite
(
long bytes,
FILE *fin, /* stream for input (if any) */
FILE *fout /* stream for output (if any) */
)
{
/* Initialize the BULK class driver */
char filePath[1000];
char buffer[BULK_DRIVE_BUFFER_SIZE];
UINT8 *ptr;
int fd;
UINT32 i;
UINT8 j=1,k=1;
UINT32 len=0;
sprintf(filePath,"%sbulkFile",BULK_DRIVE_NAME);
remove(filePath);
fd = open(filePath, O_CREAT | O_WRONLY, 0);
if (fd == ERROR)
fprintf (fout, "bulkWrite() error opening %s\n",filePath);
else
fprintf (fout, "bulkWrite() %s opened for write\n",filePath);
ptr = (UINT8 *) buffer;
for (i=1; i<=bytes; i++)
{
*ptr++ = j++;
len++;
if ( (i%BULK_DRIVE_BUFFER_SIZE)==0 || i==bytes )
{
if (len != write(fd,buffer,len))
{
fprintf (fout, "bulkWrite() error writing %u to %s\n",
i,filePath);
close(fd);
return ERROR;
}
if (i%BULK_DRIVE_DISPLAY_INTERVAL == 0)
{
fprintf (fout, "bulkWrite() wrote %u of %u bytes\n",
i,bytes);
}
len = 0;
k++;
j = k;
ptr = (UINT8 *) buffer;
}
}
close(fd);
fprintf (fout, "bulkWrite() wrote %u bytes to %s\n",i-1,filePath);
return RET_CONTINUE;
}
B:读数据过程
LOCAL UINT16 bulkRead
(
long bytes,
FILE *fin, /* stream for input (if any) */
FILE *fout /* stream for output (if any) */
)
{
/* Initialize the BULK class driver */
char filePath[1000];
char buffer[BULK_DRIVE_BUFFER_SIZE];
UINT8 *ptr;
int fd;
int i;
UINT8 j=1,k=1;
int len;
UINT32 totLen=0;
sprintf(filePath,"%sbulkFile",BULK_DRIVE_NAME);
fd = open(filePath, O_RDONLY, 0);
if (fd == ERROR)
fprintf (fout, "bulkRead() error opening %s\n",filePath);
else
fprintf (fout, "bulkRead() %s opened for read\n",filePath);
ptr = (UINT8 *) buffer;
while ((len=read(fd,buffer,BULK_DRIVE_BUFFER_SIZE)) > 0)
{
for (i=0; i<len; i++)
{
totLen++;
if (*ptr++ != j++)
{
fprintf (fout, "bulkRead() error %u != %u at %u from %s\n",
*(ptr-1),j-1,totLen,filePath);
close(fd);
return ERROR;
}
if (totLen%BULK_DRIVE_DISPLAY_INTERVAL == 0)
{
fprintf (fout, "bulkRead() verified %u of %u bytes\n",
totLen,bytes);
}
}
k++;
j = k;
ptr = (UINT8 *) buffer;
}
close(fd);
if (totLen==bytes)
{
fprintf (fout, "bulkRead() verified %u bytes from %s\n",
totLen,filePath);
}
else
{
fprintf (fout, "bulkRead() error reading at %u of %u in %s\n",
totLen,bytes,filePath);
return ERROR;
}
return RET_CONTINUE;
}
7:USB代码的注意点
这一周主要在研究USB代码的架构,发现一些问题:
(1) 数据是以祯的方式传输的,数据包的开头是一段同步字段,同步字段的结尾是PID开始的标志,包结束是以EOP为结束的标志.
(2) PE通过读出CSR以及Buffer里面的状态,来决定数据传输的可靠性,并不是PE来控制CSR
(3) 仲裁器仲裁总线传输和DMA传输, CSR[15]是DMA使能位,但是发现找不到DMA request 的触发,Wishbone部分并没有对这个信号进行相应的处理
(4) 从主机发过来的token会有两个token寄存器进行寄存,token的每个位都有相应的含义
(5) 主机每秒发送的祯的个数,祯在Top层有一个祯的计数器
(6) 在代码中,要保持信号的稳定性,往往都是采用计数器的方法,计数到一定时间后,再采样一次,这样来保持数据的稳定性
VxWorks下USB驱动总结2的更多相关文章
- VxWorks下USB驱动总结1
1.USB设备 物理特征:4条电缆,电源线.地线.数据线.脉冲线; 速 度:低速1.5Mbps,全速12Mbps,高速480Mbps; 规范版本:1998年USB1.1,2000年USB2.0; 连 ...
- 转: 嵌入式linux下usb驱动开发方法--看完少走弯路【转】
转自:http://blog.csdn.net/jimmy_1986/article/details/5838297 嵌入式linux下的usb属于所有驱动中相当复杂的一个子系统,要想将她彻底征服,至 ...
- 对于vxworks下硬盘驱动
1.曾经看到帖子说vxworks5.5下没有sata驱动,vxworks6.6下有,这样的说法恐怕不正确,由 于俺在5.5下也运用运用了sata硬盘,请注重这里俺只是说运用运用,没有说运用运用了sat ...
- Linux下USB驱动框架分析【转】
转自:http://blog.csdn.net/brucexu1978/article/details/17583407 版权声明:本文为博主原创文章,未经博主允许不得转载. http://www.c ...
- linux下usb驱动接口中端点介绍
端点 USB 通讯的最基本形式是通过一个称为端点的东西.一个USB端点只能向一个方向传输数据(从主机到设备(称为输出端点)或者从设备到主机(称为输入端点)).端点可被看作一个单向的管道. 一个 USB ...
- 八、USB驱动分析
学习目标:分析USB驱动源码结构. 一.Windows下USB驱动理论问题 1. 当usb设备接入PC时,右下角弹出"发现AAA",并弹出对话框,提示安装驱动程序.没有驱动程序,W ...
- Linux下 USB设备驱动分析(原创)
之前做过STM32的usb HID复合设备,闲来看看linux下USB设备驱动是怎么一回事, 参考资料基于韦东山JZ2440开发板,以下,有错误欢迎指出. 1.准备知识 1.1USB相关概念: USB ...
- Linux下usb设备驱动详解
USB驱动分为两块,一块是USB的bus驱动,这个东西,Linux内核已经做好了,我们可以不管,我们只需要了解它的功能.形象的说,USB的bus驱动相当于铺出一条路来,让所有的信息都可以通过这条USB ...
- Linux 下wifi 驱动开发(四)—— USB接口WiFi驱动浅析
源: Linux 下wifi 驱动开发(四)—— USB接口WiFi驱动浅析
随机推荐
- svn基本操作和图标介绍
注意事项: .svn这个隐藏目录记录着两项关键信息:工作文件的基准版本和一个本地副本最后更新的时间戳,千万不要手动修改或者删除这个.svn隐藏目录和里面的文件!!,否则将会导致你本地的工作拷贝( ...
- copy-webpack-plugin最简使用示例
拷贝文件的插件 加载插件 $ npm install copy-webpack-plugin --save-dev API new CopyWebpackPlugin(patterns: Array, ...
- JAVA关键字Volatile的特性
一.简述: 关键字Volatile是JAVA虚拟机提供的最轻量级的同步机制,但是它并不容易完全被正确.完整的理解,以致于许多程序员在遇到需要处理多线程数据竞争的时候一律使用synchronized来进 ...
- JAVA并发编程学习笔记------对象的可见性及发布逸出
一.非原子的64位操作: 当线程在没有同步的情况下读取变量时,可能会得到一个失效值,但至少这个值是由之前某个线程设置的值,而不是一个随机值,这种安全性保证被称为最低安全性.最低安全性适用于绝大多数变量 ...
- 精通libGDX游戏开发-RPG实战-开发游戏的基本前提
说起RPG,大概国人是不会陌生的. 这不得不从中国单机游戏市场说起,由于早期软件市场被盗版杀死,顺带的,单机游戏软件作为软件市场的分支,也没赚什么钱,养不活公司纷纷倒闭,只到RPG游戏<仙剑奇侠 ...
- 在高并发、高负载的情况下,如何给表添加字段并设置DEFAULT值?
在高并发.高负载的情况下,如何给表添加字段并设置DEFAULT值? 在Oracle 12c之前,当Oracle表数据量上亿时,对表执行“ALTER TABLE XXX ADD COLUMN_XX VA ...
- NOIP 2017 Day 0. 游记
刚从曲师大试机回来... 不巧,我抽到了和去年一样的考场,还是那么难用的XP,还是那么难用的键盘. 似乎在考场上有一股奇怪的力量,我本来在自己电脑上打板子打的没那么快,但是试机的那段时间..说出来你们 ...
- BZOJ 3209: 花神的数论题 [数位DP]
3209: 花神的数论题 题意:求\(1到n\le 10^{15}\)二进制1的个数的乘积,取模1e7+7 二进制最多50位,我们统计每种1的个数的数的个数,快速幂再乘起来就行了 裸数位DP..\(f ...
- BZOJ 3622: 已经没有什么好害怕的了 [容斥原理 DP]
3622: 已经没有什么好害怕的了 题意:和我签订契约,成为魔法少女吧 真·题意:零食魔女夏洛特的结界里有糖果a和药片b各n个,两两配对,a>b的配对比b>a的配对多k个学姐就可能获胜,求 ...
- 夏令营提高班上午上机测试 Day 3 解题报告
今天的题的确水.T3还是一道NOIP原题. 嘛,多刷点水题也不是什么坏事嘛. 说来也快,夏令营结束了整一星期了呢.大家也都回到了日常的暑假生活呢. 今天学业水平测试出成绩了...嗯结果还算满意呢,至少 ...