Files
M5Stack_Linux_Libs/doc/component_doc/DeviceDriver.md
T
2024-05-27 12:19:09 +08:00

12 KiB
Raw Blame History

DeviceDriver

Device driver for Linux platform, including various small sensors and actuators, along with application-level programs.

.
├── SConstruct
├── include
├── Kconfig
├── party
│   ├── framebuffer
│   │   ├── fbtools.c
│   │   └── fbtools.h
│   ├── linux_i2c
│   │   ├── linuxi2c.c
│   │   └── linuxi2c.h
│   ├── linux_spi
│   │   ├── linux_spi.c
│   │   └── linux_spi.h
│   ├── linux_uart
│   │   ├── linux_uart.c
│   │   └── linux_uart.h
│   └── ptmx
│       ├── ptmx_creat.c
│       └── ptmx_creat.h

linux_uart

A non-standard C library for Linux, used to read and write to serial devices under the /dev directory. It facilitates serial communication on Linux.

The library is located in components/DeviceDriver/party/linux_uart.

Activate the component.

Use the command make menuconfig to enable 'Enable DeviceDriver -> compile uart lib' and compile the UART library.

Permanently enable.

Add the following to the config_defaults.mk file in the project:

CONFIG_DEVICE_DRIVER_ENABLED=y
CONFIG_DEVICE_UART_ENABLED=y

Usage example: examples/linux_uart

API

typedef struct{
	int baud;              // UART baud rate.
	int data_bits;         // UART data bits.
	int stop_bits;         // UART stop bits.
	char parity;           // parity.
}uart_t;

/**
 * @brief init uart
 * @note 
 * @param [in] dev    device name
 * @param [in] param  struct uart_t pointer
 * @retval [return] [>0] fd index
 * @retval [return] [<=0] fail code
 */
int linux_uart_init(char* dev, void* param);

/**
 * @brief close uart
 * @note 
 * @param [in] fd    fd index
 * @retval 
 */
void linux_uart_deinit(int fd);

/**
 * @brief Read data from UART.
 * @note 
 * @param [in] fd    fd index
 * @param [in] cnt    buff size
 * @param [in] buf    buff pointer
 * @retval [return] [>0] The size of the read data.
 * @retval [return] [<0] Read failure code.
 */
int linux_uart_read(int fd, int cnt, void* buf);

/**
 * @brief Send data from UART.
 * @note 
 * @param [in] fd    fd index
 * @param [in] cnt    buff size
 * @param [in] buf    buff pointer
 * @retval [return] [>0] The size of the sent data.
 * @retval [return] [<0] Send failure code.
 */
int linux_uart_write(int fd, int cnt, void* buf);

linux_i2c

A non-standard C library for Linux, used to read and write to i2c devices under the /dev directory. It facilitates i2c communication on Linux.

The library is located in components/DeviceDriver/party/linux_i2c.

Activate the component.

Use the command make menuconfig to enable 'Enable DeviceDriver -> compile i2c lib' and compile the i2c library.

Permanently enable.

Add the following to the config_defaults.mk file in the project:

CONFIG_DEVICE_DRIVER_ENABLED=y
CONFIG_DEVICE_I2C_ENABLED=y

Usage example: examples/linux_i2c

API

/* I2c device */
typedef struct i2c_device {
    int bus;			        /* I2C Bus fd, return from i2c_open */
    unsigned short addr;		/* I2C device(slave) address */
    unsigned char tenbit;		/* I2C is 10 bit device address */
    unsigned char delay;		/* I2C internal operation delay, unit millisecond */
    unsigned short flags;		/* I2C i2c_ioctl_read/write flags */
    unsigned int page_bytes;    /* I2C max number of bytes per page, 1K/2K 8, 4K/8K/16K 16, 32K/64K 32 etc */
    unsigned int iaddr_bytes;   /* I2C device internal(word) address bytes, such as: 24C04 1 byte, 24C64 2 bytes */
} LINUXI2CDevice;

/* Close i2c bus */
void linuxi2c_close(int bus);

/*
**	@brief		:	Open i2c bus
**	#bus_name	:	i2c bus name such as: /dev/i2c-1
**	@return		:	failed return -1, success return i2c bus fd
*/
int linuxi2c_open(const char *bus_name);

/*
**	@brief		:	Initialize LINUXI2CDevice with defualt value
**	#device	    :	LINUXI2CDevice struct
*/
void linuxi2c_init_device(LINUXI2CDevice *device);

