0
Follow
0
View

How to set SPI Rate in windows KMDF driver

ricesky 注册会员
2023-02-28 15:15

This answer references ChatGPT
You can set the rate of SPI using the SpbRequestBusSpeed function in the SPB framework, which takes one argument, That is, the SPI rate to be set. You can use the SPB_BUS_SPEED_XXX macro to set a different rate, where XXX indicates the rate to be set, for example SPB_BUS_SPEED_FULL indicates the maximum rate.

dfh66889 注册会员
2023-02-28 15:15

To set the SPI rate in Windows KMDF driver, we need to use SPI IOCTL to set, which includes two key parameters:

SPI transfer parameters structure: This structure contains some parameters of SPI data transmission, such as transmission type, bandwidth, etc.

IOCTL SPI_GET_DEVICE_PROPERTY: The IOCTL obtains the attributes of the SPI device, such as the maximum clock frequency.

Here is an example of code that sets the SPI clock rate in a basic KMDF SPI driver:

SPI_TRANSFER_PARAMETERS spiParams;
ULONG maxFrequency;

// 获取 SPI 设备的最大时钟频率
IoctlStatus = WdfIoTargetSendIoctlSynchronously(
                  IoTarget,
                  NULL,
                  IOCTL_SPI_GET_DEVICE_PROPERTY,
                  NULL,
                  0,
                  &maxFrequency,
                  sizeof(maxFrequency),
                  NULL);

if (!NT_SUCCESS(IoctlStatus)) {
    // 处理 IOCTL 错误
}

// 设置 SPI 数据传输参数
RtlZeroMemory(&spiParams, sizeof(spiParams));
spiParams.Size = sizeof(spiParams);
spiParams.SpiMode = SPI_MODE_0;
spiParams.MaxFrequency = maxFrequency; // 使用 SPI 设备的最大时钟频率

// 执行 SPI 数据传输
IoctlStatus = WdfIoTargetSendIoctlSynchronously(
                  IoTarget,
                  NULL,
                  IOCTL_SPI_TRANSFER,
                  &spiParams,
                  sizeof(spiParams),
                  NULL,
                  0,
                  NULL);

if (!NT_SUCCESS(IoctlStatus)) {
    // 处理 IOCTL 错误
}

It should be noted that the above code is only an example, and it needs to be adjusted according to specific SPI devices and application requirements in actual situations. In addition, the specific use method of SPI device also needs to refer to relevant documents or refer to the driver provided by the hardware manufacturer

In the KMDF driver, the Serial Peripheral Bus(SPB) frame is used to control the speed of the SPI bus.

The specific implementation process is as follows:

in driven EvtDeviceAdd callback function, call WdfDeviceCreateDeviceInterface function to create a device interface driver.

In the driver, open the driver registry key using the WdfDeviceOpenRegistryKey function, and then use the WdfRegistryQueryValue function to get information about the SPI bus, such as the frequency of the SPI bus.

in the driver, use WdfDeviceRetrieveDeviceProperty function pointer to.spb controller device object, and call the SpbControllerGetConnectionSettings function get connection Settings, This includes the clock source and clock frequency of the SPI bus.

use SpbControllerSetTargetConnectionSettings function sets the SPI bus clock frequency to frequency.

After initializing the SPI bus, other functions provided by the SPB framework can be used for SPI data

deny0508 注册会员
2023-02-28 15:15

In the KMDF driver, you can use functions provided by the SPB framework to set the rate of the SPI bus. Specifically, you can use the SPB_CONTROLLER_CONFIG_INIT macro and SPB_CONTROLLER_CONFIG structure to set parameters for the SPI bus, including the clock frequency(i.e., rate).

Here is an example code to set the rate of the SPI bus:

NTSTATUS status;
SPB_CONTROLLER_CONFIG spbConfig;
SPB_CONNECTION_PARAMETERS spbConnectionParams;

// 初始化SPB控制器配置
SPB_CONTROLLER_CONFIG_INIT(&spbConfig, 0);
spbConfig.ConnectionParametersPtr = &spbConnectionParams;

// 设定SPI总线速率
spbConfig.SpbDriverParameters.SpiConnectionParameters.SpiClockFrequency = 1000000; // 1MHz

