3

I'd like to know what the difference is between hardware abstraction layer (HAL) and data abstraction layer (DAL) when speaking about embedded software. I might have the abbreviations wrong though...

My understanding is that at thr HAL level you use the mcu's registers while at the DAL level you don't. I wrote a quick example of how I personnally would implement a UART driver at HAL and DAL level:

/***************************************************************************************************************************
 * HAL
 ***************************************************************************************************************************/


#define UART_PARITY (*((volatile unsigned long *) 0x0000123))
#define T0IR        (*((volatile unsigned long *) 0x0000124))
#define U0THR       (*((volatile unsigned long *) 0x0000125))
#define UART_BDR    (*((volatile unsigned long *) 0x0000126))

typedef enum{
    UART_HAL_STATUS_SUCCESS,
    UART_HAL_STATUS_ERROR
} uart_hal_status_t;

typedef struct{

} uart_hal_t;

/* Write some values to registers. */
uart_hal_status_t UART_HAL_init(p_baudrate, p_parity, p_device)
{
    /* Calculates which exact value needs to be written to register to have desired baudrate. */
    unsigned long x = ((p_baudrate/2)*PLL*SMTH);
    UART_BDR = x;

    /* Write values to registers. */
    if (p_parity == 0)
    {
        UART_PARITY = 1<<8;
    }
    else
    {
        UART_PARITY = 0<<8;
    }

    /* Set some additional register values. */
    VICSoftIntClr = 0x20;
    T0IR =0xFF;
    VICVectAddr =0x00000000;

    return UART_HAL_STATUS_SUCCESS;
}

uart_hal_status_t UART_HAL_read_char(uart_hal_t p_uart_dev)
{
    //read registers
}

/***************************************************************************************************************************
 * DAL
 ***************************************************************************************************************************/

#include <uarth_hal.h>
#include <inttypes.h>

/**
 * Parity types.
 */
typedef enum{
    PARITY_ODD,
    PARITY_EVEN
} parity_t;

/**
 *  Return values.
 */
typedef enum{
    UART_DAL_STATUS_SUCCESS,
    UART_DAL_STATUS_ERROR
}uart_dal_status_t;

/**
 * Physical UART devices.
 */
typedef enum{
    UART_DEV_0,
    UART_DEV_1,
    UART_DEV_2
} uart_dev_t;


/**
 * Publicly accessible configuration structure.
 */
typedef struct{
    int32_t baudrate;
    parity_t parity;

    uart_dev_t device;
} UART_cfg_t;

/**
 * Wannabe opaque structure.
 */
typedef struct{
    UART_cfg_t config;

    uart_hal_t hal_device; 

    void *rx_buffer;
    uint32_t rx_buffer_nr_unread_chars;
    uint32_t rx_buffer_size;
} UART_t;

/**
 * This function initializes the UART port at the DAL level
 */
uart_dal_status_t UART_DAL_init(UART_t *p_uart_dev, UART_cfg_t *p_uart_cfg)
{
    if ((p_uart_dev == NULL) || (p_uart_cfg == NULL))
    {
        return UART_DAL_STATUS_ERROR;
    }

    UART_HAL_init(p_uart_cfg->baudrate, p_uart_cfg->parity, p_uart_cfg->device);

    p_uart_dev->config = *(p_uart_cfg);

    return UART_DAL_STATUS_SUCCESS;
}

uart_dal_status_t UART_DAL_read_data(UART_t *p_uart_dev)
{
    for (uint32_t i = 0; i < p_uart_dev->rx_buffer_nr_unread_chars; i++)
    {
        UART_HAL_read_char(p_uart_dev->hal_device);
    }

    return UART_DAL_STATUS_SUCCESS;
}

/***************************************************************************************************************************
 * main
 ***************************************************************************************************************************/

#include <uart_dal.h>

int main (int p_argc, char *p_argv[])
{
    UART_t l_uart_dev;

    UART_cfg_t l_uart_cfg = 
    {
        .baudrate = 9600,
        .parity = PARITY_ODD,
        .device = UART_DEV_0
    };

    uart_dal_status_t l_status = UART_DAL_init(&l_uart_dev, &l_uart_cfg);
    if (l_status != UART_DAL_STATUS_SUCCESS)
    {
        return -1;
    }

    while(1);

    return 0;
}

To clarify, I made all those values and register names up.

2
  • 3
    As embedded software engineer, I never encountered a "Data Abstraction Layer". I do know about "Data Access Layers", which are used to communicate with a database. That is also what is usually meant with the term DAL. Jun 28, 2018 at 17:58
  • 1
    Could DAL = Device Abstraction Layer? Some manufacturers use the term "board support package" for something that could be the same/related: a set of definitions and functions that abstract away the board-specific features (such as pinning, external components, bus connections, etc.). Otoh HAL abstracts away the MCU-specific settings (but not in a truly agnostic way, e.g. just for a specific manufacturer's MCU family)
    – user44761
    Jun 29, 2018 at 11:25

1 Answer 1

1
  • HAL = Hardware Abstraction Layer: Use a peripheral (UART, SPI, Timer, ...) with the same API on different platforms.
  • DBAL = Database Abstraction Layer: Use Data Storage with the same API with different implementation (SQL, ...).
  • DAL = Data Access Layer: Piece of software to ease the access of the raw database (SQL requests).

As database in embedded systems are simpler than computer software, DBAL and DAL are often squeezed.

To spice it up with a complex example: Lets say you have an external flash memory with SPI interface in which you want to store data:

  • The DBAL would implement a simple database mapping: for example key/value, with a key associated to a physical address and call the DAL with the correct Address.
  • The DAL would use the HAL to perform simple write/read memory operations on the Flash memory, via SPI.

Scenario: Scenario

Check for more details on DBAL/DAL: https://stackoverflow.com/questions/2838661/what-is-the-difference-between-database-abstraction-layer-data-access-layer

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.