Linux를 사용하면서 File descriptor를 보면서 공부를 했었다.
이와 같은 형태로 UART, SPI 등등 간단하게 설계를 해두면 통신 사양 등에 변경을 해야될 때 매우 편할 것 같다는 생각이 들었다.
예를 들어서 센서 값을 RS485로 뿜어주는 MCU가 있다고 해보자.

대충 이런식으로 소스 작업이 되어 있을 것이다(예제용으로 대충 짠 것이라 컴파일 안된다.)
// rs485.c
void rs485_send(uint32_t to_send, uint32_t len) {
HAL_UART_TRANSMIT(to_send, len);
}
// sensor_gather.c
sensor_t sensors[] = { sensor_1, sensor_2};
void gather_sensor(void) {
// 485로 보낸다.
uint32_t to_send[2] = {sensor_read(sensors[0]), sensor_read(sensors[2])}
rs485_send(to_send);
}
// sensor.c
typedef struct {
I2C_INST* i2c;
uint32_t sensor_value;
} sensor_t;
uint32_t sensor_read(sensor_t* self) {
self->sensor_value = I2C_Read(self->i2c, 1);
return self->sensor_value;
}
근데 만약에 485가 아니라 CAN이나 LoRa 붙어서 만들어야되면,
sensor_gather.c에 있는 내용을 바꿔야만 할 것이다.
이제 이런거를 interface를 설계해서 만들면 그거에 대해서 걱정을 할 필요가 없다.
아마 이런식으로 될 것이다.
// interface_device.h
typedef enum {
UART2,
RS485_2,
CAN_1,
} INTF_DEVICE;
// sensor_gather.c
sensor_t sensors[] = { sensor_1, sensor_2};
uint32_t write_device_id = RS485_2;
void gather_sensor(void) {
// 485로 보낸다.
uint32_t to_send[2] = {sensor_read(sensors[0]), sensor_read(sensors[2])}
write(write_device_id, to_send, 8); // write/read 같은 함수로 여러 장치 access
}
gather_sensor를 바꾸는게 아니라 write_device_id 값을 바꾸는 식으로 말이다.
(예를 들기 위해서 글로벌 변수에다 하드코딩 해두었지만, struct 안에다 만들어 두고 변경하게 할 수 있겠다.)
지금은 uint32_t write_device_id = RS485_2;
로, 485로 되어있지만 CAN을 통해서 보내야 한다고 하면 uint32_t write_device_id = CAN_1;
이런식으로 간단하게 바뀔 수가 있을 것으로 보인다.

물론 프로토콜 이런거 달라지면 그에 관한 작업은 해야겠지만, 중요한 것은 sensor_gather.c가 변하지 않는다,
소스도 더 깔끔해질 것 같고..(의존성 Down)
예전부터 펌웨어에서 더 깔끔한 구조가 무엇일까 고민을 했는데 앞으로 이런식으로 작업을 해봐야 할 것 같다.
앞으로 작업할 내용은 다음 포스팅에서 적어볼 생각이다.
'개발 > MCU' 카테고리의 다른 글
| CAN 통신 serialize(?) - uart 처럼 쓰기 (0) | 2022.06.05 |
|---|