Select *Stack\Parameters\DeviceIoControl\IoControlCode Case #IOCTL_hEvent hEvent = PeekL(*pIrp\SystemBuffer) If hEvent *DeviceExtension = *DeviceObject\DeviceExtension If *DeviceExtension\pEventObject ObDereferenceObject(*DeviceExtension\pEventObject) *DeviceExtension\pEventObject=0 EndIf ObReferenceObjectByHandle(hEvent, #SYNCHRONIZE, #Null, #UserMode, @*DeviceExtension\pEventObject, #Null) EndIf Default ntStatus = #STATUS_UNSUCCESSFUL EndSelect Else ntStatus = #STATUS_BUFFER_TOO_SMALL EndIf *pIrp\IoStatus\Information = 0 *pIrp\IoStatus\Status = ntStatus IoCompleteRequest(*pIrp, #IO_NO_INCREMENT) Procedure CreateDispatch(*DeviceObject.DEVICE_OBJECT, *Irp.IRP) *Irp\IoStatus\Information = 0 *Irp\IoStatus\Status = #STATUS_SUCCESS IoCompleteRequest(*Irp, #IO_NO_INCREMENT) ProcedureReturn #STATUS_SUCCESS EndProcedure Procedure DriverUnload(*DriverObject.DRIVER_OBJECT) Protected uniDOSString.UNICODE_STRING Protected *Extension.LOCAL_DEVICE_INFO = *DriverObject\DeviceObject\DeviceExtension ; Disconnect Interrupt IoDisconnectInterrupt(*Extension\InterruptObject) If *Extension\pEventObject ObDereferenceObject(*Extension\pEventObject) *Extension\pEventObject=0 EndIf ; Delete Device IoDeleteDevice(*DriverObject\DeviceObject) DbgPrint(«Unload Driver») !CALL _PB_EOP ; Освобождение ресурсов. Procedure DriverEntry(*DriverObject.DRIVER_OBJECT, *RegistryPath.UNICODE_STRING) Protected *DeviceObject.DEVICE_OBJECT, *DeviceExtension.LOCAL_DEVICE_INFO Protected MappedVector.l, Irql.KIRQL, EventHandle.l, Status.i Protected.UNICODE_STRING uniNameString, uniDOSString, EventName SetPoolMode(#Pool_Auto) ; Автоматический выбор типа памяти в зависимости от IRQL. Status = IoCreateDevice(*DriverObject,SizeOf(LOCAL_DEVICE_INFO),@uniNameString, #FILE_DEVICE_UNKNOWN,0,#True,@*DeviceObject) If Status = #STATUS_SUCCESS *DeviceExtension = *DeviceObject\DeviceExtension Status = IoCreateSymbolicLink(@uniDOSString, @uniNameString); If Status = #STATUS_SUCCESS *DeviceExtension\Level = 7 *DeviceExtension\Vector = *DeviceExtension\Level MappedVector = HalGetInterruptVector(#Isa,0,*DeviceExtension\Level, *DeviceExtension\Vector,@Irql, @*DeviceExtension\Affinity) Status = IoConnectInterrupt(@*DeviceExtension\InterruptObject,@Isr(), *DeviceObject,#Null,MappedVector,Irql,Irql, #Latched,#False,*DeviceExtension\Affinity,#False) If Status = #STATUS_SUCCESS *DriverObject\MajorFunction[#IRP_MJ_CREATE] = @CreateDispatch() *DriverObject\MajorFunction[#IRP_MJ_CLOSE] = @CreateDispatch() *DriverObject\MajorFunction[#IRP_MJ_DEVICE_CONTROL] = @DeviceIoControl() *DriverObject\DriverUnload = @DriverUnload() DataSection Device: !du ‘\Device\pbIntLPT’, 0, 0 DosDevices: !du ‘\DosDevices\pbIntLPT’, 0, 0 Event: !du ‘\BaseNamedObjects\SignalEventLPT’, 0, 0 EndDataSection Select Code Case #IOCTL_READ_PORT_UCHAR InByte.b=InPort(address) PokeB(*pIrp\SystemBuffer, InByte) *pIrp\IoStatus\Information = 1 Case #IOCTL_WRITE_PORT_UCHAR OutPort(address, Byte) *pIrp\IoStatus\Information = 0 Default ntStatus = #STATUS_UNSUCCESSFUL *pIrp\IoStatus\Information = 0 EndSelect *pIrp\IoStatus\Status = ntStatus IoCompleteRequest(*pIrp, #IO_NO_INCREMENT) Procedure CreateDispatch(*DeviceObject.DEVICE_OBJECT, *pIrp.IRP) *pIrp\IoStatus\Information = 0 *pIrp\IoStatus\Status = #STATUS_SUCCESS IoCompleteRequest(*pIrp, #IO_NO_INCREMENT) ProcedureReturn #STATUS_SUCCESS EndProcedure status = IoCreateSymbolicLink(@uniDOSString, @uniNameString) If status <> #STATUS_SUCCESS IoDeleteDevice(@deviceObject) ; Мы должны сами убирать «хвосты» в режиме ядра! ProcedureReturn status EndIf *DriverObject\MajorFunction[#IRP_MJ_CREATE] = @CreateDispatch() *DriverObject\MajorFunction[#IRP_MJ_DEVICE_CONTROL] = @DeviceIoControl() ; DataSection CompilerSelect #PB_Compiler_Processor CompilerCase #PB_Processor_x86 Device: !du ‘\Device\pbdriverio’, 0, 0 DosDevices: !du ‘\DosDevices\pbdriverio’, 0, 0 CompilerCase #PB_Processor_x64 Device: !du ‘\Device\pbdriverio_x64’, 0, 0 DosDevices: !du ‘\DosDevices\pbdriverio_x64’, 0, 0 CompilerEndSelect EndDataSection Соврешенно верно. Современные МК только кажутся сложными, а как начнешь изучать выясняется что они довольно простые. ODR ^= GPIO_Pin_13; // Инвертирование вывода PC13. > > void Init(void) // Инициализация периферии. < RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); // Включение тактирования таймера RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE); // и порта GPIOC. // Настройка порта в/в PC13. GPIO_InitTypeDef gpio; gpio.GPIO_Pin = GPIO_Pin_13; // Пин 13. gpio.GPIO_Mode = GPIO_Mode_Out_PP; // Выход типа push-pull. gpio.GPIO_Speed = GPIO_Speed_50MHz; // Предельная частота выхода. GPIO_Init(GPIOC, &gpio); // Конфигурация GPIOC. // Настройка таймера. TIM_TimeBaseInitTypeDef Tim; TIM_TimeBaseStructInit(&Tim); // Настройки таймера по умолчанию. TIM_TimeBaseInit(TIM2, &Tim); // Инициализация таймера TIM2 с заданными настройками. TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE); // Разрешение прерываний по переполнению. NVIC_EnableIRQ(TIM2_IRQn); // Разрешение прерываний от таймера. TIM_Cmd(TIM2, ENABLE); // Запуск таймера. > int main(void) < SystemCoreClockUpdate(); // Вычисление текущей частоты ядра. Init(); // Инициализация периферии. Источник |