/*
**	@brief		:	Get LINUXI2CDevice struct desc
**	#device	    :	LINUXI2CDevice struct
**  #buf        :   Description message buffer
**  #size       :   #buf size
**	@return		:	return i2c device desc
*/
char *linuxi2c_get_device_desc(const LINUXI2CDevice *device, char *buf, size_t size);

/* Select i2c device on i2c bus */
int linuxi2c_select(int bus, unsigned long dev_addr, unsigned long tenbit);

/* I2C internal(word) address convert */
void linuxi2c_iaddr_convert(unsigned int int_addr, unsigned int iaddr_bytes, unsigned char *addr);

/*  I2C file I/O read, write
**	@brief	:	read #len bytes data from #device #iaddr to #buf
**	#device	:	LINUXI2CDevice struct, must call i2c_device_init first
**	#iaddr	:	i2c_device internal address will read data from this address, no address set zero
**	#buf	:	i2c data will read to here
**	#len	:	how many data to read, lenght must less than or equal to buf size
**	@return : 	success return read data length, failed -1
*/
ssize_t linuxi2c_read(const LINUXI2CDevice *device, unsigned int iaddr, void *buf, size_t len);
ssize_t linuxi2c_write(const LINUXI2CDevice *device, unsigned int iaddr, const void *buf, size_t len);

/* I2c ioctl read, write can set i2c flags
**	i2c_ioctl_read/write
**	I2C bus top layer interface to operation different i2c devide
**	This function will call XXX:ioctl system call and will be related
**	i2c-dev.c i2cdev_ioctl to operation i2c device.
**	1. it can choice ignore or not ignore i2c bus ack signal (flags set I2C_M_IGNORE_NAK)
**	2. it can choice ignore or not ignore i2c internal address
**
*/
ssize_t linuxi2c_ioctl_read(const LINUXI2CDevice *device, unsigned int iaddr, void *buf, size_t len);
ssize_t linuxi2c_ioctl_write(const LINUXI2CDevice *device, unsigned int iaddr, const void *buf, size_t len);

/*
**	i2c_primitive_read/write
**	I2C bus top layer interface to operation different i2c devide
**	This function will call XXX:primitive system call and will be related
**	i2c-dev.c i2cdev_ioctl to operation i2c device.
**	1. it can choice ignore or not ignore i2c bus ack signal (flags set I2C_M_IGNORE_NAK)
**	2. it can choice ignore or not ignore i2c internal address
**
*/
ssize_t linuxi2c_primitive_read(const LINUXI2CDevice *device, void *offset, size_t offset_len, void *buf, size_t buf_len);
ssize_t linuxi2c_primitive_write(const LINUXI2CDevice *device, void *offset, size_t offset_len, void *buf, size_t buf_len);

linux_spi

A non-standard C library for Linux, used to read and write to spi devices under the /dev directory. It facilitates spi communication on Linux.

The library is located in components/DeviceDriver/party/linux_spi.

Activate the component.

Use the command make menuconfig to enable 'Enable DeviceDriver -> compile spi lib' and compile the i2c library.

Permanently enable.

Add the following to the config_defaults.mk file in the project:

CONFIG_DEVICE_DRIVER_ENABLED=y
CONFIG_DEVICE_SPI_ENABLED=y

Usage example: examples/linux_spi

API:

// open and init SPIdev
// * spi_mode may have next mask: SPI_LOOP | SPI_CPHA | SPI_CPOL |
//   SPI_LSB_FIRST | SPI_CS_HIGH SPI_3WIRE | SPI_NO_CS | SPI_READY
//   or 0 by zefault
int spi_init(spi_t *self,
             const char *device, // filename like "/dev/spidev0.0"
             int mode,           // SPI_* (look "linux/spi/spidev.h")
             int bits,           // bits per word (usually 8)
             int speed);         // max speed [Hz]
