Cross-system gyroscope data low-latency perception method based on interrupt context penetration
Patent Information
- Application Number
- CN202611140364.9
- Authority / Receiving Office
- CN · China
- Patent Type
- Applications(China)
- Current Assignee / Owner
- Filing Date
- 2026-07-30
- Publication Date
- 2026-08-28
AI Technical Summary
[0003]然而,现有通用虚拟化容器传感器传输架构仍存在难以通过参数调优解决的底层缺陷,具体包括:一是多级转发链路逐级累积延迟,传感器数据完整传输链路跨越硬件驱动、宿主内核、宿主传感器服务、虚拟化跨域通信通道、容器内传感器框架、上层应用等多层处理,形成多级串行转发路径,每一层均包含接口调用、临时缓冲、数据格式转换、跨域消息序列化等微秒级开销,在高频采样工况下链路总累积延迟显著增加,难以满足低时延闭环需求;二是多内存拷贝开销随高频采样被持续放大,数据完整流转需要依次经过硬件片上缓存、宿主内核地址空间、宿主用户态缓冲区、容器进程虚拟地址空间等多次完整内存拷贝,高频小数据包场景下拷贝开销成为性能瓶颈;三是中断处理链路冗长,响应时延突破采样阈值,硬件中断送达宿主内核后,需完整执行中断顶半部硬件确认、底半部数据分发、系统传感器服务事件上报全流程,再经由虚拟化通道转发至容器,极易出现硬件先进先出缓冲区数据堆积、帧丢失、时序错乱等问题;四是宿主与容器跨域协同机制完全割裂,宿主系统、容器客户端的传感器运行逻辑相互独立,没有参数协商通道,采样速率配置互不感知,容器应用请求高频率采样时,宿主仍按默认低速率采集,只能依靠软件插值补齐数据,引入额外时序误差,另外,时间戳由宿主侧统一生成后转发,与硬件ADC采样真实时刻存在偏移,造成应用层延迟误判,容器数据接收线程与宿主中断处理线程调度策略、优先级完全隔离,容器线程频繁被系统后台任务抢占,数据处理持续滞后;五是静态共享内存同步机制存在读写冲突损耗,现有方案采用固定容量静态共享内存作为跨域数据载体,未适配传感器的生产者及消费者异步读写模型,只能依靠互斥锁完成读写同步,高频采样场景下锁竞争、锁等待概率大幅提升,进一步放大传输抖动与平均延迟
[0023]This invention encapsulates the gyroscope subscription request initiated by the container application into a subscription request contract and sends it to the host. The host parses the request and, in conjunction with hardware capability parameters, negotiates and generates a collaborative contract to complete cross-domain address mapping verification. Then, the host creates a gyroscope interrupt and data writing thread bound to a specified core and with a unified real-time priority. The container synchronously creates a data receiving thread with a matching priority. The host configures the gyroscope sampling frequency division, data precision, hardware timestamp, and interrupt penetration kernel processing logic according to the collaborative contract. After the gyroscope hardware sampling generates an interrupt, the kernel sends a custom signal to wake up the container receiving thread. At the same time, the acquisition thread is woken up to generate a global frame sequence number and calculate the offset sequence number in the buffer by modulo operation. A complete gyroscope data frame carrying a double-layer frame sequence number and a checksum is assembled. The host atomically filters the writable buffer and writes the data frame to the shared memory buffer through DMA zero-copy. When the single buffer is full, the buffer checksum and status are updated. After the container receiving thread is woken up, it filters the full buffer, reads the frame data and completes the verification. After reading the data, the buffer status is reset, and the sensor data is extracted, encapsulated into a sensor event callback, and pushed to the upper-layer application.
Smart Images

