Mi piacerebbe sapere qual è la differenza tra HAL (Hardware Abstraction Layer) e DAL (Data Abstraction Layer) quando parliamo di software embedded. Potrei avere le abbreviazioni sbagliate però ...
La mia comprensione è che al livello HAL si usano i registri di mcu mentre al livello DAL non si. Ho scritto un rapido esempio di come implementare personalmente un driver UART a livello HAL e DAL:
/***************************************************************************************************************************
* 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;
}
Per chiarire, ho creato tutti quei valori e i nomi dei registri.