//----------------------------------------------------------------------------
// sets mode on existing spi
int spi_set_mode(spi_t* self, int mode);
//----------------------------------------------------------------------------
// sets speed on existing spi
int spi_set_speed(spi_t* self, int speed);
//----------------------------------------------------------------------------
// close SPIdev file and free memory
void spi_free(spi_t *self);
//----------------------------------------------------------------------------
// read data from SPIdev
int spi_read(spi_t *self, void* rx_buf, int len);
//----------------------------------------------------------------------------
// write data to SPIdev
int spi_write(spi_t *self, const void* tx_buf, int len);
//----------------------------------------------------------------------------
// read and write `len` bytes from/to SPIdev
int spi_exchange(spi_t *self, void* rx_buf, const void* tx_buf, int len);
//----------------------------------------------------------------------------
// read data from SPIdev from specific register address
int spi_read_reg8(spi_t *self, uint8_t reg_addr, void* rx_buf, int len);
//----------------------------------------------------------------------------
// write data to SPIdev to specific register address
int spi_write_reg8(spi_t *self, uint8_t reg_addr, const void* tx_buf, int len);

framebuffer

A non-standard C library for Linux, used to read and write to framebuffer devices under the /dev directory. It facilitates framebuffer communication on Linux.

The library is located in components/DeviceDriver/party/framebuffer.

Activate the component.

Use the command make menuconfig to enable 'Enable DeviceDriver -> compile framebuffer lib' and compile the i2c library.

Permanently enable.

Add the following to the config_defaults.mk file in the project:

CONFIG_DEVICE_DRIVER_ENABLED=y
CONFIG_DEVICE_FRAMEBUFFER_ENABLED=y

Usage example: examples/linux_framebuffer

API:

/* a framebuffer device structure */
typedef struct fbdev{
int fb;
unsigned long fb_mem_offset;
unsigned long fb_mem;
struct fb_fix_screeninfo fb_fix;
struct fb_var_screeninfo fb_var;
char dev[20];
} FBDEV, *PFBDEV;

/* open & init a frame buffer */
/* to use this function,
you must set FBDEV.dev="/dev/fb0"
or "/dev/fbX" */
/* it's your frame buffer. */
int fb_open(PFBDEV pFbdev);

/*close a frame buffer*/
int fb_close(PFBDEV pFbdev);

/*get display depth*/
int get_display_depth(PFBDEV pFbdev);

/*draw rgb888 or rgb565 to framebuffer.color=24/16*/
void fb_draw_img(PFBDEV pFbdev, int w, int h, int color, void *buf);
void fb_put_pixel(PFBDEV pFbdev, int x, int y, unsigned int color);

/*full screen clear */
void fb_memset(void *addr, int c, size_t len);

ptmx

A non-standard C library for Linux, used to read and write to pts devices under the /dev directory. Standard input/output for linux virtual terminals to operate other processes. Useful in daemons.

The library is located in components/DeviceDriver/party/ptmx.

Activate the component.

Use the command make menuconfig to enable 'Enable DeviceDriver -> compile ptmx lib' and compile the i2c library.

Permanently enable.

Add the following to the config_defaults.mk file in the project:

CONFIG_DEVICE_DRIVER_ENABLED=y
CONFIG_DEVICE_PTMX_ENABLED=y

Usage example: examples/ptxm_tcp_tran

API

typedef enum {
	PTMX_STOP = 0,
	PTMX_RUN = 1
} ptmx_status_t;

/*msg call back */
typedef void (*msg_call_back_t)(const char*, int);
/* a ptmx device structure */
struct ptmx_creat_t 
{
	int master_ptmx;
	char slave_ptmx_name[50];
	int ptmx_status;			
	pthread_t ptmx_loop_handler_d;
	msg_call_back_t call;
	int buff_size;
};
/*creat a ptmx struct ptmx_creat_t */
struct ptmx_creat_t* ptmx_creat();
/*destroy ptmx struct ptmx_creat_t */
int ptmx_destroy(struct ptmx_creat_t **p);
/*open one ptmx*/
int ptmx_open(struct ptmx_creat_t *self);

/*set msg callback fun*/
void ptmx_set_msg_callback(struct ptmx_creat_t *self, msg_call_back_t fun);
void *ptmx_loop_handler(void *par);
/*exit one ptmx*/
void ptmx_exit(struct ptmx_creat_t *self);
#ifdef __cplusplus
class ptmx
{
private:
	struct ptmx_creat_t ptm;
public:
	ptmx();
    /*open ptmx*/
	int open();
    /*set ptmx read buff*/
	void set_buff_size(int size);
    /*set msg callback fun*/
	void set_msg_call_back(msg_call_back_t msg);
	std::string get_slave_ptmx_name();
	void exit();
	~ptmx();
};
#endif