Porting

2022-09-14
No Rating

When porting the payload device control program developed based on PSDK to different versions of software and hardware platforms, it is necessary to initialize the Hal and Osal layers first and register key configuration information. By loading the static library, referencing the specified resource file, and declaring Structure, set the configuration information required for cross-platform migration of the payload device control program. Finally, use the specified interface to register the Platform module in the payload device control program, obtain hardware resources and operating system resources, and realize the cross-platform payload device control program. transplant.

Sample code
  • Linux

    • Hal layer adaptation: sample/platform/linux/manifold2/hal
    • Osal layer adaptation: sample/platform/linux/common/osal/
  • FreeRTOS

    • Hal layer adaptation: sample/platform/rtos_freertos/psdk_development_board_1.0/hal
    • Osal layer adaptation: sample/platform/rtos_freertos/common/osal/

Description: The API interface of the PSDK Platform module is in the psdk_lib/api_headers/psdk_platform.h file.

Overview

In order to transplant the payload device control program developed based on PSDK to different software and hardware platforms, it is necessary to adapt to different hardware platforms through Hal (Hardware Abstraction Layer), and through Osal (Operating System Abstraction Layer) to achieve compatibility with different operating systems, as shown in Figure 1. Code porting.

Figure 1. Code porting

Basic Concepts

Hal Layer

Hal (Hardware Abstraction Layer) is the PSDK hardware interface abstraction layer, which is located between the operating system, the payload device control program, and the hardware interface. Developers need to follow the function prototypes in the PsdkPlatform_RegHalUartHandler() and PsdkPlatform_RegHalNetworkHandler() interfaces to implement and register the functions that are adapted to the Hal layer to the payload device control program. The payload device control program developed based on PSDK can directly access the underlying resources of the payload device hardware through the Hal layer and control the payload device to perform corresponding actions, so that the payload device control program can adapt to different hardware platforms, such as STM32F407IGH6-EVAL or Manifold 2-C, etc.

Ethernet Port Device

To adapt the Hal layer function to the device that needs to use the network port, you need to perform the following operations:

  • Implement the function of adapting the network port of the Hal layer
    • Local network configuration: T_PsdkReturnCode (*NetWorkConfig)(const char *ipAddr, const char *netMask)
  • Use PsdkPlatform_RegHalNetworkHandler() interface to register network port operation functions

Serial Device

To adapt a device using serial communication to the Hal layer function, you need to perform the following operations:

  • Implement the UART operation function that adapts to the Hal layer
    • Serial port initialization: T_PsdkReturnCode (*UartInit)(void)
    • Send data: T_PsdkReturnCode (*UartWriteData)(const uint8_t *buf, uint16_t len)
    • Receive data: T_PsdkReturnCode (*UartReadData)(uint8_t *buf, uint16_t len, uint16_t *realLen)
  • Use PsdkPlatform_RegHalUartHandler() interface to register serial port operation function

Illustrate

  • Parameters of the serial port of the payload device
    • Baud rate: 460800 (SkyPort V2/X-Port firmware version is lower than and includes V01.01.0100) or DJI Assistant 2 software setting value (SkyPort V2/X-Port firmware version is higher than V01.01.0100)
    • Stop bit: 1
    • Data bits: 8
    • Parity check: none
  • You can set the communication baud rate between the SkyPort V2/X-Port and the PSDK payload device through the DJI Assistant 2 software (the communication parameters of the PSDK device must be consistent with the SkyPort V2/X-Port), which perfectly adapts to different hardware platforms (some hardware platform does not support the default communication parameters or has functional defects) and adapts to different application scenarios (for example, when subscribing to a large amount of data, the communication baud rate needs to be appropriately increased).

Figure 2. Setting the communication baud rate

USB Device

In M300 RTK and M30/M30T, the Service and Host mode of USB exits some differences:

  • M300 RTK: SDK device side is USB Host, the drone side is USB Device
  • M30/M30T: SDK device side is USB Device, the drone side is USB Host
M300 RTK

The USB function limitations are as follows:

USB FunctionFunction Limitation
Virtual Serial PortGimbal management, Camera management, part of the basic communication
USB BulkGet Liveview, Get perception image, MOP function, Media file management

Virtual Serial Port:

  1. Linux platform: No additional configuration, the driver supports it by default. It can be searched through ls /dev/ttyACMx, please operate as a standard serial device.
  2. RTOS platform: The library of USB Host should be transplanted to read and write, please refer to the USB_Host transplant and realization of samples/sample_c/platform/rtos_freertos/stm32f4_discovery/middlewares/ST/STM32_USB_Host_Library/.

