Trong vài năm qua, vi điều khiển đã trở thành một phần thiết yếu trong cuộc sống hàng ngày của chúng ta. Bạn có thể không nhận thấy, nhưng nó đang thực hiện một số nhiệm vụ tối giản để cải thiện cuộc sống hàng ngày của chúng ta. Từ chip 8-bit đơn giản điều khiển bóng đèn thông minh cho đến bộ xử lý tín hiệu kỹ thuật số 32-bit (DSP) trong TV và hộp giải mã tín hiệu số, giúp chúng ta có thêm phương tiện giải trí và phương tiện kỹ thuật số. Nếu không có vi điều khiển, cuộc sống của chúng ta không chỉ kém phần giải trí mà còn mất đi khả năng kiểm soát. Với nhu cầu ngày càng tăng làm tăng sự phát triển của các sản phẩm dựa trên vi điều khiển, hàng tỷ đơn vị vi điều khiển đã được bán mỗi năm.
Bây giờ câu hỏi đặt ra là, điều gì sẽ xảy ra khi hàng tỷ sản phẩm dựa trên vi điều khiển được sản xuất và bán, và việc nâng cấp firmware trở thành ưu tiên hàng đầu? Mỗi thiết bị đã bán có cần phải trả lại nhà sản xuất mỗi khi có nhu cầu nâng cấp firmware không? Câu trả lời rõ ràng cho câu hỏi này là không! Và đây là một trong những lý do quan trọng nhất tại sao một hệ thống dựa trên vi điều khiển có bootloader trên bo mạch.
Bootloader là gì
Bootloader là một ứng dụng có mục tiêu chính là nâng cấp hoặc sửa đổi phần mềm hệ thống mà không cần sự can thiệp của các công cụ nâng cấp chương trình cơ sở chuyên dụng. Bootloader có thể có nhiều chức năng, nhưng nó chủ yếu được sử dụng để quản lý ứng dụng. Nó cũng có thể sử dụng các giao thức khác nhau như UART, CAN, I2C, I2S, Ethernet hoặc USB để thiết lập giao tiếp và bắt đầu nâng cấp firmware. Một ví dụ điển hình là bootloader trong bo Arduino, được cấu hình để flash phần mềm ứng dụng trong bộ nhớ flash của chip ATMega.
Tìm hiểu hệ thống bootloader
Bootloader có nhiều kích cỡ và có thể được phân biệt theo loại tác vụ mà nó thực thi. Mã phân nhánh khi khởi động quyết định thực thi mã bootloader hay mã ứng dụng bằng cách kiểm tra một chân GPIO khi khởi động. Trong một hệ thống phức tạp hơn, bootloader tự tải vào bộ nhớ cùng với mã ứng dụng, sau đó nó kiểm tra các tham số ban đầu và tính toàn vẹn của hệ thống. Sau khi hoàn tất, nó sẽ quay trở lại quá trình thực thi mã ứng dụng. Đây là lý do tại sao nhiều bootloader chứa mã phân nhánh.
Ngay cả khi ứng dụng đang chạy, nó được thiết kế đến mức có thể yêu cầu nâng cấp firmware, sau đó nó sẽ thực hiện các thao tác dọn dẹp hệ thống cần thiết. Nó sẽ reset chip bằng cách đặt các giá trị đã biết vào thanh ghi watchdog. Ngoài ra, ứng dụng đưa ra tất cả các hướng dẫn cần thiết cho mã phân nhánh để đưa thiết bị vào chế độ bootloader.
Khi bootloader tải vào bộ nhớ, nó sẽ bắt đầu khởi tạo hướng dẫn cơ bản và các thiết bị ngoại vi để chuẩn bị cho việc nâng cấp firmware. Các thiết bị ngoại vi thường là đồng hồ hệ thống, ngắt và các kênh liên lạc, và bộ lập lịch. Những thứ này cho phép bootloader chấp nhận hướng dẫn từ bên ngoài và nó bắt đầu quá trình nâng cấp; sau khi hoàn tất, nó sẽ reset chip và khi khởi động lại, nó sẽ chuyển sang chế độ hoạt động bình thường.
Lập trình bộ nhớ
Chúng ta sẽ tìm hiểu một chút kiến thức về cấu trúc bộ nhớ và cách lập trình của nó. Để làm điều này, chúng ta sẽ lấy một ví dụ về vi điều khiển AVR, nhưng trước đó, hãy làm rõ một số thuật ngữ cụ thể mà bạn có thể biết hoặc có thể không biết. Mọi loại vi điều khiển đều có sẵn một bộ nhớ không thay đổi được dùng để lưu trữ chương trình. Bộ nhớ được sử dụng phổ biến nhất được gọi là bộ nhớ flash. Nó được chia thành các phần nhỏ hơn khác nhau. Phần nhỏ nhất được gọi là một trang. Các trang được kết hợp và tạo nên một cấu trúc bộ nhớ được gọi là một khu vực. Các khu vực được sắp xếp để tạo thành các cấu trúc lớn hơn được gọi là các khối. Mỗi bộ vi điều khiển đều khác nhau về cách thao tác các khối này. Nhưng hầu hết các bộ vi điều khiển sẽ cho phép bạn ghi một byte duy nhất tại một thời điểm.
Bootloader trong AVR:
AVR đi kèm với một bộ nhớ được chia thành hai phần, một phần ứng dụng, một phần bootloader. Phần ứng dụng chứa mã dành riêng cho ứng dụng và phần bootloader có thể chứa nhiều bootloader khác nhau. Trong AVR, phần này có thể được cấu hình bằng cách thiết lập các cầu chì. Chúng ta có thể đặt không gian bộ nạp khởi động cần thiết theo yêu cầu của chúng ta hoặc đặt nó được sử dụng cho mã ứng dụng.
Khi AVR đi vào bootloader. Đầu tiên, nó xóa bộ nhớ trang và lấy nội dung trang mới từ UART, sau đó sẽ lấp đầy bộ đệm trang. Sau khi viết xong, nó sẽ đợi thêm trang từ UART; Nếu một trang mới có sẵn, quá trình bắt đầu lại một lần nữa; nếu không, chương trình sẽ vào phần RWW (Read While Write) và kết thúc hoạt động. Đây là phiên bản đơn giản hóa của hoạt động bootloader.