Figure CN122653793A_ABST
Abstract
Description
Technical Field
[0001] This invention belongs to the field of computer software development technology, specifically relating to a low-latency sensing method for cross-system gyroscope data based on interrupt context penetration. Background Technology
[0002] In heterogeneous virtualization architectures where guest containers or virtual machines run on the host operating system, the transmission of high-frequency inertial sensor hardware data, such as MEMS gyroscopes, to applications within the container generally suffers from multi-layered link redundancy and a lack of cross-domain scheduling coordination. The overall end-to-end latency is significantly higher than that of directly acquiring data from native applications within the same system. Gyroscopes sense spatial angular motion through MEMS microelectromechanical structures, converting mechanical displacement into analog electrical signals. After analog-to-digital conversion by an on-chip ADC, batch sampling is triggered by hardware interrupts. A single frame of sampled data contains three-axis angular velocity and a timestamp, exhibiting typical high-frequency sensing characteristics.
[0003] However, existing general-purpose virtualized container sensor transmission architectures still suffer from fundamental defects that are difficult to resolve through parameter tuning. These defects include: First, the multi-level forwarding links accumulate latency at each level. The complete sensor data transmission link spans multiple layers of processing, including hardware drivers, the host kernel, host sensor services, virtualized cross-domain communication channels, the in-container sensor framework, and upper-layer applications, forming a multi-level serial forwarding path. Each layer contains microsecond-level overhead such as interface calls, temporary buffers, data format conversions, and cross-domain message serialization. Under high-frequency sampling conditions, the total accumulated latency of the link increases significantly, making it difficult to meet the low-latency closed-loop requirements. Second, the overhead of multiple memory copies is continuously amplified with high-frequency sampling. The complete data flow requires multiple complete memory copies, sequentially passing through the hardware on-chip cache, the host kernel address space, the host user-mode buffer, and the container process virtual address space. In high-frequency, small-data-packet scenarios, this copy overhead becomes a performance bottleneck. Third, the interrupt handling link is lengthy, and the response latency exceeds the sampling threshold. After a hardware interrupt is delivered to the host kernel, the entire process of hardware confirmation in the top half of the interrupt, data distribution in the bottom half, and event reporting by the system sensor service must be executed before... Forwarding data to containers via virtualization channels can easily lead to problems such as data accumulation in the hardware first-in-first-out buffer, frame loss, and timing errors. Fourth, the cross-domain collaboration mechanism between the host and container is completely disconnected. The sensor operation logic of the host system and the container client is independent of each other, with no parameter negotiation channel and no awareness of each other's sampling rate configuration. When the container application requests high-frequency sampling, the host still collects data at the default low rate, and can only rely on software interpolation to fill in the data, introducing additional timing errors. In addition, the timestamp is uniformly generated by the host side and forwarded, which is offset from the actual sampling time of the hardware ADC, causing application layer delays and misjudgments. The scheduling strategy and priority of the container data receiving thread and the host interrupt handling thread are completely isolated, and the container thread is frequently preempted by system background tasks, resulting in continuous data processing delays. Fifth, the static shared memory synchronization mechanism suffers from read-write conflict losses. The existing solution uses fixed-capacity static shared memory as a cross-domain data carrier, which is not adapted to the asynchronous read-write model of sensor producers and consumers. It can only rely on mutex locks to complete read-write synchronization. In high-frequency sampling scenarios, the probability of lock contention and lock waiting increases significantly, further amplifying transmission jitter and average latency.
[0004] In summary, current mainstream optimization methods in the industry only focus on surface-level parameter tuning and communication protocol simplification, which are insufficient to solve underlying bottleneck problems such as multi-layer forwarding, multiple replication, and fragmented cross-domain scheduling. Summary of the Invention
[0005] In view of this, the present invention provides a low-latency sensing method for cross-system gyroscope data based on interrupt context penetration. Through layered contract negotiation between container and host, unified configuration of hardware registers, kernel interrupt penetration wake-up and native event callback push, reliable and lock-free real-time transmission of raw gyroscope hardware sensing data is achieved from hardware acquisition, host shared memory cache, real-time reading by container to low-latency delivery to upper-layer application.
[0006] The present invention provides a low-latency sensing method for cross-system gyroscope data based on interruption context penetration, which specifically includes the following steps:
[0007] The container application initiates a gyroscope data subscription request, including the target sampling rate, data accuracy requirements, latency threshold and hardware timestamp enable flag, and encapsulates it into a subscription request contract after adding the container process ID, container application process priority and data receiving thread preset flag and sending it to the host.
[0008] The host resolves the basic parameters, obtains the hardware capability parameters, arbitrates to determine the optimal sampling rate, CPU cores, and shared memory capacity, allocates double the shared memory capacity as a double buffer, configures state control blocks for each buffer block, maps them to the container's virtual address space, and forms scheduling coordination parameters based on the host data writing thread priority, container data receiving thread mapping priority, CPU core identifier to be bound, double buffer physical address, number of single buffer frames, and single frame data size; a coordination contract is formed by the basic parameters, hardware capability parameters, and scheduling coordination parameters and sent to the container.
[0009] The host creates gyroscope interrupt threads and data write threads with the same scheduling policy and priority, and both are bound to the CPU core to be bound; the container creates a data receiving thread according to the cooperation contract and configures it with the same scheduling policy as the data writing thread; the host configures the gyroscope according to the cooperation contract, binds the interrupt vector number and interrupt penetration handling function, and initializes the container interrupt context associated with the container process and the data receiving thread.
[0010] After the gyroscope buffers angular motion data, it generates an interrupt signal. The host executes the interrupt penetration handling function to clear the interrupt flag and wakes up the container's data receiving thread. At the same time, the interrupt signal triggers the host interrupt thread to wake up the gyroscope acquisition thread, read the angular motion data and timestamp, and encapsulate the gyroscope data frame. The host filters free buffer blocks, establishes a DMA mapping between them and the gyroscope buffer, and writes the gyroscope data frame into the buffer block. After the data receiving thread is woken up, it reads the full buffer block, constructs the container sensor event object, and pushes it to the container application.
[0011] Furthermore, the host configures the gyroscope according to the cooperative contract as follows: calculate the gyroscope's frequency division coefficient based on the system clock frequency and the optimal sampling rate determined by the cooperative contract, and write the high 16 bits and low 16 bits of the frequency division coefficient into the gyroscope's extended register and sampling rate control register in sequence; determine the corresponding hardware configuration parameters according to the data precision requirements in the cooperative contract, and configure the gyroscope's data format register; select the system's high-precision hardware counter as the timing reference, enable the microsecond-level hardware timestamp and configure the automatic latching mechanism upon sampling completion, and simultaneously send the timestamp storage register address recorded in the cooperative contract to the gyroscope.
[0012] Furthermore, the simultaneous interrupt signal triggers the host interrupt thread to wake up the gyroscope acquisition thread, reads the angular motion data and timestamp, and encapsulates the gyroscope data frame. Specifically, the acquisition thread maintains a globally incrementing first frame sequence number, increments the first frame sequence number for each generated frame, and calculates the pre-encoded buffer offset sequence number of the first frame sequence number by taking the modulo of the number of single buffer frames agreed upon in the cooperative contract. Then, the buffered angular motion data is read according to a fixed timing sequence, and the hardware high-precision latched timestamp is read synchronously. The data is then encapsulated into a gyroscope data frame containing a hardware timestamp, angular motion data, a double-layer frame sequence number, a status identifier, and a check bit. The double-layer frame sequence number includes the first frame sequence number and the buffer offset sequence number.
[0013] Furthermore, the host filters free buffer blocks in the following way: the host reads the state of the state control block corresponding to each buffer block in the double buffer through atomic operations, filters the buffer blocks with the state of being free, and uses atomic comparison and swap operations to update the state of the selected buffer block from free to being written. If the atomic update fails, the host re-traverses and filters the buffer blocks.
[0014] Furthermore, the method of writing the gyroscope data frame into the buffer block is as follows: calculate the physical address of the gyroscope data frame in the buffer block according to the offset sequence number carried by the gyroscope data frame; establish a DMA mapping between the gyroscope hardware data buffer and the selected buffer block; configure the DMA source address, destination address, and single frame transmission length; start DMA transmission to write the gyroscope data frame into the buffer block; trigger a DMA interrupt after the DMA transmission is completed; and the HAL layer waits for the transmission to complete and clears the DMA interrupt flag.
[0015] When the number of frames written to the buffer block is equal to the maximum number of frames in a single buffer, the buffer block is determined to be full. The CRC32 checksum of all data frames in the buffer block is calculated and written to the corresponding status control block. The status is updated to full and the number of frames written is updated.
[0016] Furthermore, after the data receiving thread is awakened, it reads the full buffer block and constructs a container sensor event object to push to the container application in the following way: The data receiving thread reads the double-buffered state control block through atomic operations, filters the buffer blocks whose state is full, calculates the range of readable frames based on the sequence number of the written frames and the number of written frames in the buffer block, reads the frame data of the range of frames into the user space corresponding to the data receiving thread, completes the integrity verification, timing verification and timestamp validity verification of the frame data, and sets the state of the buffer block to idle; The container extracts the hardware timestamp and the three-axis angular velocity to construct the container sensor event object, and pushes it to the container application using the container's native sensor callback interface.
[0017] Furthermore, the host verifies whether the target sampling rate in the subscription request contract is within the supported range of the gyroscope. If it exceeds the supported range, the target sampling rate is modified to the maximum sampling rate of the gyroscope, and a correction log is recorded.
[0018] Furthermore, the arbitration determines the optimal sampling rate, CPU cores, and shared memory capacity in the following way:
[0019] If the target sampling rate is not greater than the maximum sampling rate, the optimal sampling rate is the target sampling rate; otherwise, the maximum sampling rate is used and a sampling rate degradation is marked in the log. Query the system CPU load and select CPU cores with loads less than the threshold as cores to be bound, prioritizing CPU cores with the same interrupt thread as the gyroscope. Calculate the memory buffer size according to the method that the number of single buffer frames is a set multiple of the sampling rate and the size of a single frame is a set value, and determine the optimal shared memory capacity.
[0020] Furthermore, the host monitors the thread scheduling status within the bound CPU cores in real time. When multiple highest-priority real-time threads are detected running concurrently, scheduling conflict handling is triggered: according to the strategy of prioritizing gyroscope-related threads, the scheduling priority of unrelated threads is temporarily reduced, and the original priority is restored after the gyroscope subscription is terminated; if the conflicting parties are the host's native gyroscope-related threads and the container's gyroscope-related threads, then the high sampling rate priority strategy is followed, and the scheduling priority of the thread with the lower sampling frequency is reduced.
[0021] Furthermore, after the data receiving thread is awakened, the wake-up delay is calculated based on the signal receiving timestamp and the thread wake-up timestamp. If the wake-up delay is greater than the threshold, the CPU core with a lower load is switched.
[0022] Beneficial effects:
[0023] This invention encapsulates the gyroscope subscription request initiated by the container application into a subscription request contract and sends it to the host. The host parses the request and, in conjunction with hardware capability parameters, negotiates and generates a collaborative contract to complete cross-domain address mapping verification. Then, the host creates a gyroscope interrupt and data writing thread bound to a specified core and with a unified real-time priority. The container synchronously creates a data receiving thread with a matching priority. The host configures the gyroscope sampling frequency division, data precision, hardware timestamp, and interrupt penetration kernel processing logic according to the collaborative contract. After the gyroscope hardware sampling generates an interrupt, the kernel sends a custom signal to wake up the container receiving thread. At the same time, the acquisition thread is woken up to generate a global frame sequence number and calculate the offset sequence number in the buffer by modulo operation. A complete gyroscope data frame carrying a double-layer frame sequence number and a checksum is assembled. The host atomically filters the writable buffer and writes the data frame to the shared memory buffer through DMA zero-copy. When the single buffer is full, the buffer checksum and status are updated. After the container receiving thread is woken up, it filters the full buffer, reads the frame data and completes the verification. After reading the data, the buffer status is reset, and the sensor data is extracted, encapsulated into a sensor event callback, and pushed to the upper-layer application. Attached Figure Description
[0024] Figure 1 This is a flowchart illustrating the low-latency sensing method for cross-system gyroscope data based on interruption context penetration provided by the present invention. Detailed Implementation
[0025] The present invention will be described in detail below with reference to the accompanying drawings and embodiments.
[0026] The cross-system gyroscope data low-latency perception method based on interrupt context penetration provided by this invention has the following core idea: The container encapsulates the gyroscope subscription request initiated by the container application into a subscription request contract and sends it to the host. The host parses the request and, in conjunction with hardware capability parameters, negotiates and generates a cooperative contract to complete cross-domain address mapping verification. Then, the host creates gyroscope interrupt and data writing threads that are bound to a specified core and have a unified real-time priority. The container synchronously creates a data receiving thread with a matching priority. The host configures the gyroscope sampling frequency division, data precision, hardware timestamp, and interrupt penetration kernel processing logic according to the cooperative contract. After the gyroscope hardware sampling generates an interrupt, the kernel sends a custom signal to wake up the container receiving thread. At the same time, it wakes up the acquisition thread to generate a global frame sequence number and calculate the offset sequence number in the buffer by taking the modulus. It then assembles a complete gyroscope data frame carrying a double-layer frame sequence number and a check bit. The host atomically filters the writable buffer and writes the data frame to the shared memory buffer through DMA zero-copy. When the single buffer is full, it updates the buffer checksum and status. After the container receiving thread is woken up, it filters the buffer that is full, reads the frame data and completes the verification. After reading the data, it resets the buffer status, extracts the sensor data, encapsulates it into a sensor event callback, and pushes it to the upper layer application.
[0027] The present invention provides a low-latency sensing method for cross-system gyroscope data based on interrupt context penetration, the processing flow of which is as follows: Figure 1 As shown, the specific steps include:
[0028] Step 1: The container application initiates a gyroscope data subscription request. The request includes the target sampling rate, data accuracy requirements, latency threshold, and hardware timestamp enable flag. After receiving the request, the container adds the container process ID, container application process priority, and data receiving thread preset flag to the request, and then encapsulates the request into a subscription request contract and sends it to the host.
[0029] The subscription request contract includes the target sampling rate, data accuracy requirements, latency threshold, hardware timestamp enable flag, container process ID, container application process priority, and preset flag for the container sensor data receiving thread. Furthermore, it verifies whether the target sampling rate is within the gyroscope's supported range; if it exceeds this range, the target sampling rate is modified to the maximum supported sampling rate, and a correction log is recorded.
[0030] Step 2: The host parses the subscription request contract to form basic configuration layer parameters; it obtains hardware capability parameters through the gyroscope driver, including maximum sampling rate, supported data precision, interrupt vector number, timestamp support identifier, data register start address, and timestamp register start address, forming hardware capability layer parameters; based on the subscription request contract and hardware capability layer parameters, arbitration determines the optimal sampling rate, CPU cores, and shared memory capacity, and allocates a contiguous physical memory area with twice the shared memory capacity as two independent data buffers, i.e., double buffering. For each buffer block of the double buffer, an independent state control block is set to record the buffer status, written frame sequence number, written frame number, read frame sequence number, read frame number, and checksum, obtain the physical address corresponding to the double buffer, calculate the state control block address, and map both the buffer physical address and the state control block address to the container process virtual address space. The container allocates the corresponding virtual address segment for in-container access, establishing a cross-domain address mapping relationship. The scheduling coordination layer parameters are formed by the host data writing thread priority, container data receiving thread mapping priority, CPU core identifier to be bound, physical address corresponding to the double buffer, number of single buffer frames, and single frame data size.
[0031] The coordination contract is formed by the basic configuration layer parameters, hardware capability layer parameters, and scheduling coordination layer parameters. After calculating the CRC32 check value of the coordination contract, the coordination contract and the check value are sent to the container. The container parses and verifies the contract. If the verification matches, it returns an acknowledgment response packet. Otherwise, it returns a renegotiation response packet to trigger the host to re-execute the negotiation process.
[0032] Specifically, based on the subscription request contract and hardware capability layer parameters, arbitration determines the optimal sampling rate, CPU cores, and shared memory capacity. Specifically: if the target sampling rate is not greater than the maximum sampling rate, the optimal sampling rate is the target sampling rate; otherwise, the maximum sampling rate is used, and a sampling rate downgrade is marked in the log. The system CPU load is queried, and CPU cores with loads below a threshold are selected as cores to be bound, further prioritizing CPU cores with the same interrupt thread as the gyroscope. The memory buffer size is calculated according to a set multiple of the sampling rate for the number of single buffer frames and a set value for the size of a single frame, thus determining the optimal shared memory capacity.
[0033] Furthermore, when the container application modifies the request parameters, the container generates a new subscription request contract, increments the version number of the original subscription request contract as the version number of the new subscription request contract, and sends it to the host, which then completes the update.
[0034] Step 3: The host creates a gyroscope interrupt thread and a data write thread, sets these two threads to the same real-time scheduling policy and priority, and binds them to the CPU core to be bound as determined by the cooperation contract. The priority is set according to the preset host container priority mapping table. The container creates a data receiving thread according to the preset identifier of the data receiving thread in the cooperation contract, and sends a priority mapping request to the host. The host sets the data receiving thread to the same real-time scheduling policy as the data write thread, and sets its priority according to the container data receiving thread mapping priority in the cooperation contract.
[0035] Furthermore, the host monitors the thread scheduling status within the bound CPU cores in real time. When multiple highest-priority real-time threads are detected running concurrently, scheduling conflict handling is triggered: according to the strategy of prioritizing gyroscope-related threads, the scheduling priority of unrelated threads is temporarily reduced, and the original priority is restored after the gyroscope subscription is terminated; if the conflicting parties are the host's native gyroscope-related threads and the container's gyroscope-related threads, then the high sampling rate priority strategy is followed, and the scheduling priority of the thread with the lower sampling frequency is reduced.
[0036] Step 4: The host calculates the gyroscope's frequency division coefficient based on the system clock frequency and the optimal sampling rate determined by the cooperative contract. The high 16 bits and low 16 bits of the frequency division coefficient are written to the gyroscope's extended register and sampling rate control register in sequence. The corresponding hardware configuration parameters are determined according to the data precision requirements in the cooperative contract, and the gyroscope's data format register is configured. The system's high-precision hardware counter is selected as the timing reference, microsecond-level hardware timestamps are enabled, and an automatic latching mechanism is configured upon completion of sampling. At the same time, the timestamp storage register address recorded in the cooperative contract is sent to the gyroscope to achieve precise marking and fixed storage of the sampling time.
[0037] The host replaces the original interrupt handling logic with the interrupt vector number in the cooperative contract, binds a custom gyroscope interrupt penetration handling function; initializes the container interrupt context, establishes the association between the interrupt context and the container process and data receiving thread in the kernel, and configures the gyroscope to use rising edge interrupt triggering mode.
[0038] Step 5: The angular motion is converted from analog to digital by the gyroscope hardware and the data is buffered. The gyroscope generates a hardware interrupt signal.
[0039] The host kernel executes the interrupt penetration handling function, verifies that the interrupt vector matches the target gyroscope and that the container process is in a normal operating state. If the verification passes, it writes to the register to clear the hardware interrupt flag. The host uses the task pointer of the data receiving thread to send a custom wake-up signal to it, and hides the default processing logic of the signal. The host kernel scheduler directly wakes up the container data receiving thread and adds it to the head of the bound CPU core run queue, and synchronously increments the interrupt sending counter.
[0040] The hardware interrupt signal generated by the gyroscope synchronously triggers the host local interrupt thread wake-up process, which wakes up the gyroscope acquisition thread. The acquisition thread maintains a globally incrementing first frame sequence number, incrementing the first frame sequence number with each generated frame. It calculates the pre-encoded buffer offset sequence number of the first frame sequence number by taking the modulo of the number of single buffer frames agreed upon in the cooperative contract. Then, it reads the original sensor data from the hardware cache according to a fixed timing sequence, synchronously reads the hardware high-precision latch timestamp, and encapsulates it into a gyroscope data frame containing the hardware timestamp, original business data, double-layer frame sequence number, status identifier, and check bit. The double-layer frame sequence number includes the first frame sequence number and the buffer offset sequence number.
[0041] Furthermore, after the data receiving thread is awakened, the wake-up delay is calculated based on the signal reception timestamp and the thread wake-up timestamp. If the wake-up delay is greater than the threshold, the CPU affinity configuration is adjusted, such as replacing the core with one that has a lower load.
[0042] Step 6: The host reads the state of the state control block corresponding to each buffer block in the double buffer through atomic operations, filters the buffer blocks with the state of being free, and uses atomic comparison and swap operations to update the state of the selected buffer block from free to being written. If the atomic update fails, the buffer blocks are traversed and filtered again.
[0043] Based on the buffer offset sequence number carried by the gyroscope data frame, calculate the physical address of the gyroscope data frame in the selected buffer block; establish DMA mapping between the gyroscope hardware data buffer and the selected buffer block, configure the DMA source address, destination address, and single frame transmission length, start DMA transmission to write the gyroscope data frame to the selected buffer block, trigger DMA interrupt after DMA transmission is completed, and the HAL layer waits for the transmission to complete and clears the DMA interrupt flag.
[0044] When the number of written frames in the selected buffer block is equal to the maximum number of frames in a single buffer, the selected buffer block is determined to be full. The CRC32 checksum of all data frames in the selected buffer block is calculated and written to the corresponding status control block. The status is updated to full and the number of written frames is updated.
[0045] Step 7: After the data receiving thread in the container is awakened by a custom wake-up signal, it reads the double-buffered state control block through atomic operations, filters the buffer blocks whose state is full, calculates the range of readable frames based on the sequence number of the written frames and the number of written frames in the buffer block, reads the frame data of the range of frames into the user space corresponding to the data receiving thread, completes the integrity verification, timing verification and timestamp validity verification of the frame data, and sets the state of the buffer block to idle; the container extracts the hardware timestamp and the three-axis angular velocity to construct the container sensor event object, and pushes it to the container application using the container's native sensor callback interface.
[0046] Step 8: When the container application initiates a subscription termination request, the container sends a subscription termination contract to the host, which includes the container PID, shared memory identifier, interrupt penetration channel identifier, and contract version number. The container reclaims the relevant resources. After receiving the subscription termination contract, the host stops hardware sampling, releases shared memory, closes the interrupt penetration channel, restores the gyroscope to its original state, and returns a resource reclamation completion signal to the container. The container records the reclamation log.
[0047] Example:
[0048] This embodiment employs the low-latency perception method for cross-system gyroscope data based on interrupt context penetration provided by the present invention. Using OpenHarmony as the host system and Android as the container system, it reconstructs the gyroscope data transmission link between the Android container and the host in OpenHarmony 5.0, eliminating transmission path redundancy, clearing data copy overhead, and ensuring timing consistency and scheduling coordination. This makes the total latency of the Android application within the container acquiring gyroscope data close to that of the native Android application, achieving near-native real-time data acquisition. The specific process includes:
[0049] S1. The Android application initiates a gyroscope data subscription request, which transmits the Android application's needs to the container.
[0050] S1.1 Android applications call the native Android Sensor API. Specifically, Android applications such as AR games initiate gyroscope data subscription by calling the SensorManager.registerListener() method.
[0051] S1.2 In this embodiment, the source code of SensorService within the Android container is modified, and a new request parsing and enhancement module is added to implement the request parsing and enhancement of the container SensorService. After receiving the request, this module converts the request parameters into the target sampling rate, data precision requirements, latency threshold, and whether to enable hardware timestamps. Among them, the data precision requirements are such as 32-bit floating-point type and include a temperature compensation field, and then performs the following operations:
[0052] Parameter validity verification: The requested sampling rate is verified to be within the range supported by the gyroscope hardware by checking the pre-stored hardware capability list. This list is synchronized by subsequent cross-layer negotiation. If it exceeds the range, it is corrected to the maximum supported sampling rate of the hardware and the correction log is recorded.
[0053] The request is enhanced by adding key information from the container side to the original request parameters, including the container process ID (PID), application process priority, and the default identifier of the sensor data receiving thread within the container, such as gyro_receive_thread.
[0054] A subscription request contract is generated, which encapsulates the corrected sampling rate, data precision, latency threshold, hardware timestamp enable flag, container PID, and thread flag into a subscription request contract using a preset protobuf simplified encoding format. This contract serves as a unified data carrier for cross-layer collaboration, ensuring that parameter transmission is error-free.
[0055] S1.3, the container initiates a contract request to the host. SensorService sends the subscription request contract to the OH host's Sensor Framework through the extended container virtualization interface, triggering a cross-layer negotiation process. The extended container virtualization interface is optimized based on the OpenHarmony IPC mechanism, simplifying interface fields and retaining only contract data to reduce the overhead of interface calls.
[0056] S2, the cross-layer sensor capability contract mechanism, responds to contract requests initiated by the container, unifies the configuration parameters of the OH host and the Android container through a standardized contract mechanism, solves the problem of missing cross-layer collaboration, and provides a unified basis for subsequent resource initialization and hardware configuration.
[0057] S2.1 Standardized definition of contract structure: Cross-layer collaborative contracts are divided into three levels: basic configuration layer, hardware capability layer, and scheduling coordination layer. Fields in each layer are encoded using protobuf 3.0, and all field types are in fixed-length format to avoid parsing overhead. The specific structure is as follows:
[0058] syntax = "proto3";
[0059] message GyroContract {
[0060] / / Basic configuration layer, specifically related to application requirements
[0061] message BasicConfig {
[0062] uint32 target_sample_rate = 1; / / Target sampling rate, in Hz, value from 1 to 1000
[0063] uint32 data_precision = 2; / / Data precision, 0 represents 16-bit integer, 1 represents 32-bit floating-point.
[0064] uint32 delay_threshold = 3; / / Delay threshold, in μs, with a value from 1 to 5000
[0065] bool enable_hw_timestamp = 4; / / Whether to enable hardware timestamps, the value is true or false
[0066] uint32 container_pid = 5; / / Container PID
[0067] string thread_identifier = 6; / / The container receives the thread identifier, which can be up to 32 bytes.
[0068] }
[0069] / / Hardware capability layer, i.e., the actual hardware support capabilities
[0070] message HardwareCap {
[0071] uint32 max_sample_rate = 1; p {
[0072] uint32 max_sample_rate = 1; / / Maximum hardware sampling rate, in Hz
[0073] uint32 supported_precision = 2; / / Supported data precision
[0074] bool hw_timestamp_support = 3; / / Whether to support hardware timestamps
[0075] uint32 irq_vector = 4; / / Gyroscope interrupt vector number
[0076] uint32 data_reg_addr = 5; / / Starting address of the data register, i.e., physical address
[0077] uint32 ts_reg_addr = 6; / / Start address of the timestamp register, i.e., the physical address
[0078] }
[0079] / / Scheduling coordination layer, including thread, memory, and interrupt coordination parameters.
[0080] message SchedConfig {
[0081] uint32 host_thread_prio = 1; / / Host thread priority (SCHED_FIFO, 1~100)
[0082] uint32 container_thread_prio = 2; / / Container thread priority mapping
[0083] uint32 cpu_core_id = 3; / / Bind CPU core ID
[0084] uint32 shm_buf_a_phy = 4; / / Physical address of shared memory Buffer A
[0085] uint32 shm_buf_b_phy = 5; / / Physical address of shared memory Buffer B
[0086] uint32 shm_frame_count = 6; / / Number of frames per buffer
[0087] uint32 frame_size = 7; / / Size of a single frame in bytes
[0088] }
[0089] BasicConfig basic = 1;
[0090] HardwareCap hardware = 2;
[0091] SchedConfig sched = 3;
[0092] uint32 contract_version = 4; / / Contract version
[0093] uint32 crc32 = 5; / / Overall CRC32 checksum
[0094] }
[0095] Contract version management: Major and minor version identifiers are used, such as 1.0, where 1 is the major version and 0 is the minor version. Changes to the major version indicate incompatible modifications, such as adding or deleting fields, while changes to the minor version indicate compatible modifications, such as extending fields. The container and the host ensure parsing compatibility through version negotiation.
[0096] S2.2 Contract negotiation.
[0097] During the contract initiation phase, the container SensorService sends the generated subscription request contract, which only contains BasicConfig level parameters, to the host through the virtualization interface. The interface transmission adopts a fixed header and contract data format. The header contains a contract length of 2 bytes and a version of 2 bytes to ensure that the host can quickly identify it.
[0098] During the hardware capability query phase, after the host sensor framework receives the contract, it calls the GetHardwareCap() method of the gyroscope driver through the HDF interface. The driver obtains the following capability parameters by accessing hardware registers, including: reading the maximum sampling rate by accessing the control register, whose physical address is 0x10, and the lower 16 bits are the maximum sampling rate value; reading the interrupt vector number by accessing the interrupt configuration register, whose physical address is 0x08, and the higher 8 bits are the interrupt vector number, such as 0x40 corresponding to IRQ 64; and determining hardware timestamp support by accessing the timestamp control register, whose physical address is 0x18, and bit 0 being 1 to indicate support. The above parameters are then filled into the HardwareCap level.
[0099] During the collaborative parameter arbitration phase, the host performs multi-dimensional arbitration, combining application requirements and hardware capabilities:
[0100] Sampling rate arbitration: If BasicConfig.target_sample_rate is not greater than HardwareCap.max_sample_rate, then the target value is used; otherwise, max_sample_rate is used, and a sampling rate degradation is marked in the log.
[0101] CPU core arbitration obtains the number of cores through sysconf(_SC_NPROCESSORS_CONF), obtains the load of each core through / proc / stat, selects the core with a load of no more than 10% as the binding core, and prioritizes the core that is the same as the gyroscope interrupt thread.
[0102] Memory parameter arbitration is used to calculate the buffer size based on the number of single buffer frames being twice the sampling rate and the single frame size being 30 bytes, to ensure that the buffer capacity is not less than twice the amount of data in the sampling period in order to avoid overflow.
[0103] Populate the above arbitration results into the SchedConfig level.
[0104] During the contract confirmation phase, the host generates a complete contract containing three levels, calculates the CRC32 checksum of all fields, and sends it to the container. The container parses the contract and verifies the CRC32. If they match, it returns an ACK response containing the virtual address mapping result of the container process, and the contract takes effect. If they do not match, it returns a NACK, triggering renegotiation.
[0105] S2.3 Contract storage and synchronization.
[0106] The host-side storage stores the contract in the / sys / class / sensors / gyro / contract node. This node is readable and writable, with permissions set to 600, allowing the HAL layer and kernel interrupt module to read it in real time.
[0107] Container-side storage stores the contract in the file / data / misc / sensors / gyro_contract.bin within the container, while maintaining a contract cache in the SensorService memory to avoid disk I / O;
[0108] Contract change synchronization: When an application modifies request parameters, the container generates a new version of the contract, increments the version number, and sends it to the host. After the host updates its storage, it notifies the HAL layer and kernel module to load the new contract through the inotify mechanism.
[0109] S3, cross-layer resource pre-initialization and permission binding: based on the generated cross-layer collaboration contract, complete the initialization of shared memory, threads and permissions, and realize priority affinity scheduling.
[0110] S3.1, Creation and mapping of shared memory double buffer.
[0111] The OH host creates a double buffer. The sensor framework of the OH host creates a double buffer, locks memory using mlock() to prevent paging, and writes the contract SchedConfig.shm_buf_a_phy and shm_buf_b_phy after converting the physical address. Memory virtual and physical address mapping: the host container virtualization layer maps physical addresses to the container process virtual address space. Cache consistency configuration: memory is set to non-cached attribute to ensure that data is directly synchronized to physical memory after being written.
[0112] S3.2 Priority kinship scheduling.
[0113] Priority mapping rules are defined, and a priority mapping table between the OH host and the Android container is established, using a real-time alignment strategy. The specific mapping relationship is shown in the table below.
[0114] Table 1 Priority Mapping Table between OH Host and Android Container
[0115] Host-side thread priority configuration:
[0116] Host gyroscope interrupt thread irq_thread configuration: Initialize thread attributes through pthread_attr_init(&attr), set the scheduling policy through pthread_attr_setschedpolicy(&attr, SCHED_FIFO), and set param.sched_priority=99 through pthread_attr_setschedparam(&attr, ¶m);
[0117] Host data writing thread (write_thread) configuration: Consistent with interrupt thread configuration, ensuring that data writing and interrupt handling have the same priority;
[0118] CPU affinity binding: The CPU set is initialized by cpu_set_t cpuset, CPU_SET(contract.sched.cpu_core_id, &cpuset) binds the thread to the core specified by the contract, and pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset) applies the configuration.
[0119] Container-side thread priority mapping implementation:
[0120] The container thread is created by calling `pthread_create(&thread, &attr, gyro_receive_thread, NULL)` to create a receiving thread. The thread identifier is "gyro_receive_thread" as agreed in the contract. The thread ID of `gyro_receive_thread` is set by calling `prctl(PR_SET_NAME, xxx)`.
[0121] Priority mapping request: The container initiates a priority mapping request to the host through the virtualization interface HostSchedSetPriority(container_pid, thread_id, contract.sched.container_thread_prio) extended by the implementation instance;
[0122] Host kernel layer mapping processing: After receiving the request, the container scheduling module of the host kernel calls the function to add the thread to the real-time scheduling cgroup and set the host-side priority using sched_setscheduler(thread_id, SCHED_FIFO, ¶m), thus realizing a direct mapping from the container thread priority to the host kernel priority.
[0123] Dispatch conflict arbitration mechanism:
[0124] Conflict detection involves reading thread scheduling information bound to the core via / proc / sched_debug. If multiple threads with a SCHED_FIFO priority of 99 exist, it is determined to be a scheduling conflict.
[0125] For conflict arbitration, a sensor thread priority strategy is adopted. The priority of other threads is temporarily reduced to 98 by sched_setparam(other_thread_id, &low_param), and restored after the gyroscope subscription is terminated. If there is a conflict between the native sensor thread and the container sensor thread, the higher sampling rate is prioritized for arbitration. For example, if the container has a 1000Hz sampling rate and the native has a 500Hz sampling rate, the container has priority.
[0126] S3.3. Permissions and interrupt channels are bound together. Shared memory permissions are set using `chmod(" / dev / shm / gyro_shm", 0600)`, and read / write permissions are granted only to the container process using `setfacl(-m, "u:container_uid:rw", " / dev / shm / gyro_shm")` to lock permissions. The host kernel calls `irq_create_mapping(NULL,contract.hardware.irq_vector)` to create interrupt mappings, `irq_set_chip_data(irq, container_irq_data)` to bind container interrupt data, and `irq_set_handler_data(irq, &penetrate_handler)` to set the interrupt penetration handler function, thus binding the interrupt channel to the container to create an interrupt penetration channel.
[0127] S4. Gyroscope hardware sampling configuration and interrupt context association: Based on contract parameters and resource configuration, the sampling parameters of the gyroscope hardware are configured, and the deep association between the interrupt context and the container thread is realized, providing a hardware foundation for subsequent interrupt penetration and data sampling.
[0128] The OH host HAL layer hardware configuration is initialized. The HAL layer opens the contract node using fopen(" / sys / class / sensors / gyro / contract", "r"), reads and parses the contract data using the protobuf decoder, and stores it in the global variable g_gyro_contract, ensuring that parameters can be accessed in real time during the configuration process. Hardware configuration handle acquisition: The gyroscope device handle is obtained through the HDF interface HdfDeviceOpen("hdf_sensor_gyro"), and subsequent configuration calls the driver interface through this handle.
[0129] For precise sampling rate configuration, the gyroscope hardware uses a system clock frequency division method to control the sampling rate. The system clock frequency f_sys is fixed at 8MHz, which can be confirmed by reading from register 0x04. The frequency division coefficient N = f_sys / target sampling rate, i.e., N = 8,000,000 / g_gyro_contract.basic.target_sample_rate. The frequency division coefficient N is split into high 16 bits and low 16 bits. The low 16 bits are written to the sampling rate control register at address 0x12, and the high 16 bits are written to the extended register at address 0x13. Specifically, the high 16 bits are written first using a custom HdfSensorWrite(handle, 0x13, (N>>16)&0xFFFF), and then the low 16 bits are written using HdfSensorWrite(handle, 0x12, N&0xFFFF) to ensure that the frequency division coefficient configuration is accurate. After writing, the high 16 bits are written using a custom HdfSensorRead(handle, 0x14, The `&read_sample_rate` function reads the actual sampling rate. For example, register 0x14 stores the current sampling rate. If the deviation from the target value is greater than 1Hz, the frequency division coefficient is recalculated and written. The maximum number of retries is 3.
[0130] The data format and hardware timestamp configuration are determined by writing configuration values to the data format register at address 0x15 according to the contract g_gyro_contract.basic.data_precision. For 32-bit floating-point data with a precision of 1, the values are written to the register at address 0x03, where bit0=1 indicates angular velocity (32-bit floating-point) and bit1=1 indicates temperature compensation (16-bit integer). For 16-bit integer data with a precision of 0, the values are written to the register at address 0x01. After configuration, the consistency of the configuration values is verified using HdfSensorRead(handle,0x15, &read_format).
[0131] Hardware timestamp configuration: Write 0x01 to timestamp clock source register 0x17 to select the ARM architecture CNTPCT counter as the timestamp clock source. The CNTPCT counter has an accuracy of 1ns and is synchronized with the system clock.
[0132] To enable and configure the timestamp precision, write 0x07 to the timestamp control register at address 0x18. Here, bit0=1 indicates enable, bit1=1 indicates microsecond-level output, and bit2=1 indicates automatic latching when sampling is complete.
[0133] The timestamp register address is bound by writing g_gyro_contract.hardware.ts_reg_addr (e.g., 0x20) from the contract to the timestamp address mapping register at address 0x19, ensuring that the timestamp value is written to the specified register address after hardware sampling is completed.
[0134] The interrupt context is associated with the container thread, the interrupt vector table is modified, the host kernel replaces the original interrupt handler function, and the interrupt vector number is bound to the custom interrupt penetration handler function.
[0135] The interrupt context data structure is initialized by defining a container interrupt context structure, as shown below:
[0136] typedef struct {
[0137] pid_t container_pid; / / Container PID
[0138] pthread_t container_thread; / / Container receiving thread ID
[0139] cpu_set_t bind_cpu; / / Bind to CPU core
[0140] bool irq_active; / / Interrupt activation state
[0141] } ContainerIrqCtx;
[0142] The structure is initialized using kzalloc(sizeof(ContainerIrqCtx), GFP_KERNEL), which fills the structure with the container PID, thread ID, and bound CPU core from the contract.
[0143] Interrupt context and thread association: The kernel task structure of the container process is obtained through task_pid_nr_ns(find_task_by_pid_nr(container_pid), &init_pid_ns), and the interrupt context structure pointer is stored in the real_cred->security field of the task structure to realize the association between the interrupt context and the container thread.
[0144] Configure the interrupt triggering method. Based on the gyroscope hardware characteristics such as edge triggering, set the interrupt triggering method to rising edge triggering through the custom irq_set_trigger_type(contract.hardware.irq_vector, IRQF_TRIGGER_RISING) to avoid repeated triggering.
[0145] Read all configuration registers, such as 0x12 to 0x19, and compare them with the contract configuration parameters to ensure that the configuration values are consistent; read the status register 0x01, bit 0 being 1 indicates that the hardware initialization is complete and can receive sampling triggers; if it is 0, retry after a 10μs delay, up to 5 retries, and report the hardware configuration failure log if it fails.
[0146] S5, gyroscope hardware interrupt triggering and native data acquisition, based on a defined hardware configuration, uses angular motion to trigger interrupts and sampling, realizing gyroscope MEMS sampling, electrical signal conversion, data register reading and frame sequence number precoding, providing high real-time raw data for subsequent data writing.
[0147] S5.1, Gyroscope MEMS structure sampling.
[0148] The gyroscope MEMS structure includes a vibrating mass made of silicon. When there is angular motion in the external environment, the mass will displace perpendicular to the vibration direction under the action of force. The displacement of the mass will cause the distance between the capacitor plates to change. The capacitance change is converted into an analog voltage signal by the built-in capacitor-to-voltage converter in the hardware, with a voltage range of ±2.5V. The analog voltage signal is converted into a digital signal by a 16-bit successive approximation ADC, with the sampling rate consistent with the configured target sampling rate. The converted digital signal is first stored in the internal FIFO buffer in the hardware with a depth of 16 frames to avoid sampling overflow. At the same time, the hardware sets bit 1 of the FIFO status register at address 0x02 to 1, indicating that there is data in the FIFO.
[0149] The interrupt trigger condition is set to one frame of data in the FIFO by HdfSensorWrite(handle, 0x09, 0x01), which triggers an interrupt once for each frame of data sampled, thus avoiding delay caused by FIFO accumulation. When one frame of data is stored in the FIFO buffer, the hardware interrupt generation module immediately generates a rising edge interrupt signal and sends it to the OH kernel interrupt controller through the interrupt pin. The duration of the interrupt signal is one system clock cycle.
[0150] The HAL layer data acquisition thread is synchronized with the interrupt. After the host gyroscope interrupt thread irq_thread is awakened by the interrupt signal, it wakes up the data acquisition thread write_thread through wake_up_process(write_thread_pid). Since it is bound to the same CPU core and has the highest priority, the thread wake-up delay is small. The acquisition thread acquires the spinlock through spin_lock_irqsave(&gyro_spinlock, flags) to disable local interrupts and prevent the acquisition process from being interrupted by other threads. The time spent on critical section operations is controlled within the set time.
[0151] The raw data register is read according to the following fixed timing sequence, with data_reg_addr=0x28 as agreed in the contract, to ensure data integrity during reading:
[0152] T0 (0ns): Low chip select CS=0, gyroscope chip selected.
[0153] T1 (50ns): CS setup time is met; send X-axis low byte read command 0x80+0x28.
[0154] T2 (450ns): Read the lower 8 bits of the X-axis data.
[0155] T3 (850ns): Send X-axis high byte read command 0x80+0x29 to read the high 8 bits of the X-axis.
[0156] T4 (1250ns): Send Y-axis low byte read command 0x80+0x2A to read the lower 8 bits of the Y-axis.
[0157] T5 (1650ns): Send Y-axis high byte read command 0x80+0x2B to read the high 8 bits of the Y-axis.
[0158] T6 (2050ns): Send Z-axis low byte read command 0x80+0x2C to read the lower 8 bits of the Z-axis.
[0159] T7 (2450ns): Send Z-axis high byte read command 0x80+0x2D to read the high 8 bits of the Z-axis.
[0160] T8 (2850ns): Send temperature low byte read command 0x80+0x2E to read the low 8 bits of the temperature.
[0161] T9 (3250ns): Send temperature high byte read command 0x80+0x2F to read the high 8 bits of the temperature.
[0162] T10 (3650ns): Wait 50ns for CS margin
[0163] T11 (3700ns): Increase chip select CS=1, complete reading of a full frame of three-axis angular velocity and temperature.
[0164] The above timing sequence is implemented using GPIO simulation built into the HAL layer.
[0165] Read the hardware timestamp. At time T11, after the data reading is completed, immediately read the timestamp register from 0x20 to 0x27 using HdfSensorRead(handle, g_gyro_contract.hardware.ts_reg_addr, &ts_raw). The value of this register is the CNTPCT counter value latched by the hardware at the moment the ADC conversion is completed. Convert the ns-level timestamp to the microsecond level, such as ts_us=ts_raw / 1000. If ts_raw%1000 ≥ 500, round up to ensure that the timestamp accuracy is within 1μs.
[0166] The frame sequence number precoding and data frame assembly employ a dual encoding mechanism of global increment and in-buffer offset. The global frame sequence number starts from 0 and increments by 1 for each sampled frame. The in-buffer offset number is the position of the current frame in the current write buffer, i.e., from 0 to shm_frame_count-1. The global variable g_global_frame_seq is maintained in the HAL layer and is automatically incremented before each data frame assembly. At the same time, buf_offset_seq = g_global_frame_seq % g_gyro_contract.sched.shm_frame_count is calculated. Then, the data frames are assembled byte by byte according to the contractual format. The specific field offsets and value calculations are shown in the table below.
[0167] Table 2. Offset and Values of Contractual Fields
[0168] The assembled data frame is 30 bytes long, consistent with the frame_size agreed upon in the contract.
[0169] The system performs the following checks: Data integrity verification: Angular velocity values are checked to ensure they are within ±2000° / s, and temperature compensation values are within -400 to 850° (corresponding to -40℃ to 85℃). If these values are outside the range, the status flag is set to 0x04. Timestamp validity verification: The system calculates the difference Δts between the current timestamp and the previous frame's timestamp. If Δts < (1000000 / g_gyro_contract.basic.target_sample_rate)*0.5 or Δts > (1000000 / g_gyro_contract.basic.target_sample_rate)*2, the timestamp is flagged as abnormal, and the status flag is set to 0x08. After verification, the spinlock is released using `spin_unlock_irqrestore(&gyro_spinlock, flags)`.
[0170] S6, Interrupt Context Penetration and Container Thread Wake-up, enables direct penetration of interrupt signals from hardware to container threads, avoiding redundant processing by the host and ensuring microsecond-level response for thread wake-up.
[0171] S6.1 Interrupt Penetration Handling Function Entry Definition: The host kernel's interrupt penetration handling function penetrate_irq_handler(int irq, void *dev_id) executes according to the following process, running entirely in the interrupt context:
[0172] The interruption is determined by irq_to_desc(irq)->irq_data.irq== g_gyro_contract.hardware.irq_vector. If it is invalid, IRQ_NONE is returned directly.
[0173] The container process is obtained by finding_task_by_pid_nr(g_container_irq_ctx.container_pid). If the process status is TASK_DEAD, IRQ_HANDLED is returned and interrupts are disabled.
[0174] The HdfSensorWrite(handle, 0x0A, 0x01) function writes 0x01 to the gyroscope interrupt confirmation register (0x0A) to clear the hardware interrupt flag and prevents any redundant operations such as data distribution and event reporting.
[0175] S6.2. Construct an interrupt signal container penetration channel, inject container interrupt signals, obtain the task pointer of the container receiving thread through the kernel's task_struct structure, and call send_sig_info(SIGRTMIN+1, SEND_SIG_PRIV, task) to send the real-time signal SIGRTMIN+1 to the container thread. This signal is a custom signal for gyroscope interrupts. The signal is sent by direct injection, skipping the signal queue and directly waking up the thread. Through sigemptyset(&mask); sigaddset(&mask, SIGRTMIN+1); pthread_sigmask(SIG_BLOCK, &mask, NULL), the default handling logic of the real-time signal is disabled, and it is only used for thread waking up. The signal handling function is not executed, reducing signal handling overhead.
[0176] S6.3 Optimization of container thread wake-up scheduling: After signal injection, the kernel scheduler executes `wake_up_process(task)` to wake up the container thread. Since the thread has been bound to the CPU core through priority affinity scheduling and configured with SCHED_FIFO99 priority, the scheduler directly sets the thread to TASK_RUNNING state and places it at the head of the run queue of the corresponding CPU core. The scheduling attribute of the thread is set to SCHED_RESET_ON_FORK by `sched_setattr(task, &attr, 0)` to ensure that the thread has no scheduling privilege downgrade after being woken up. At the same time, CPU frequency scaling is disabled by `echo performance > / sys / devices / system / cpu / cpuX / cpufreq / scaling_governor` to avoid wake-up delay caused by CPU downclocking.
[0177] In the container thread, the signal reception timestamp and thread wake-up timestamp are obtained and recorded using clock_gettime(CLOCK_MONOTONIC_RAW, &ts_recv). The wake-up delay is calculated as delay = ts_wake.tv_nsec - ts_recv.tv_nsec.
[0178] S6.4 Interrupt penetration integrity verification: The host maintains the interrupt sending counter g_host_irq_count, and the container thread increments the interrupt receiving counter g_container_irq_count after wake-up. It is synchronized periodically through the virtualization interface, once every 100 frames. If the difference is greater than 1, it is marked as an interrupt loss. After reading from the timestamp register, the difference between the hardware interrupt generation timestamp and the container thread wake-up timestamp is calculated to ensure that the difference is not greater than 500ns. If it exceeds, the CPU affinity configuration is adjusted, such as replacing the core with one with a lower load.
[0179] S7. During the data transmission process from the host HAL layer to shared memory, zero-copy writing and lock-free rotation mechanism are achieved through double-buffered rotation and frame sequence number precoding, which avoids read-write conflicts and ensures high real-time performance of data transmission.
[0180] S7.1, Double-buffered state management mechanism.
[0181] A separate status control block is set for each buffer A and Buffer B. This status control block is located 16 bytes before the start address of the buffer block, and its physical address does not overlap with the data area. The structure of the status control block is as follows:
[0182] typedef struct {
[0183] uint8_t buf_state; / / Buffer state: 0 indicates idle and writable, 1 indicates writing in progress, 2 indicates full and readable, 3 indicates reading in progress.
[0184] uint32_t current_write_seq; / / Global sequence number of the currently written frame
[0185] uint32_t write_frame_count; / / Number of frames written
[0186] uint32_t current_read_seq; / / Global sequence number of the currently read frame
[0187] uint32_t read_frame_count; / / Number of frames read
[0188] uint32_t crc32; / / CRC32 checksum of all data frames in the buffer
[0189] } BufCtrlBlock;
[0190] The HAL layer calculates the state control block address, such as buf_ctrl_addr = buf_phy_addr - 16, using the buffered physical address in the contract. After mapping it to a virtual address using ioremap(buf_ctrl_addr, 16), it accesses the address. State updates are performed atomically to avoid state inconsistencies.
[0191] S7.2 Double-buffered write judgment and state switching: The HAL layer maintains the current write buffer flag g_current_write_buf (0=Buffer A, 1=Buffer B), and reads the state of the two buffers through atomic operations before writing:
[0192] uint8_t buf_a_state = atomic_read(&buf_a_ctrl->buf_state);
[0193] uint8_t buf_b_state = atomic_read(&buf_b_ctrl->buf_state);
[0194] If the current write buffer is full, switch to another buffer that is free; if the current buffer is free or in the process of being written to, continue using the current buffer.
[0195] After selecting a buffer, the buffer state is updated from idle to being written using atomic_cmpxchg(&buf_ctrl->buf_state, 0, 1). If the update fails because the state has already been modified, a new buffer is selected.
[0196] S7.3, hardware-level implementation of zero-copy data writing.
[0197] Calculate the write address by using the buffer offset sequence number buf_offset_seq pre-encoded from the frame sequence number to calculate the physical address of the data frame in the buffer:
[0198] data_frame_addr = buf_phy_addr + buf_offset_seq * g_gyro_contract.sched.frame_size
[0199] Configuring Direct Memory Access (DMA): The HAL layer configures the DMA channel through the HDF interface, establishing a DMA mapping between the gyroscope hardware data buffer and the shared memory buffer block.
[0200] Configure the DMA source address and the physical address of the gyroscope hardware FIFO buffer, which ranges from 0x40000000 to 0x400000FF.
[0201] Configure the DMA destination address, where data_frame_addr is the address of the shared memory data frame;
[0202] Configure the DMA transfer length to 30 bytes, which is the size of a single frame;
[0203] Configure DMA transfer trigger. After the data frame is assembled, start DMA transfer through HdfDmaStart(dma_channel) to realize the direct transfer of data from the hardware buffer to the shared memory without CPU participation.
[0204] DMA transfer completion interrupt handling: After the DMA transfer is completed, a DMA interrupt is triggered. The HAL layer waits for the transfer to complete through the custom interface HdfDmaWaitCompletion(dma_channel, 10), with a timeout of 10μs. After the transfer is completed, the DMA interrupt flag is cleared.
[0205] S7.4, Double-buffered rotation triggering and state synchronization are implemented.
[0206] The condition for determining a full frame is: when the buffer's write_frame_count == g_gyro_contract.sched.shm_frame_count, meaning the number of frames written has reached the maximum number of frames in a single buffer, or when the current frame sequence number satisfies the condition that the buffer offset sequence number is shm_frame_count-1, which is the last frame, the buffer is determined to be full.
[0207] Once the HAL layer is full, it performs the following atomic operations to update the state:
[0208] Calculate the CRC32 checksum of all data frames in the buffer and write it to buf_ctrl->crc32; update the buffer state to full using atomic_set(&buf_ctrl->buf_state, 2), and it can be read; update the number of frames written using atomic_add(write_frame_count, &buf_ctrl->write_frame_count); write the global sequence number of the currently written frame to buf_ctrl->current_write_seq.
[0209] After the state update is complete, switch the g_current_write_buf flag, such as from 0 to 1 or from 1 to 0, and execute atomic_set(&new_buf_ctrl->buf_state, 1) on the new buffer to set it to be in writing, and start writing to the new buffer.
[0210] S7.5 Frame sequence number precoding to avoid read / write conflicts.
[0211] Aligning read and write frame sequence numbers: When the container thread reads data, it first reads the current_write_seq and write_frame_count of the buffer control block and calculates the range of readable frames from current_read_seq to current_write_seq-1. The container thread uses the global frame sequence number to determine whether the data frame is the latest to avoid reading old data.
[0212] The lock-free read / write process is as follows: When the producer HAL layer writes to Buffer A, the consumer container thread reads Buffer B. The two have no address overlap and no conflict. After the producer fills Buffer A, it switches to Buffer B. At this time, the consumer is still reading Buffer A, and its status is 3, indicating that it is reading. The producer determines not to write to Buffer A based on the status to avoid conflict. After the consumer finishes reading Buffer A, it updates its status to 0, indicating that it is idle. The producer can write again later, forming a lock-free rotation from writing A to reading B to writing B to reading A.
[0213] Frame sequence number loss prevention mechanism: If the consumer's read speed is slower than the producer's write speed, when the new buffer is full, the old buffer is still being read. The producer determines whether the old buffer has been read completely by checking buf_ctrl->read_frame_count == buf_ctrl->write_frame_count. If it has not been read completely, the producer marks the status flag 0x04 to indicate data overflow and discards the latest frame, prioritizing the timeliness of the read frames.
[0214] S7.6. To ensure cache consistency, the cache is flushed after DMA transfer. Since the shared memory is configured as non-cached, but the CPU may have cache remnants, the HAL layer executes the ARM architecture's cache flush instructions after the DMA transfer is complete.
[0215] `__asm__ __volatile__ ("dsb st" : : : "memory");` is a data synchronization barrier that ensures storage operations complete.
[0216] `__asm__ __volatile__ ("isb" : : : "memory");` is an instruction synchronization barrier that ensures subsequent instructions read the latest data.
[0217] Cache invalidation before container read: Before a container thread reads shared memory, a cache invalidation instruction is executed to avoid reading old data in the cache.
[0218] `__asm__ __volatile__ ("dc ivac, %0" : : "r" (data_frame_addr) : "memory");` invalidates the data cache line.
[0219] S7.7 Verify the reliability of the written data. Obtain the actual DMA transfer length using HdfDmaGetTransferCount(dma_channel, &transfer_len). If transfer_len ≠ 30 bytes, retry the DMA transfer, up to a maximum of 3 times, to verify the correctness of the DMA transfer.
[0220] Before reading from the buffer, the container thread calculates the CRC32 checksum of all data frames in the buffer and compares it with buf_ctrl->crc32. If they match, reading begins; otherwise, the buffer data is marked as corrupted and the thread switches to another buffer, thus implementing the CRC32 checksum of the buffer.
[0221] S8, the process of acquiring data on the container side, including real-time data reading and multi-dimensional verification.
[0222] Buffer read judgment: The gyro_receive_thread thread, which is awakened by the interrupt, first reads the status control blocks of the two buffers through atomic operations to identify the buffer that is full.
[0223] Zero-copy data reading: The thread directly accesses the current frame data in the shared memory buffer that is already full through the mapped virtual address. Here, the data is read in the order of the frame number, which is consistent with the writing order of the HAL layer. No data copying is required throughout the process. The data enters the user space of the container thread directly from the physical address of the shared memory, realizing zero-copy transfer from shared memory to the container thread.
[0224] To ensure data reliability, the thread performs three checks on the read data frame. The check logic is designed based on the temporal continuity and integrity characteristics of gyroscope data.
[0225] Calculate the CRC32 check value of the first 29 bytes of the data frame and compare it with the check bit at the end of the frame. If they match, it means that the data has not been tampered with or damaged, and the integrity check is completed.
[0226] Extract the global frame sequence number of the current data frame and compare it with the sequence number of the previous frame. If the sequence numbers are consecutive, the data passes. If there is a jump, such as the current sequence number being 100 and the previous sequence number being 98, then search for the missing sequence number, such as 99, in the buffer according to the offset sequence number in the buffer. If found, insert it into the current data stream. If not found, mark it as data loss. This informs the application to avoid timing out-of-order issues and completes the timing verification.
[0227] Check if the hardware timestamp value is within a reasonable range, such as the difference between it and the container system time not exceeding 10ms. If it exceeds the range, it is determined to be an invalid frame and the data is discarded.
[0228] After a thread has read all the written frames in a certain buffer, it updates the status bit of the buffer to 0x00 through an atomic operation to indicate that it is free, allowing the HAL layer to write again, thus completing the round-robin reuse of the double buffer.
[0229] S9. Data is pushed from the container SensorService to the application, ensuring that the data maintains its native format and real-time performance.
[0230] Data format restoration: The data push module of the container SensorService receives the verified data frame transmitted by the gyro_receive_thread thread. Without modifying any fields, including the original hardware timestamp and 3-axis angular velocity values, it only extracts the core data required by the application, such as timestamp, 3-axis angular velocity, and temperature compensation value, and restores it to the native Android SensorEvent object. The timestamp field of this object is directly assigned the hardware timestamp, values[0]~values[2] are assigned the X, Y, and Z axis angular velocity values respectively, and values[3] is assigned the temperature compensation value, which is completely consistent with the SensorEvent format of the native Android environment.
[0231] SensorService uses Android's native sensor callback mechanism, SensorEventListener.onSensorChanged(), to directly push SensorEvent objects to the Android application's listening thread without adding any extra buffering, delay, or format conversion logic. Since the priority of the application's listening thread is coordinated with the container thread and the host interrupt thread through a cross-layer contract, it ensures that the callback function is executed within 0.2ms after the data is received.
[0232] In addition, the application can obtain the original hardware timestamp through the SensorEvent.timestamp field, compare it with the system time when the application callback is executed, which is obtained and converted to microseconds through System.nanoTime(), and calculate the actual delay: actual_delay = callback_time - sensor_event.timestamp. If the delay exceeds the threshold, such as greater than 3ms, a delay warning is sent to the OH host through SensorService, triggering S10 dynamic adaptation adjustment.
[0233] S10. To adapt to changes in application requirements or system resource status, dynamic adjustment of cross-layer parameters is achieved to ensure that the transmission link always adapts to real-time requirements.
[0234] If an Android application re-registers via SensorManager.unregisterListener(), modifies the sampling rate or latency threshold, the container SensorService generates a new subscription request contract, increments the version number, and renegotiates the cross-layer collaboration contract with the OH host.
[0235] The OH host dynamically adjusts the number of frames in the double buffer based on the sampling rate of the new contract. There is no need to destroy and rebuild the shared memory. The frame count parameter of the state control block is modified only by atomic_set(&buf_ctrl->shm_frame_count, new_frame_count) to ensure that the buffer capacity matches the throughput.
[0236] The OH gyroscope HAL layer writes new configuration instructions to the hardware register through the HDF interface according to the sampling rate and data format parameters of the new contract. After the hardware completes the sampling of the current frame, it immediately starts sampling according to the new parameters without switching delay.
[0237] If the adjusted sampling rate of the container application conflicts more severely with the native OH application, the OH host sensor framework will initiate time-sharing multiplexing scheduling. For example, according to the set sampling period, it will be implemented through hardware FIFO partitioning: the early sampling data is written to the container's shared memory, and the later sampling data is written to the native application's buffer, ensuring that the needs of both are met and that the latency of the container application is not affected.
[0238] S11. When the application stops acquiring gyroscope data, release cross-layer resources to avoid resource leaks and restore the system to its default state.
[0239] Application initiates subscription termination request: Android application stops gyroscope data subscription through SensorManager.unregisterListener() method. After receiving the request, container SensorService sends subscription termination contract to OH host sensor framework, including container PID, shared memory identifier, interrupt penetration channel identifier, and contract version number;
[0240] Container-side resource reclamation: The container SensorService terminates the gyro_receive_thread thread by pthread_cancel(thread), removes the virtual address mapping of shared memory by munmap(shm_virt_addr, buf_size*2), deletes the contract file / data / misc / sensors / gyro_contract.bin, and releases the container process address space;
[0241] After receiving the subscription termination contract, the OH host sensor framework performs the following operations:
[0242] Stop hardware sampling by sending a stop sampling command to the gyroscope hardware through the HAL layer, such as writing 0x00 to the control register 0x00, disabling hardware interrupts and data conversion functions, and restoring the hardware default configuration.
[0243] Release shared memory by unmapping the shared memory using munmap(shm_virt_addr, buf_size*2), deleting the shared memory object using shm_unlink(" / dev / shm / gyro_shm"), and reclaiming physical memory resources;
[0244] To disable interrupt penetration, remove the interrupt penetration handler function using `irq_set_handler(contract.hardware.irq_vector, NULL)`, destroy the interrupt mapping using `irq_dispose_mapping(contract.hardware.irq_vector)`, and remove the association between the hardware interrupt vector number and the container thread.
[0245] Restore the host state, delete the / sys / class / sensors / gyro / contract contract node. If the gyroscope usage of the native OH application was previously paused or downgraded to adapt to the container application, restore the sampling configuration and priority of the native application through SensorManager.resumeListener(), unbind the CPU core through cpu_set_t, and restore the CPU frequency scaling strategy to ondemand.
[0246] Cross-layer state synchronization: The OH host sensor framework sends a resource reclamation completion signal to the container SensorService. The container SensorService records the reclamation log, which includes the list of reclaimed resources and the time taken, thus completing the end of the entire process.
[0247] In summary, the above are merely preferred embodiments of the present invention and are not intended to limit the scope of protection of the present invention. Any modifications, equivalent substitutions, improvements, etc., made within the spirit and principles of the present invention should be included within the scope of protection of the present invention.
Claims
1. A low-latency sensing method for cross-system gyroscope data based on interruption context penetration, characterized in that, Specifically, the steps include: The container application initiates a gyroscope data subscription request, including the target sampling rate, data accuracy requirements, latency threshold and hardware timestamp enable flag, and encapsulates it into a subscription request contract after adding the container process ID, container application process priority and data receiving thread preset flag and sending it to the host. The host resolves the basic parameters, obtains the hardware capability parameters, arbitrates to determine the optimal sampling rate, CPU cores, and shared memory capacity, allocates double the shared memory capacity as a double buffer, configures state control blocks for each buffer block, maps them to the container's virtual address space, and forms scheduling coordination parameters based on the host data writing thread priority, container data receiving thread mapping priority, CPU core identifier to be bound, double buffer physical address, number of single buffer frames, and single frame data size; a coordination contract is formed by the basic parameters, hardware capability parameters, and scheduling coordination parameters and sent to the container. The host creates gyroscope interrupt threads and data write threads with the same scheduling policy and priority, and both are bound to the CPU core to be bound; the container creates a data receiving thread according to the cooperation contract and configures it with the same scheduling policy as the data writing thread; the host configures the gyroscope according to the cooperation contract, binds the interrupt vector number and interrupt penetration handling function, and initializes the container interrupt context associated with the container process and the data receiving thread. After the gyroscope buffers angular motion data, it generates an interrupt signal. The host executes the interrupt penetration handling function to clear the interrupt flag and wakes up the container data receiving thread. At the same time, the interrupt signal triggers the host interrupt thread to wake up the gyroscope acquisition thread, read the angular motion data and timestamp, and encapsulate the gyroscope data frame. The host filters free buffer blocks, establishes a DMA mapping between them and the gyroscope cache, and writes gyroscope data frames into the buffer blocks. After the data receiving thread is awakened, it reads the full buffer block, constructs a container sensor event object, and pushes it to the container application.
2. The low-latency sensing method for cross-system gyroscope data according to claim 1, characterized in that, The host configures the gyroscope according to the cooperative contract as follows: Calculate the gyroscope's frequency division coefficient based on the system clock frequency and the optimal sampling rate determined by the cooperative contract; write the high 16 bits and low 16 bits of the frequency division coefficient sequentially into the gyroscope's extended register and sampling rate control register; determine the corresponding hardware configuration parameters according to the data precision requirements in the cooperative contract; configure the gyroscope's data format register; select the system's high-precision hardware counter as the timing reference; enable microsecond-level hardware timestamps and configure an automatic latching mechanism upon sampling completion; and simultaneously send the timestamp storage register address recorded in the cooperative contract to the gyroscope.
3. The low-latency sensing method for cross-system gyroscope data according to claim 1, characterized in that, Simultaneously, the interrupt signal triggers the host interrupt thread to wake up the gyroscope acquisition thread, reads the angular motion data and timestamp, and encapsulates the gyroscope data frame. Specifically, the acquisition thread maintains a globally incrementing first frame sequence number, increments the first frame sequence number for each generated frame, and calculates the pre-encoded buffer offset sequence number of the first frame sequence number by taking the modulo of the number of single buffer frames agreed upon in the cooperative contract. Then, it reads the buffered angular motion data according to a fixed timing sequence, synchronously reads the hardware high-precision latched timestamp, and encapsulates it into a gyroscope data frame containing a hardware timestamp, angular motion data, a double-layer frame sequence number, a status identifier, and a check bit. The double-layer frame sequence number includes the first frame sequence number and the buffer offset sequence number.
4. The low-latency sensing method for cross-system gyroscope data according to claim 1, characterized in that, The host selects free buffer blocks in the following way: the host reads the state of the state control block corresponding to each buffer block in the double buffer through atomic operations, selects the buffer blocks with the free state, and uses atomic comparison and swap operations to update the state of the selected buffer block from free to write. If the atomic update fails, the host re-traverses and selects the buffer blocks.
5. The low-latency sensing method for cross-system gyroscope data according to claim 3, characterized in that, The method for writing gyroscope data frames into the buffer block is as follows: calculate the physical address of the gyroscope data frame in the buffer block based on the offset sequence number carried by the gyroscope data frame in the buffer; establish a DMA mapping between the gyroscope hardware data buffer and the selected buffer block; configure the DMA source address, destination address, and single frame transmission length; start DMA transmission to write the gyroscope data frame into the buffer block; trigger a DMA interrupt after the DMA transmission is completed; and the HAL layer waits for the transmission to complete and clears the DMA interrupt flag. When the number of frames written to the buffer block is equal to the maximum number of frames in a single buffer, the buffer block is determined to be full. The CRC32 checksum of all data frames in the buffer block is calculated and written to the corresponding status control block. The status is updated to full and the number of frames written is updated.
6. The low-latency sensing method for cross-system gyroscope data according to claim 1, characterized in that, After the data receiving thread is awakened, it reads the full buffer block and constructs the container sensor event object to push to the container application in the following way: The data receiving thread reads the double-buffered state control block through atomic operations, filters the buffer blocks that are full, calculates the range of frames that can be read based on the sequence number of the written frames and the number of written frames in the buffer block, reads the frame data of the frame range into the user space corresponding to the data receiving thread, completes the integrity verification, timing verification and timestamp validity verification of the frame data, and sets the state of the buffer block to idle. The container extracts hardware timestamps and triaxial angular velocities to construct container sensor event objects, which are then pushed to the container application using the container's native sensor callback interface.
7. The low-latency sensing method for cross-system gyroscope data according to claim 1, characterized in that, The host verifies whether the target sampling rate in the subscription request contract is within the supported range of the gyroscope. If it exceeds the supported range, the target sampling rate is modified to the maximum sampling rate of the gyroscope, and a correction log is recorded.
8. The low-latency sensing method for cross-system gyroscope data according to claim 1, characterized in that, The arbitration determines the optimal sampling rate, CPU cores, and shared memory capacity as follows: If the target sampling rate is not greater than the maximum sampling rate, the optimal sampling rate is the target sampling rate; otherwise, the maximum sampling rate is used and a sampling rate degradation is marked in the log. Query the system CPU load and select CPU cores with loads less than the threshold as cores to be bound, prioritizing CPU cores with the same interrupt thread as the gyroscope. Calculate the memory buffer size according to the method that the number of single buffer frames is a set multiple of the sampling rate and the size of a single frame is a set value, and determine the optimal shared memory capacity.
9. The low-latency sensing method for cross-system gyroscope data according to claim 1, characterized in that, The host monitors the thread scheduling status within the bound CPU cores in real time. When multiple highest-priority real-time threads are detected running concurrently, scheduling conflict handling is triggered: according to the strategy of prioritizing gyroscope-related threads, the scheduling priority of unrelated threads is temporarily reduced, and the original priority is restored after the gyroscope subscription is terminated; if the conflicting parties are the host's native gyroscope-related threads and the container's gyroscope-related threads, the high sampling rate priority strategy is followed, and the scheduling priority of the thread with the lower sampling frequency is reduced.
10. The low-latency sensing method for cross-system gyroscope data according to claim 1, characterized in that, After the data receiving thread is awakened, the wake-up delay is calculated based on the signal receiving timestamp and the thread wake-up timestamp. If the wake-up delay is greater than the threshold, the CPU core with a lower load is switched.