// 通过SPB框架创建SPB连接对象
status = SpbDeviceCreateConnection(Device, &spbConfig, &Connection);
if (!NT_SUCCESS(status))
{
    // 连接创建失败,处理错误
}

In the above code, we first initialize the SPB_CONTROLLER_CONFIG_INIT macros and set the ConnectionParametersPtr field to & spbConnectionParams, which is a SPB_CONNECTION_PARAMETERS structure object.

then, we through spbConfig SpbDriverParameters. SpiConnectionParameters. SpiClockFrequency field, set the rate of SPI bus of 1 MHZ, which is 1000000. Finally, by SpbDeviceCreateConnection function creates.spb connection object, and spbConfig passed as a parameter.

Note that in actual development, you need to adjust the speed and other parameters according to your specific situation. Alternatively, if more complex SPI controls are required, you can refer to other functions and constructs provided by the SPB framework.

daiyufei123 注册会员
2023-02-28 15:15

The SPB framework is required to set the rate of the SPI bus in the Windows KMDF driver. The SPB framework provides a common SPI interface for communicating with various peripherals. In order to set the rate of SPI, need is realized in drive EvtDevicePrepareHardware callback function, and use the.spb framework SpbPeripheralGetConnectionParameters function to obtain the connection parameters. In this function, you can specify the rate of the SPI bus. For example:

NTSTATUS
EvtDevicePrepareHardware(
    _In_ WDFDEVICE Device,
    _In_ WDFCMRESLIST ResourcesRaw,
    _In_ WDFCMRESLIST ResourcesTranslated
    )
{
    NTSTATUS status;
    SPB_CONNECTION_PARAMETERS spiConnectionParams;

    // Get the SPB target from the device context
    SPB_TARGET *spiTarget = GetSpbTarget(Device);

    // Get the SPI connection parameters
    RtlZeroMemory(&spiConnectionParams, sizeof(SPB_CONNECTION_PARAMETERS));
    status = SpbPeripheralGetConnectionParameters(
        spiTarget,
        &spiConnectionParams,
        sizeof(SPB_CONNECTION_PARAMETERS)
        );

    if (!NT_SUCCESS(status)) {
        // Failed to get connection parameters
        return status;
    }

    // Set the SPI clock frequency to 1MHz
    spiConnectionParams.ConnectionParameters.SpiConnectionParameters.SpiClockFrequency = 1000000;

    // Set the SPI connection parameters
    status = SpbPeripheralSetConnectionParameters(
        spiTarget,
        &spiConnectionParams,
        sizeof(SPB_CONNECTION_PARAMETERS)
        );

    if (!NT_SUCCESS(status)) {
        // Failed to set connection parameters
        return status;
    }

    return status;
}
duck0083 注册会员
2023-02-28 15:15

See the following example: kmdf driver tutorial 2 -- Driver and application communication, link: https://blog.csdn.net/hustd10/article/details/50589743

ctrl61 注册会员
2023-02-28 15:15
https://www.baidu.com/link?url=r7Kx_ADmi2wM9qeeFfKnMd3IFCgsdBxuUqpUeyOzLaaXFWq4Upgwl4U_p4gMwNLcanwF3Z6Hn7l58_4QrR651nwBqXT8gT44tO4AC5ODiaa& wd =, eqid = bf6c02f60011b5de0000000263ef565c < / >
< !- - - - - >
cxzhou520 注册会员
2023-02-28 15:15
czmike 注册会员
2023-02-28 15:15

My driver is a client driver, not a controller driver, cannot get SPB_CONTEXT

cuxiaozhuge 注册会员
2023-02-28 15:15

Here is an example code to set the SPI rate:

SPB_TRANSFER_LIST_AND_ENTRIES(2) SpbTransferList = {0};
SPB_TRANSFER_LIST_ENTRY SpbTransferListEntries[2] = {0};

// 设置SPI时钟极性和相位
SpbTransferListEntries[0].Flags = SPB_TRANSFER_LIST_FLAG_WRITE;
SpbTransferListEntries[0].DelayInUs = 0;
SpbTransferListEntries[0].BufferSize = 1;
SpbTransferListEntries[0].Buffer[0] = SPI_MODE_0;