USB-Bulk:

  1. Linux platform: If the user develops a program at Type-C expansion port, methods of installing and calling libusb can be used for development.

    The installation method: sudo apt-get install libusb-1.0-0-dev

  2. RTOS platform: don't support the related drivers of USB Bulk.

M30/M30T

The USB function limitations are as follows:

USB FunctionFunction Limitation
RNDISPush Liveview
USB BulkGet Liveview, Get perception image, MOP function, Media file management
Configure the USB of Development Platform to Device Mode
  1. Configure the USB-Device: Configure the USB pin multiplexing, and set to USB-OTG or USB-Device mode. After the configuration, USB port can be linked to the USB Host of another device. The vid and pid information can be searched to determine whether it fulfills the expectation. If we configure the vid and pid of DJI Manifold 2-G to 0x0955 and 0x7020, and link the USB to another Ubuntu, we can easily search by lsusb. 1

  2. Configure the RNDIS network card: Firstly, make sure whether the platform support and open the USB Gadget. For details, please refer to hereopen in new window. Write the RNDIS configuration. After running as administator, the USB port can be linked to the USB Host of another device. Through ifconfig to search whether the corresponding network card is enumerated, and make sure whether fulfills the expectation. ping can be used to check whether the communication is succeeded. 23

  3. 配置USB Bulk:首先确认是否平台是否支持并且打开 USB Gadget驱动,详细请参考[补链接]。编写USB bulk的配置配置并运行bulk初始化程序,以管理员身份运行后,可以将USB口接到另外一个设备的USB Host上,先使用“sudo su”切换root账户再通过cat /sys/kernel/debug/usb/devices命令查询到对应的网卡,并确认是否符合预期。对bulk设备的读写操作详情请参考hal_usb_bulk.c中的接口实现。 4

Osal Layer

Osal (Operating System Abstraction Layer) is the operating system abstraction layer of PSDK, which is located between the payload device control program and the operating system. Developers need to follow the function prototype in the PsdkPlatform_RegOsalHandler() interface to implement and register functions that are adapted to different operating systems into the payload device control program. Using the payload device control program developed by PSDK can directly access the operating system and the resources of the operating system kernel, and port the payload device control program to different operating systems.

Thread Function

To use the thread mechanism to manage the payload device control program to perform the corresponding tasks, the developer needs to implement the functions of creating threads, destroying threads, and thread sleeping.

  • Create thread: T_PsdkReturnCode (*TaskCreate)(T_PsdkTaskHandle *task, void *(*taskFunc)(void *),uint32_t stackSize,void *arg)
  • Destroy thread: T_PsdkReturnCode (*TaskDestroy)(T_PsdkTaskHandle task)
  • Thread sleep: T_PsdkReturnCode (*TaskSleepMs)(uint32_t timeMs)

Mutex

Mutex is a mechanism used to prevent multiple threads from performing read and write operations on the same queue, counter, interrupt handler, and other common resources (such as shared memory, etc.) at the same time, which can effectively avoid process deadlock or long waiting. Using the mutual exclusion lock mechanism requires developers to create, destroy, lock, and unlock a mutex.

  • Create mutex: T_PsdkReturnCode (*MutexCreate)(T_PsdkMutexHandle *mutex)
  • Destroy the mutex: T_PsdkReturnCode (*MutexDestroy)(T_PsdkMutexHandle mutex)
  • Mutex lock: T_PsdkReturnCode (*MutexLock)(T_PsdkMutexHandle mutex)
  • Mutex unlock: T_PsdkReturnCode (*MutexUnlock)(T_PsdkMutexHandle mutex)

Semaphore

A semaphore is a mechanism used to prevent multiple threads from operating on the same piece of code at the same time. When developers use this mechanism, they need to implement the functions of creating semaphore, destroying semaphore, waiting for semaphore, releasing semaphore, and waiting for timeout semaphore.

  • Create semaphore: T_PsdkReturnCode (*SemaphoreCreate)(T_PsdkSemHandle *semaphore, uint32_t initValue)

Note: When using this interface, please set the initial value of the initValue semaphore.

  • Destroy the semaphore: T_PsdkReturnCode (*SemaphoreDestroy)(T_PsdkSemHandle semaphore)
  • Wait for semaphore: T_PsdkReturnCode (*SemaphoreWait)(T_PsdkSemHandle semaphore)

Description: The max value of the waiting time for the semaphore interface is 32767 ms.

  • Wait for timeout semaphore: T_PsdkReturnCode (*SemaphoreTimedWait)(T_PsdkSemHandle semaphore, uint32_t waitTimeMs)
  • Release the semaphore: T_PsdkReturnCode (*SemaphorePost)(T_PsdkSemHandle semaphore)

Time interface

Get the current system time (ms): T_PsdkReturnCode (*GetTimeMs)(uint32_t *ms)

