Tại sao chúng ta cần một bộ nạp khởi động tách biệt với chương trình ứng dụng của chúng ta trong vi điều khiển?


28

Tại sao chúng ta cần một chương trình riêng biệt trong cùng bộ nhớ chương trình flash của vi điều khiển, cụ thể là STM32F103, được gọi là bộ tải khởi động?

Điều gì đặc biệt về nó để giữ cho nó tách biệt với chương trình ứng dụng chính?

Nói chung, bộ tải khởi động của hệ thống dựa trên bộ vi xử lý (giả sử PowerPC MPC8270) thực hiện công việc tương tự như bộ vi điều khiển (nói ARM STM32F103) hoặc chúng thực hiện các công việc khác nhau về cơ bản với nhau và cả hai đều được gọi là 'bộ nạp khởi động' với nhau. ?


2
cùng một lý do bạn có các chip và bộ phận riêng lẻ và không phải là một cấu trúc nguyên khối khổng lồ
Emobe

Bạn không. Chỉ cần nhập chương trình của bạn với các công tắc và đèn trên bảng điều khiển máy tính.
Hot Licks

1
Nói đúng ra, bạn không cần một chương trình bộ nạp khởi động riêng trên vi điều khiển. Nhưng chúng tôi thường chọn để có một chức năng tiện ích bổ sung mà nó cung cấp. Nếu các chức năng này là không cần thiết, không muốn, thì bạn có thể loại bỏ bộ nạp khởi động. Bộ tải khởi động vi điều khiển thường được sử dụng để ghi chương trình mới vào flash. Nó đôi khi có thể được sử dụng để gỡ lỗi các chức năng, một số điểm dừng hỗ trợ và các chức năng dễ có khác. Trên máy vi tính, thông thường bộ tải khởi động tải các chương trình từ bộ nhớ chung và sẽ cần thiết ở đó.
ghellquist

Câu trả lời:


55

Bộ tải khởi động trên vi điều khiển có trách nhiệm cập nhật phần sụn chính qua kênh liên lạc khác với tiêu đề lập trình. Điều này rất hữu ích để cập nhật chương trình cơ sở trong lĩnh vực qua BLE, UART, I2C, thẻ SD, USB, v.v ... Sẽ rất bất tiện khi yêu cầu khách hàng mua lập trình viên chỉ để cập nhật chương trình cơ sở trên thiết bị của họ.

Lý do tại sao bộ nạp khởi động được giữ riêng biệt là cho độ tin cậy. Bộ tải khởi động và mã ứng dụng được đặt trong các phần riêng biệt của flash, để mã ứng dụng có thể được xóa và ghi lại bởi bộ nạp khởi động mà không thay đổi bất cứ điều gì liên quan đến mã bộ tải khởi động.

Nếu bộ tải khởi động và ứng dụng được giữ cùng nhau, thì mã bộ tải khởi động sẽ cần được sao chép vào RAM trước khi có thể chạy, vì bất kỳ bản cập nhật chương trình cơ sở nào cũng sẽ xóa mã bộ tải khởi động trong flash. Nếu nguồn bị cắt với mã bộ nạp khởi động trong RAM và đèn flash bị xóa, thiết bị sẽ bị brick.


3
Chúng ta là cùng một lý do. Chúng nằm trong cùng một đèn flash, nhưng bộ tải khởi động là đèn flash xóa liên kết và đủ thông minh để chỉ xóa đèn flash cao hơn địa chỉ của chính nó.
Joshua

3
Trong một số trường hợp, tiêu đề lập trình của bộ vi xử lý thực sự có thể không truy cập được mà không cần phải tháo rời khung máy của sản phẩm, do đó việc có thể lập trình lại nó trên bus comms mà không cần phần cứng thêm là yếu tố chính cho độ tin cậy.
John Go-Soco

