Site icon TAPIT

Porting LWIP cho vi điều khiển STM32 (P1)

LWIP – Light weight IP là một bộ thư viện mã nguồn mở được thiết kế dành cho những hệ thống có tài nguyên tương đối hạn chế, phù hợp với các hệ thống nhúng. Hỗ trợ tương đối đầy đủ các giao thức mạng trên nền TCP/IP. Có thể hỗ trợ giao tiếp với vi điều khiển thông qua Serial hoặc Ethernet. TAPIT chia sẻ đến các bạn chuỗi bài viết hướng dẫn về lý thuyết thư viện, porting các function, kết nối MQTT, kết nối HTTP trên nền tảng LWIP và tối ưu chương trình trên vi điều khiển STM32.

Tại phần 1, mình sẽ giới thiệu đến các bạn bộ thư viện LWIP, hướng dẫn cách add thư viện, cách để port các file và port các function khi sử dụng LWIP. 

Phần 1. Porting LWIP cho vi điều khiển STM32

1. Giới thiệu về LWIP

1.1 Mô hình kết nối giữa vi điều khiển và server

LWIP hỗ trợ các cách kết nối vật lí chính:

a. Sử dụng serial UART

Ở mô hình kết nối này, vi điều khiển sẽ kết nối với modem mạng qua chuẩn giao tiếp nối tiếp UART, phù hợp với nhiều dòng VDK khác nhau, tuy nhiên tốc độ kết nối phụ thuộc nhiều vào tốc độ baudrate của VDK.

b. Sử dụng Ethernet

Với mô hình kết nối này, LWIP sẽ sử dụng Ethernet để kết nối lên server, tốc độ cao hơn Serial. Tuy nhiên VDK cần phải hỗ trợ Phy Ethernet hoặc module chuyển đổi SPI-Ethernet. Bài viết sẽ tập trung vào cách porting LWIP qua chuẩn giao tiếp serial UART.

1.2 So sánh cách giao tiếp AT command và LWIP stack

Về cơ bản có 2 cách kết nối chính từ vi điều khiển lên cloud qua serial với module 4G như sau:

Phương pháp Network stack Ưu điểm Nhược điểm
AT command (cách 1)

 

· Phần xử lí các application như TCP, UDP, HTTP… đều nằm trên module 4G.

· Chip vi điều khiển chỉ nhận lấy các kết quả cuối cùng của các giao thức bằng các tập lệnh AT-Command

· Tiết kiệm tài nguyên cho vi điều khiển

· Các ứng dụng mạng phụ thuộc vào firmware của nhà sản xuất module

· Khi thay đổi module thì cần phải thay đổi tập lệnh của các ứng dụng.

· Tiêu tốn ít tài nguyên của vi điều khiển.· Độ ổn định của firmware module 4G cần test lại với mỗi module, mỗi nhà sản xuất khác nhau.

· Nhiều giao thức mạng bị hạn chế bởi module của nhà sản xuất, và phụ thuộc và tính năng firmware module của nhà sản xuất.

LWIP stack (cách 2)

 

· Phần xử lí tầng application các giao thức mạng đều nằm hết trên vi điều khiển, module 4G không xử lí các giao thức mạng.

 

· Khả năng port code giữa các nền tảng tương đối dễ dàng.· Kế thừa được nhiều framework base trên LWIP.

· Khả năng “portable, reuseable” cao· Dễ dàng chuyển đổi module 4G giữa các nhà cung cấp khác nhau.

· Tiêu tốn tài nguyên của vi điều khiển nhiều hơn so với dùng AT command và network stack của nhà sản xuất.

· Một số ứng dụng cần nhiều tài nguyên phần cứng (SSL..) thì đòi hỏi cấu hình RAM của vi điều khiển lớn.

· Không chạy được đồng thời data mode và command mode. Phải chuyển qua lại giữa data mode và command mode.

2. Porting