Memory management interface

  • Allocate memory: void *(*Malloc)(uint32_t size)
  • Free memory: void (*Free)(void *ptr)

Implement cross-platform porting

1. Cross-platform interface adaptation

Hal layer adaptation

Serial port
  • Linux

    Please configure the corresponding serial device name according to the hardware connection, such as ttyUSB0, and implement the serial port initialization, serial port read data and serial port write data callback functions. For detailed implementation methods, please refer to: /sample/platform/linux/manifold2/hal/hal_uart.c

  • RTOS

    Please configure the corresponding serial port pins according to the MCU model, and implement the serial port initialization, serial port read data and serial port write data callback functions. For detailed implementation methods, please refer to: sample/platform/rtos_freertos/stm32f4_eval/hal/hal_uart.c

Network port
  • Linux

    After connecting the third-party development platform to the DJI drone using the network port, you need to implement and register the callback function for configuring the network. When the system is initialized, the configuration of the load network parameters will be automatically completed. Function. For detailed implementation methods, please refer to: /sample/platform/linux/manifold2/hal/hal_network.c

  • RTOS

    For the RTOS system, you can obtain the network parameters that should be configured for the current load by registering the callback function for configuring network parameters and inform other subsystem modules according to actual needs to complete the functions related to the network port. For detailed implementation methods, please refer to: /sample/platform/rtos_freertos/stm32f4_eval/application/main.c

Osal layer adaptation

  • Linux

    Use the standard library pthread to encapsulate the thread functions, mutex locks, semaphores, and time interfaces in T_PsdkOsalHandler. For detailed implementation methods, please refer to: sample/platform/linux/common/osal/osal.c

  • RTOS

    Use the thread interface encapsulated by CMSIS to encapsulate the thread function, mutex, semaphore, and time interface in T_PsdkOsalHandler. For detailed implementation methods, please refer to: sample/platform/rtos_freertos/common/osal/osal.c

2. Register the cross-platform adaptation interface

Struct declaration

Please fill in the interface content in T_PsdkHalUartHandler, T_PsdkHalNetWorkHandler, and T_PsdkOsalHandler completely to ensure that the registered interfaces can be used normally.

  • T_PsdkHalUartHandler halUartHandler
T_PsdkHalUartHandler halUartHandler = {
    .UartInit = Hal_UartInit,
    .UartReadData = Hal_UartReadData,
    .UartWriteData = Hal_UartSendData,
};
  • T_PsdkHalNetWorkHandler halNetWorkHandler
T_PsdkHalNetWorkHandler halNetWorkHandler = {
        .NetWorkConfig = HalNetWork_Config,
    };
  • T_PsdkHalUartHandler osalHandler
T_PsdkOsalHandler osalHandler = {
    .Malloc = Osal_Malloc,
    .Free = Osal_Free,
    .TaskCreate = Osal_TaskCreate,
    .TaskDestroy = Osal_TaskDestroy,
    .TaskSleepMs = Osal_TaskSleepMs,
    .MutexCreate = Osal_MutexCreate,
    .MutexDestroy = Osal_MutexDestroy,
    .MutexLock = Osal_MutexLock,
    .MutexUnlock = Osal_MutexUnlock,
    .SemaphoreCreate = Osal_SemaphoreCreate,
    .SemaphoreDestroy = Osal_SemaphoreDestroy,
    .SemaphoreWait = Osal_SemaphoreWait,
    .SemaphorePost = Osal_SemaphorePost,
    .SemaphoreTimedWait = Osal_SemaphoreTimedWait,
    .GetTimeMs = Osal_GetTimeMs,
};

Please call PsdkPlatform_RegHalUartHandler(), PsdkPlatform_RegHalNetworkHandler() and PsdkPlatform_RegOsalHandler() functions in turn to register the Hal layer and the Osal layer. If the interface registration fails, please check the error according to the return code and log information.

Note: The cross-platform porting module must be registered before other PSDK function modules. If the Platform module fails to register or is not registered, the developer will not be able to use the load device developed based on PSDK.

if (PsdkPlatform_RegHalUartHandler(&halUartHandler) != PSDK_RETURN_CODE_OK) {
    printf("psdk register hal uart handler error");
    return PSDK_RETURN_CODE_ERR_UNKNOWN;
}

if (PsdkPlatform_RegHalNetworkHandler(&halNetWorkHandler) != PSDK_RETURN_CODE_OK) {
    printf("psdk register hal network handler error");
    return PSDK_RETURN_CODE_ERR_UNKNOWN;
}

if (PsdkPlatform_RegOsalHandler(&osalHandler) != PSDK_RETURN_CODE_OK) {
    printf("psdk register osal handler error");
    return PSDK_RETURN_CODE_ERR_UNKNOWN;
}