6
@ alt-rose Bộ tải khởi động và chương trình ứng dụng là các chương trình được biên dịch riêng, mỗi chương trình có mã và main()chức năng khởi động riêng . Khi khởi động, mã khởi động của bộ nạp khởi động sẽ chạy và gọi bộ nạp khởi động main(). Chương trình bộ nạp khởi động kiểm tra một chương trình ứng dụng hợp lệ và sau đó chuyển sang mã khởi động của chương trình ứng dụng gọi chương trình ứng dụng main(). Mã khởi động của mỗi chương trình khởi tạo môi trường thời gian chạy C cho chương trình tương ứng (nghĩa là khởi tạo biến, ngăn xếp, v.v.) và thông thường, không chương trình main()nào trở lại mã khởi động.
kkrambo

1
@ alt-rose: Cũng giống như cách CPU lấy địa chỉ bắt đầu của bộ tải khởi động - không. Thay vào đó, CPU chỉ định những gì nó sẽ sử dụng làm địa chỉ bắt đầu của bộ tải khởi động và bộ nạp khởi động chỉ định những gì nó sẽ sử dụng làm địa chỉ bắt đầu của chương trình ứng dụng.
MSalters

4
@kkrambo Mặc dù thông thường là đúng, nhưng không có yêu cầu nào (cũng không phải sự thật trên toàn cầu) rằng một bộ nạp khởi động được viết bằng ngôn ngữ C hoặc có nguồn gốc C với maintất cả.
Yakk

26
  1. Vì vậy, quá trình tải có thể phục hồi từ lỗi. Giả sử có lỗi giao tiếp hoặc ngắt nguồn trong quá trình nâng cấp. Nếu bộ tải khởi động là một phần của ứng dụng bạn đang nâng cấp thì người dùng sẽ không thể thử lại mà không sử dụng phần cứng đặc biệt để phản xạ lại bộ tải khởi động.

  2. Một số bộ vi điều khiển không thể thực thi mã từ RAM. Nếu bộ tải khởi động được trộn lẫn với phần còn lại của phần mềm thì bạn thực sự sẽ không thể nâng cấp phần mềm của mình vì bạn không thể xóa các trang flash mà bạn hiện đang thực hiện. Công việc xung quanh là trước tiên ghi mã mới vào nửa sau của flash, sau đó nhảy tới nó. Mã mới sau đó tự sao chép vào nửa đầu của đèn flash. Tất nhiên nhược điểm là flash flash thường chậm và bây giờ bạn phải thực hiện hai lần quá trình tải có thể mất tới hai lần. Ngoài ra, công việc này giới hạn kích thước ứng dụng của bạn không lớn hơn một nửa tổng số đèn flash của bạn.

  3. Các bộ tải khởi động được viết tốt cố gắng xác minh rằng mã hợp lệ tồn tại trên thiết bị trước khi thử thực thi nó. Nếu bộ tải khởi động và mã khác được trộn lẫn với nhau thì làm sao bạn có thể chắc chắn rằng thói quen xác nhận của bạn sẽ hoạt động nếu tất cả các mã không tải?

  4. Xác thực. Bộ tải khởi động an toàn cố gắng xác minh rằng ứng dụng được tải khớp với chữ ký số trước khi thực thi. Nhưng nếu bộ tải khởi động và mã khác được trộn lẫn với nhau thì bạn không thể kiểm soát những gì chạy trên thiết bị vì một khi người dùng tải mã mới, bạn không thể kiểm soát những gì xảy ra khi khởi động.


4
Ví dụ về điểm 2, một số bộ vi điều khiển thậm chí có thể không RAM có thể truy cập khi khởi động: ví dụ, Raspberry Pi sử dụng GPU của nó để tải bộ tải khởi động từ thẻ SD, sau đó kích hoạt bộ xử lý và bộ nhớ ARM.
ErikF

11

Họ thường ở đó để cho phép bạn cập nhật chương trình ứng dụng chính của mình.

Bạn cần một số mã biết cách xóa và lập trình lại một số đèn flash bên trong, đó không thể là chương trình chính vì khi nó tự xóa, nó sẽ không thể lập trình lại.


9