Trong bài viết này, mình sử dụng kit có sẵn cho thuận tiện, với tài nguyên như sau:

Mình sẽ hướng dẫn các bạn khởi một Project và cách thêm thư viện LWIP vào Project.

2.1 Khởi tạo project

2.2 Thêm thư viện LWIP vào project

2.3 Port các file cần thiết cho nền tảng STM32

a. lwipopts.h

 lwipopts.h chứa toàn bộ các cấu hình của LWIP stack.

b. sys_timer.c

Có nhiệm vụ cung cấp các timer để định thời, timeout cho internal timer của LWIP. Trong đó bắt buộc cần có 2 hàm trả về thời gian hiện tại của hệ thống là “sys_now” và “sys_jiffies” với đơn vị millisecond, các bạn có thể thay thế hàm “sys_get_tick_ms” bằng hàm “HAL_GetTick” của STM32.

c. cc.h và cpu.h

Chứa các định nghĩa về kiến trúc MCU đang sử dụng.

2.4 Porting các function cần thiết

a. sys_rand

Dùng để ramdom 1 số uint32_t, để cho đơn giản mình sẽ lấy systick value của vi điều khiển lỗi ARM

b. Các hàm liên quan đến việc log dữ liệu debug

Để phục vụ in dữ liệu qua màn hình, các bạn có thể retarget printf qua UART, tuy nhiên ở ví dụ này, mình sử dụng bộ thư việc “Segger_RTT”, ưu điểm của bộ thư viện này là chỉ cần 2 dây debug “SWD” để in dữ liệu. Các bạn có thể tìm hiểu thêm về bộ thư viện này ở đây “https://www.segger.com/products/debug-probes/j-link/technology/about-real-time-transfer/”, tuy nhiên ở bài viết này mình sẽ không đề cập chi tiết.

c. Hàm gửi dữ liệu qua cổng UART từ LWIP đến module 4G

 “ppp_output_callback” gửi data qua cổng “USART1”, với 2 tham số cơ bản là “data” và “len”, lần lượt là dữ liệu và độ dài dữ liệu LWIP muốn đẩy tới module 4G.

d. gsm_hw_pppos_polling và sio_read

e. Hàm ngắt nhận dữ liệu UART

Hàm nhận dữ lịêu ngắt uart rồi lưu vào PPP buffer, hoặc AT command buffer. Đây là 1 cách implement đơn giản của mình.

Trong đó “uint32_t sio_read(sio_fd_t fd, u8_t *data, u32_t len)” trả về số byte UART-RX mà vi điều khiển nhận về từ module 4G, cần truyền lượng data này vào lwip stack, với tham số truyền vào là buffer data và độ dài dữ liệu mong muốn của LWIP. Dữ liệu được đưa tiếp vào LWIP stack bằng hàm “pppos_input”.

Vậy là tại phần này, mình đã giới thiệu đến các bạn về LWIP và các hàm driver cần thiết cho LWIP. Các nội dung tiếp theo của chuỗi bài viết:

Phần 2: Thiết kế chương trình và porting ứng dụng cho LWIP

Phần 3: Kết nối MQTT trên nền tảng LWIP

Phần 4: Kết nối HTTP trên nền tảng LWIP

Phần 5: Tối ưu các tham số cho vi điều khiển – Optimize memory (ram, flash, speed)

Cố vấn tại Cộng đồng Kỹ thuật TAPIT

Trần Văn Huy

Tìm hiểu thêm:
Tổng hợp hướng dẫn Internet of Things với NodeMCU ESP8266 và ESP32
Tổng hợp các bài hướng dẫn Lập trình vi điều khiển STM32
[HỌC ONLINE:LẬP TRÌNH VI ĐIỀU KHIỂN STM32, VI XỬ LÝ ARM CORTEX–M]
Fanpage Cộng đồng Kỹ thuật TAPIT: TAPIT – Learning, Research and Sharing Community