// 设置SPI传输速率
SpbTransferListEntries[1].Flags = SPB_TRANSFER_LIST_FLAG_WRITE;
SpbTransferListEntries[1].DelayInUs = 0;
SpbTransferListEntries[1].BufferSize = 2;
SpbTransferListEntries[1].Buffer[0] = (CCHAR)(SPI_CLOCK_DIVIDER >> 8);
SpbTransferListEntries[1].Buffer[1] = (CCHAR)(SPI_CLOCK_DIVIDER & 0xFF);

// 将设置封装到SPB_TRANSFER_LIST中
SpbTransferList.TotalTransfers = 2;
SpbTransferList.Transfers = SpbTransferListEntries;

// 调用SPB库函数发送SPB_REQUEST_PACKET
status = SpbWriteDataSynchronously(SpbDevice, &SpbTransferList, NULL);

where SPI_MODE_0 is the SPI mode with clock polarity 0 and phase 0. SPI_CLOCK_DIVIDER Specifies the SPI rate. You can change this parameter to change the transfer rate.

jiaoliuyang321 注册会员
2023-02-28 15:15

Write based on Monster group and GPT:
Set SPI rate using WDFSPBREQUEST object in client driver:

NTSTATUS SetSpiClockRate(
In WDFDEVICE Device,
In ULONG ClockRateInHz
)
{
NTSTATUS status;
WDFSPBREQUEST spbRequest;
SPB_TRANSFER_LIST_AND_ENTRIES(2) transferList;
SPB_TRANSFER_LIST_INIT(&(transferList.List), 2);
// 设置 SPI 速率
SPB_TRANSFER_ELEMENT_INIT(&(transferList.List.Transfers[0]), 0, 0, 0, 0);
transferList.List.Transfers[0].Flags |= SPB_TRANSFER_DIRECTION_NONE;
transferList.List.Transfers[0].DelayInUs = 0;
transferList.List.Transfers[0].Length = 0;
transferList.List.Transfers[0].NextTransfer = &(transferList.List.Transfers[1]);
transferList.List.Transfers[0].Command.Sequence = SPB_TRANSFER_SEQUENCE_DEFAULT;

SPB_TRANSFER_ELEMENT_INIT(&(transferList.List.Transfers[1]), 0, 0, 0, 0);
transferList.List.Transfers[1].Flags |= SPB_TRANSFER_DIRECTION_NONE;
transferList.List.Transfers[1].DelayInUs = 0;
transferList.List.Transfers[1].Length = 0;
transferList.List.Transfers[1].NextTransfer = NULL;
transferList.List.Transfers[1].Command.Sequence = SPB_TRANSFER_SEQUENCE_DEFAULT;

// 获取 WDFSPBREQUEST 对象
status = WdfIoTargetFormatRequestForIoctl(
    WdfDeviceGetIoTarget(Device),
    spbRequest,
    IOCTL_SPB_EXECUTE_SEQUENCE,
    NULL,
    NULL,
    NULL,
    NULL
    );
if (!NT_SUCCESS(status))
{
    return status;
}

// 设置 SPI 速率
status = WdfIoTargetSendIoctlSynchronously(
    WdfDeviceGetIoTarget(Device),
    NULL,
    spbRequest,
    IOCTL_SPB_SET_CONNECTION_PARAMETERS,
    &(SpbContext->ConnectionParameters),
    sizeof(SPB_CONNECTION_PARAMETERS),
    NULL,
    NULL
    );
if (!NT_SUCCESS(status))
{
    return status;
}

// 发送 SPI 传输请求
status = WdfIoTargetSendIoctlSynchronously(
    WdfDeviceGetIoTarget(Device),
    NULL,
    spbRequest,
    IOCTL_SPB_EXECUTE_SEQUENCE,
    &(transferList.List),
    sizeof(SPB_TRANSFER_LIST),
    NULL,
    NULL
    );
if (!NT_SUCCESS(status))
{
    return status;
}

return status;
}

About the Author

Question Info

Publish Time
2023-02-28 15:15
Update Time
2023-02-28 15:15