日本熟妇hd丰满老熟妇,中文字幕一区二区三区在线不卡 ,亚洲成片在线观看,免费女同在线一区二区

TTY設備驅動程序開發指南

更正文檔

1. 前言

本文介紹如何編寫符合AliOS Things標準的teletype設備(一般用于實現UART或虛擬終端)驅動程序。

2. 頭文件

在程序中使用本文提及的功能應包含頭文件aos/tty_core.h。

3. 數據結構

AliOS Things提供TTY設備的抽象基礎結構:

typedef struct aos_tty aos_tty_t;

采用結構體嵌套的方式從基礎結構派生出具體的硬件結構。派生類型應包含具體硬件操作所需的各種變量。例如:

typedef struct {
    aos_tty_t tty;
    /* private data */
    void *reg_base;
    int irq_num;
} tty_abc_t;

使用宏aos_container_of實現從基礎結構指針到派生結構指針的轉換。例如:

aos_tty_t *tty_dev = foo();
tty_abc_t *tty_abc = aos_container_of(tty_dev, tty_abc_t, tty);

4. 注冊及注銷

4.1. 注冊

AliOS Things提供如下函數用于注冊TTY設備:

aos_status_t aos_tty_register(aos_tty_t *tty);

調用注冊函數之前,BSP開發者應自行分配一個aos_tty_t類型或其派生類型的變量并對包含的如下變量賦值:

  • dev.iduint32_t類型,表示該設備的ID。不同TTY設備不能擁有相同的ID。

  • opsconst aos_tty_ops_t *類型,指向一組面向硬件的回調函數:

typedef struct {
    void (*unregister)(aos_tty_t *tty);
    aos_status_t (*startup)(aos_tty_t *tty);
    void (*shutdown)(aos_tty_t *tty);
    aos_status_t (*set_attr)(aos_tty_t *tty);
    void (*enable_rx)(aos_tty_t *tty);
    void (*disable_rx)(aos_tty_t *tty);
    void (*start_tx)(aos_tty_t *tty);
    void (*stop_tx)(aos_tty_t *tty);
} aos_tty_ops_t;

  • flagsuint32_t類型,可包含如下字段,各字段使用按位或運算連接:

  • AOS_TTY_F_UNIQUE_REF:表示該設備只能同時被引用一次。

調用注冊函數之前,BSP開發者應初始化派生類型中的私有變量,并執行具體硬件相關的注冊時初始化工作(例如映射寄存器地址等)。

4.2. 注銷

AliOS Things提供如下函數用于注銷TTY設備:

aos_status_t aos_tty_unregister(uint32_t id);

調用此函數之后,BSP開發者可回收相關聯的aos_tty_t類型或其派生類型的變量。

5. 回調函數

驅動程序應實現aos_tty_ops_t定義的一組面向硬件的回調函數。

5.1. unregister

void (*unregister)(aos_tty_t *tty);

unregister回調函數在設備注銷時被調用,可在該函數中執行具體硬件相關的注銷時反初始化工作(例如解除寄存器地址映射等)。

5.2. startup

aos_status_t (*startup)(aos_tty_t *tty);

startup回調函數在設備引用計數從0增加到1時被調用,可在該函數中執行具體硬件相關的運行時初始化工作。初始化成功時應返回0;失敗時應返回errno(負值)。該函數不應使能硬件發送和接收功能。

startup回調函數可讀取tty->termios.c_cflag變量獲取設備初始屬性并修改硬件狀態;也可修改該變量使其反映硬件的實際狀態。該變量是tcflag_t類型,可包含如下字段,各字段使用按位或運算連接:

  • 波特率,掩碼為CBAUD,取值必須為以下當中的一個:

  • B50

  • B75

  • B110

  • B134

  • B150

  • B200

  • B300

  • B600

  • B1200

  • B1800

  • B2400

  • B4800

  • B9600

  • B19200

  • B38400

  • B57600

  • B115200

  • B230400

  • B460800

  • B500000

  • B576000

  • B921600

  • B1000000

  • B1152000

  • B1500000

  • B2000000

  • B2500000

  • B3000000

  • B3500000

  • B4000000

  • 字節長度,掩碼為CSIZE,取值只能為以下當中的一個:

  • CS5

  • CS6

  • CS7

  • CS8

  • CSTOPB:該標志有效時表示停止位為2位,否則為1位。

  • PARENB:表示使能校驗位。

  • PARODDPARENB有效時,若PARODD有效則校驗方式為奇校驗,否則為偶校驗。

5.3. shutdown

void (*shutdown)(aos_tty_t *tty);

shutdown回調函數在設備引用計數從1減小到0時被調用,可在該函數中執行具體硬件相關的運行時反初始化工作。該函數被調用時,硬件發送和接收功能已被禁用。

5.4. set_attr

aos_status_t (*set_attr)(aos_tty_t *tty);