Bộ tải khởi động cho phép MCU giao tiếp với người khác để chấp nhận một chương trình mới, lưu trữ và chạy nó sau khi thiết lập lại. Nếu bạn không có bộ tải khởi động, thì cần có Lập trình viên để truy cập bộ nhớ và đặt chương trình vào vị trí.


2
Nó khá là nhiều. MCU chỉ có thể nhận mã thông qua một hệ thống con lập trình đặc biệt (như AVRICE hoặc JTAG) hoặc bằng cách có bộ tải khởi động trong flash. Đây là một quyết định của ứng dụng về mức độ phức tạp của bộ tải khởi động, ví dụ một số hệ thống có thể tải mã từ WiFi. Trên các MCU cấp thấp như ATTiny, bộ tải khởi động (và chân nối tiếp) là một chi phí lớn, vì vậy bạn luôn sử dụng một lập trình viên.
Giàu

7

Ngoài các câu trả lời đúng khác về việc cho phép lập trình lại phần sụn chính từ bộ tải khởi động, một lợi ích khác của việc có bộ nạp khởi động là tách biệt một cách hợp lý các tác vụ "làm một lần khi khởi động" khỏi mã bạn cần trong thời gian chạy. Sau đó, sau khi bộ nạp khởi động hoàn thành các tác vụ cấu hình ban đầu, phần sụn chính có thể đuổi bộ nạp khởi động với tất cả mã không còn cần thiết khỏi bộ nhớ, tiết kiệm không gian RAM đáng kể. Có thể đạt được điều này theo những cách khác, nhưng phần tách bootloader / firmware giúp cho nhiều kiến ​​trúc dễ dàng hơn nhiều.


1
Trên một vi điều khiển, mã rất có thể không bao giờ nằm ​​trong RAM, vì vậy nó không thể bị xóa. Tất nhiên, bạn có thể loại bỏ dữ liệu của bộ nạp khởi động khỏi RAM.
Ben Voigt

@BenVoigt, nó phụ thuộc vào vi điều khiển. Một số (chủ yếu là những người có flash NOR) sẽ cho phép bạn thực hiện trực tiếp ngoài flash, nhưng những người khác (thường là với flash NAND, đang trở nên phổ biến hơn) yêu cầu bạn phải thực hiện hết RAM. Đôi khi, thậm chí không có bất kỳ đèn flash nào trên tàu và bạn phải sao chép mã từ chip flash ngoài vào SRAM cục bộ trước khi bạn có thể thực hiện bất cứ điều gì.
Nate S - Tái lập lại

2

Câu trả lời ngắn gọn, là bởi vì phần mềm là tuyệt vời.

Bạn có thể có mọi thứ mà bộ nạp khởi động là "phần cứng thuần túy". Nhưng nó rất xa, rất xa, dễ dàng hơn để có các tác vụ mà bộ nạp khởi động được viết dưới dạng phần mềm, sau đó được giải thích bằng phần cứng.

Các tác vụ này có thể liên quan đến việc thiết lập phần cứng cho phần mềm "thực" để chạy (ví dụ: trên Raspberry Pi (thông qua @ErikF)), có một giao thức để thay thế chương trình "thực" trước khi chạy (kiểm tra mã pin, nếu pin đó được đặt sau đó khởi động lại chương trình thực) hoặc thậm chí thiết lập môi trường phần mềm cho chương trình "thực".

Trên phần mềm quy mô nhỏ hơn, khi bạn chạy một trình tải ứng dụng có thể thực thi, các công cụ di chuyển sẽ thực hiện các công việc như tải các phần dữ liệu của bạn vào bộ nhớ, đôi khi sửa địa chỉ, thiết lập đối số cho các nội dung chính hoặc toàn cầu khác, tạo ra các thư viện do HĐH cung cấp và sau đó nhảy đến đầu _mainmã. Một số trong những điều này có thể được thực hiện bởi một bộ tải khởi động.

Trong một vi điều khiển, một số tác vụ mà bộ tải khởi động thực hiện có thể được tách ra trong chương trình. Trình biên dịch cho nền tảng của bạn có thể tự động đưa mã "thiết lập" vào mọi tệp thực thi.

