Zephyr Device Driver and Device Model Computer Science

  • Slides: 11
Download presentation
Zephyr Device Driver and Device Model Computer Science & Engineering Department Arizona State University

Zephyr Device Driver and Device Model Computer Science & Engineering Department Arizona State University Tempe, AZ 85287 Dr. Yann-Hang Lee yhlee@asu. edu (480) 727 -7507

Device Model q To support initializing all the drivers configured into the system v

Device Model q To support initializing all the drivers configured into the system v The driver fills in the pointer to the structure containing the function pointers to its API functions during driver initialization. v These structures are placed into the RAM section in initialization level order. q To provide a generic type API for each type of driver (UART, SPI, I 2 C) v can be used by fibers and tasks q API calls may be blocked for synchronous IO operations v must use proper mechanisms for blocking according to execution context, e. g. , a nanokernel semaphore cannot be used when the context is a task. v Synchronous calls API typedef struct { type /** Nanokernel semaphore for fiber context */ struct nano_sem f_sem; device_sync_call_t #ifdef CONFIG_MICROKERNEL /* use microkernel semaphore */ inline functions struct _k_sem_struct _t_sem; ksem_t t_sem; device_sync_call_init() enum device_sync_waiter; device_sync_call_init() bool device_ready; #endif device_sync_call_init() } device_sync_call_t; CSE 530 EOSI Fall 2016 1

Driver APIs q The runtime device struct per driver instance struct device { struct

Driver APIs q The runtime device struct per driver instance struct device { struct device_config *config; void *driver_api; void *driver_data; }; struct device_config { char *name; int (*init)(struct device *device); void *config_info; }; q DEVICE_INIT() v create device object and set it up for boot time initialization. q DEVICE_AND_API_INIT() v Create device object and set it up for boot time initialization. This also takes a pointer to driver API struct for link time pointer assignment. q DEVICE_NAME_GET() v Expands to the full name of a global device object. q DEVICE_GET() v Obtain a pointer to a device object by name. q DEVICE_DECLARE() v Declare a device object. CSE 530 EOSI Fall 2016 2

Device Initialization – DEVICE_INIT() #define DEVICE_AND_API_INIT(dev_name, drv_name, init_fn, data, cfg_info, level, prio, api)

Device Initialization – DEVICE_INIT() #define DEVICE_AND_API_INIT(dev_name, drv_name, init_fn, data, cfg_info, level, prio, api) static struct device_config __config_##dev_name __used __attribute__((__section__(". devconfig. init"))) = { . name = drv_name, . init = (init_fn), . config_info = (cfg_info) }; static struct device (__device_##dev_name) __used __attribute__((__section__(". init_" #level STRINGIFY(prio)))) = { . config = &(__config_##dev_name), . driver_api = api, . driver_data = data } q defines a device object that is automatically configured by the kernel during system initialization v two static struct __config##dev_name and __device_##dev_name v place them in “. devconfig. init” and “init_ #level STRINGFFY(prio)” sections q invoke_sys_device_do_config_level() to call device->init() CSE 530 EOSI Fall 2016 3

Driver Example: i 2 c_dw DEVICE_AND_API_INIT(i 2 c_0, CONFIG_I 2 C_DW_0_NAME, &i 2 c_dw_initialize,

Driver Example: i 2 c_dw DEVICE_AND_API_INIT(i 2 c_0, CONFIG_I 2 C_DW_0_NAME, &i 2 c_dw_initialize, &i 2 c_0_runtime, &i 2 c_config_dw_0, SECONDARY, CONFIG_I 2 C_INIT_PRIORITY); q initialization func – i 2 c_dw_initialize() q driver API functions q config_data and driver_data struct i 2 c_dw_dev_config { device_sync_call_t sync; union dev_config app_config; uint 8_t *xfr_buf; uint 32_t xfr_len; uint 32_t rx_pending; uint 16_t hcnt; uint 16_t lcnt; volatile uint 8_t state; /* last dir. of transfer */ uint 8_t request_bytes; uint 8_t xfr_flags; bool support_hs_mode; }; CSE 530 EOSI Fall 2016 static struct i 2 c_driver_api funcs = {. configure = i 2 c_dw_runtime_configure, . transfer = i 2 c_dw_transfer, . suspend = i 2 c_dw_suspend, . resume = i 2 c_dw_resume, }; struct i 2 c_dw_rom_config { uint 32_t base_address; uint 32_t irq_num; uint 32_t interrupt_mask; #ifdef CONFIG_PCI struct pci_dev_info pci_dev; #endif /* CONFIG_PCI */ i 2 c_isr_cb_t config_func; #ifdef CONFIG_I 2 C_DW_SHARED_IRQ char *shared_irq_dev_name; #endif /* CONFIG_I 2 C_DW_SHARED_IRQ */ }; 4

Bit-Transfer on I 2 C Bus q One clock pulse is generated for each

Bit-Transfer on I 2 C Bus q One clock pulse is generated for each data bit that is transferred q Data Validity v The data on the SDA line must be stable during the HIGH(1) period of the clock. The data line(SDA) can change data only when the clock signal (SCL) is LOW(0) q Wired-and function v open-drain or opencollector CSE 530 EOSI Fall 2016 5

Data Transfer With 7 -Bit Device Address q After START condition (S), a slave

Data Transfer With 7 -Bit Device Address q After START condition (S), a slave address(7 -bit) is sent. q A read/write (R/W’) direction is then sent(8 th bit) q Data transfer occurs, and then always terminated by STOP condition. However, repeated START conditions can occur. CSE 530 EOSI Fall 2016 6

Master-Transmitter to Slave-Receiver Data Transfer q In this, the transmission direction never changes. The

Master-Transmitter to Slave-Receiver Data Transfer q In this, the transmission direction never changes. The set-up and transfer is straight-forward CSE 530 EOSI Fall 2016 7

Master-Receiver and Slave-Transmitter Data Transfer q Master initiates the data transfer by generating the

Master-Receiver and Slave-Transmitter Data Transfer q Master initiates the data transfer by generating the START condition followed by the start byte (with read/write bit set to 1 i. e. read mode) q After the first ack from the slave, the direction of data changes and the master becomes receiver and slave transmitter. q The STOP condition is still generated by the master (master sends not-ACK before generating the STOP) CSE 530 EOSI Fall 2016 8

Example I 2 C Device – 24 FC 256 EEPROM q 32 K bytes

Example I 2 C Device – 24 FC 256 EEPROM q 32 K bytes in 512 pages of 64 bytes q I 2 C interface with A 2, A 1, A 0 address pins q Page write operation: q Random read operation: CSE 530 EOSI Fall 2016 9

Use of I 2 C Driver in Galileo Board q CONFIG_I 2 C_0=y in

Use of I 2 C Driver in Galileo Board q CONFIG_I 2 C_0=y in /zephyr/boards/galileo_defconfig q I 2 C interface wrapper in /zephyr/include/i 2 c. h static int i 2 c_transfer(struct device *dev, struct i 2 c_msg *msgs, uint 8_t num_msgs, uint 16_t addr) q Need to find the “struct device” q Search the device objects by configuration name v With DEVICE_INIT macro, the objects are placed in memory by the linker. struct device *device_get_binding(char *name) { struct device *info; for (info = __device_init_start; info != __device_init_end; info++) { if (!strcmp(name, info->config->name)) { return info; } } return NULL; } CSE 530 EOSI Fall 2016 10