set_attr回調函數在修改設備屬性時被調用,驅動程序應在該函數中根據新屬性(存放在tty->termios.c_cflag變量中)修改硬件狀態。修改成功后返回0;失敗時應返回errno(負值),且驅動程序應將硬件狀態恢復到此函數被調用之前的狀態。該函數被調用時,硬件發送和接收功能已被禁用。

5.5. enable_rx

void (*enable_rx)(aos_tty_t *tty);

enable_rx回調函數在使能接收功能時被調用,驅動程序應在該函數中使能硬件的接收功能。該函數無需等待有數據被接收到再返回,而是應該使能接收中斷(本設備級別而非中斷控制器級別)并立即返回,在硬件中斷處理程序中處理后續接收工作。

size_t aos_tty_rx_buffer_produce(aos_tty_t *tty, const void *buf, size_t count);

在中斷處理程序中使用aos_tty_rx_buffer_produce將硬件接收到的數據送入設備軟件核心層。參數count為硬件接收到的字節數目。驅動程序應在調用該函數之前從FIFO或DMA獲取數據并存放到buf指向的空間。返回值為實際送入設備軟件核心層的字節數目,在設備軟件接收緩沖區已滿的情況下返回值會小于count。aos_tty_rx_buffer_produce應在關閉本地CPU中斷且tty->lock加鎖的環境下調用。例如:

void rx_irq_handler(tty_abc_t *tty_abc)
{
    aos_tty_t *tty = &tty_abc->tty;
    uint8_t fifo_data[RX_FIFO_SIZE];
    size_t rx_count;
    aos_irqsave_t flags;

    flags = aos_spin_lock_irqsave(&tty->lock);
    if (!is_rx_irq_en(tty_abc->reg_base) || !is_rx_ready(tty_abc->reg_base)) {
        aos_spin_unlock_irqrestore(&tty->lock, flags);
        return;
    }
    rx_count = get_rx_fifo_data(tty_abc->reg_base, fifo_data);
    (void)aos_tty_rx_buffer_produce(tty, fifo_data, rx_count);
    aos_spin_unlock_irqrestore(&tty->lock, flags);
}

5.6. disable_rx

void (*disable_rx)(aos_tty_t *tty);

enable_rx回調函數在禁用接收功能時被調用,驅動程序應在該函數中禁用硬件的接收功能。此時FIFO中已接收的數據或DMA正在接收的數據可直接丟棄。

5.7. start_tx

void (*start_tx)(aos_tty_t *tty);

start_tx回調函數在設備軟件發送緩沖區由空變為非空時被調用,驅動程序應在該函數中將待發送數據送入FIFO或DMA。該函數無需等待數據全部被硬件發出再返回,而是應該使能發送中斷(本設備級別而非中斷控制器級別)并立即返回,在硬件中斷處理程序中處理后續發送工作。注意start_tx回調函數在關閉本地CPU中斷且tty->lock加鎖的環境下被調用,請不要在該函數中進行任務調度或執行長耗時的工作。

size_t aos_tty_tx_buffer_consume(aos_tty_t *tty, void *buf, size_t count);

start_tx回調函數或中斷處理程序中使用aos_tty_tx_buffer_consume從設備軟件核心層獲取待發送數據。參數count為硬件發送最大字節數,例如FIFO深度或DMA最大長度。待發送數據將被復制到buf指向的空間,驅動程序應將這些數據交給FIFO或DMA。返回值為實際從設備軟件核心層獲取的字節數目;返回0時說明設備軟件發送緩沖區為空,驅動程序應禁用發送中斷(本設備級別而非中斷控制器級別)。aos_tty_tx_buffer_consume應在關閉本地CPU中斷且tty->lock加鎖的環境下調用。例如:

void tx_irq_handler(tty_abc_t *tty_abc)
{
    aos_tty_t *tty = &tty_abc->tty;
    uint8_t fifo_data[TX_FIFO_SIZE];
    size_t tx_count;
    aos_irqsave_t flags;

    flags = aos_spin_lock_irqsave(&tty->lock);
    if (!is_tx_irq_en(tty_abc->reg_base) || !is_tx_empty(tty_abc->reg_base)) {
        aos_spin_unlock_irqrestore(&tty->lock, flags);
        return;
    }
    tx_count = aos_tty_tx_buffer_consume(tty, fifo_data, TX_FIFO_SIZE);
    if (tx_count > 0)
        set_tx_fifo_data(tty_abc->reg_base, fifo_data, tx_count);
    else
        disable_tx_irq(tty_abc->reg_base);
    aos_spin_unlock_irqrestore(&tty->lock, flags);
}

5.8. stop_tx

void (*stop_tx)(aos_tty_t *tty);

disable_tx回調函數在中止發送時被調用,驅動程序應在該函數中中止硬件的發送流程。若此時FIFO中有待發送的數據或DMA正在發送數據,應先等待這些數據發送完成。