Nhưng, có nó trong bộ tải khởi động có nghĩa là cùng một trình biên dịch có thể hoạt động trên các phần cứng khác nhau, vì bộ tải khởi động có thể "che giấu" sự khác biệt giữa các nền tảng.

Trên hết, thực tế là đèn flash của chương trình chính không gây rủi ro cho bộ tải khởi động (và khả năng khởi động lại chương trình chính) và có một bộ tải khởi động không tầm thường là một điều khá tuyệt vời.


-1

Một câu trả lời chưa được đề cập là sự cần thiết phải phân tách các mối quan tâm do những hạn chế của ngôn ngữ C.

Nói chung, bộ tải khởi động được viết bằng hỗn hợp của hội và C, với giai đoạn khởi động rất sớm trong hội.

Điều này được thực hiện để thiết lập một số thứ như:

  • phân bổ ngăn xếp C
  • đọc con trỏ ngăn xếp vào thanh ghi
  • đọc bộ đếm chương trình vào sổ đăng ký
  • khai báo vectơ thiết lập lại
  • tải giai đoạn thứ hai (initramfs) vào RAM.

Đây là một xấp xỉ rất thô sơ của các bước được thực hiện và tôi đang mô tả quá trình khởi động ARM, nó lại khác với x86 và các kiến ​​trúc khác.

Tuy nhiên, lý do nguyên tắc vẫn giống nhau: phân bổ ngăn xếp C phải được thực hiện từ lắp ráp.


Tại sao các downvote? Điều này vừa có liên quan vừa chính xác.
BitShift

-1

Một phần của câu hỏi chưa được trả lời cho đến nay là sự khác biệt giữa bộ tải khởi động trên bộ vi điều khiển và hệ thống vi xử lý.

Vi điều khiển

Hầu hết các bộ vi điều khiển đều có bộ nhớ ROM tích hợp có chứa mã chương trình của chúng. Thay đổi mã này thường yêu cầu một thiết bị lập trình kết nối với giao diện lập trình của vi điều khiển (ví dụ: ISP trên ATMega). Nhưng các giao diện lập trình này thường không thuận tiện để sử dụng, so với các giao diện khác, vì chúng có thể không có sẵn trong ngữ cảnh cụ thể. Vì vậy, ví dụ, trong khi hầu hết mọi máy tính đều có cổng USB, giao diện SPI cần thiết cho ISP hiếm hơn nhiều và các giao diện khác như giao diện PID được sử dụng trên ATXMega chỉ được hỗ trợ bởi phần cứng lập trình chuyên dụng.

Vì vậy, ví dụ, nếu bạn muốn cập nhật phần mềm từ máy tính thông thường mà không cần bất kỳ phần cứng bên ngoài nào, bạn có thể sử dụng bộ tải khởi động đọc từ một loại giao diện khác (ví dụ: RS232, USB hoặc RS232 qua USB như trên Arduino) để lập trình cho thiết bị trên các giao diện phổ biến.

Điều đó nói rằng, nếu bạn không cần chức năng này, bộ nạp khởi động là hoàn toàn tùy chọn. Bộ vi điều khiển vẫn có thể chạy mã hoàn toàn mà không cần bộ tải khởi động.

Bộ vi xử lý

Trên một bộ vi xử lý mọi thứ có một chút khác biệt. Mặc dù hầu hết các bộ vi xử lý đều có ROM đủ lớn cho bộ tải khởi động, những ROM đó không đủ lớn để chứa một hệ điều hành đầy đủ. Vì vậy, mục đích của bộ tải khởi động là khởi tạo phần cứng, tìm kiếm một hệ điều hành có khả năng khởi động, tải nó và chạy nó. Vì vậy, bộ nạp khởi động là rất quan trọng cho mỗi lần khởi động.

Trên các hệ thống x86 / x64, bộ tải khởi động này là BIOS hoặc UEFI (về cơ bản là phiên bản mới hơn của BIOS).

Đôi khi bạn thậm chí có thể có nhiều bộ tải khởi động đang chạy trong một chuỗi. Ví dụ: nếu bạn có một hệ thống khởi động kép với Windows và Linux, bạn có thể kết thúc bằng các điều sau:

  • BIOS / UEFI khởi động và tìm thấy GRUB được cài đặt. Sau đó, nó tải GRUB (= Grand Unified Bootloader)
  • GRUB tìm thấy một số loại Linux và Windows Bootloader. Người dùng chọn Bộ tải khởi động Windows.
  • Bộ tải khởi động Windows khởi động và tìm thấy Windows 7 và Windows 10 được cài đặt. Người dùng chọn Windows 10.
  • Windows 10 cuối cùng cũng khởi động.

Vì vậy, trong trường hợp này, có ba phần mềm có thể được coi là bộ tải khởi động. Cả GRUB và Windows Bootloader hầu hết đều ở đó để cung cấp cho người dùng tùy chọn lựa chọn khởi động thuận tiện hơn so với BIOS / UEFI sẽ cung cấp cho họ. Nó cũng cho phép nhiều hệ điều hành được khởi chạy từ cùng một ổ cứng hoặc thậm chí cùng một phân vùng.

TLD

Vì vậy, trong khi trong cả hai hệ thống, bộ nạp khởi động thực hiện những điều tương tự (giúp người dùng chọn mã nào để khởi động) cả hai đều khác nhau rất nhiều về cách họ thực hiện điều đó và chính xác những gì họ làm.


Mặc dù rất hữu ích để phân biệt các hệ thống có đủ bộ lưu trữ không bay hơi truy cập ngẫu nhiên (ROM hoặc flash) để giữ toàn bộ chương trình khỏi các hệ thống cần chạy mã từ RAM, nhưng có cả bộ vi điều khiển của cả hai loại và bộ vi xử lý của cả hai loại.
supercat

Tất nhiên, sự khác biệt giữa vi điều khiển và vi xử lý không phải là đường viền cứng và một số vi điều khiển hoạt động giống như vi xử lý và ngược lại. Đó là lý do tại sao tôi lấy AtMega / Arduino và x86 / x64 làm ví dụ, bởi vì chúng hoạt động theo cách đó.
Dakkaron

"Bộ vi xử lý có ROM đủ lớn cho bộ tải khởi động ... Trên các hệ thống x86 / x64, bộ tải khởi động này là BIOS hoặc UEFI" Nope. BIOS hoặc UEFI được lưu trữ trong bộ nhớ flash ngoài chip. ROM trên chip dành cho các chức năng cấp thấp hơn, như khởi tạo vi mã.
Ben Voigt

@Dakkaron: Tôi sẽ vẽ ranh giới giữa bộ vi xử lý và vi điều khiển dựa trên việc chip có được thiết kế để có thể sử dụng cho các mục đích không tầm thường mà không cần bất cứ điều gì khác trên bus địa chỉ hay không. 8031 sẽ không đủ điều kiện ngoại trừ chức năng 8051 (chắc chắn là vi điều khiển) không được chỉ định là có bất kỳ thứ gì hữu ích trong ROM bên trong, nhưng mặt khác sẽ được thiết kế để có thể sử dụng hoàn toàn từ bộ nhớ trong). Một cái gì đó giống như một chiếc RCA / CDP 1802 sẽ không đủ điều kiện mặc dù nó có thể được sử dụng để lái một bảng tên LED ...
supercat

... Không có RAM và ROM ngoài, vì các thiết kế RAMless / ROMless bị giới hạn trong các tác vụ tầm thường. Một cái gì đó giống như TMS 32050 mà nếu tôi nhớ lại có bộ tải khởi động và một vài nghìn từ trong 16 bit RAM bên trong sẽ đủ điều kiện làm vi điều khiển, tuy nhiên; mặc dù nhiều ứng dụng sẽ yêu cầu thêm RAM nhiều hơn, nhưng nếu được kết nối qua UART với hệ thống khác, nó có thể phục vụ nhiều mục đích mà không cần bất cứ điều gì trên bus bộ nhớ.
supercat
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.