Chạy mã một lần trong đời của chương trình C nhúng


8

Làm cách nào tôi có thể tạo một đoạn mã chỉ chạy một lần trong vòng đời của chương trình? Nó có thể được tắt và bật nhiều lần. Tùy chọn duy nhất để chạy đoạn mã một lần nữa phải được flash lại bảng.

Mã này là Phần Hiệu chỉnh mà tôi không muốn chạy lại. Nếu tôi sử dụng EEPROM hoặc Flash, chúng tôi sẽ đặt Cờ thành đúng hoặc Sai. Vì vậy, khi chúng ta lần đầu tiên đọc vị trí bộ nhớ đó, giá trị ngẫu nhiên trong vùng nhớ đó là gì?

Phương pháp tốt nhất để thực hiện điều này trong nhúng C là gì?


5
Sử dụng cờ và lưu cờ này vào eeprom (hoặc đèn flash). Trong mỗi tức thì đọc cờ từ eeprom. Lần đầu tiên ngay lập tức, giá trị của cờ sẽ buộc hàm thực thi. Sau đó, bạn có thể thay đổi giá trị của cờ và lưu lại vào eeprom. Tất cả các lần khác, giá trị cờ sẽ không bắt buộc thực hiện chức năng.
hoo2

2
không rõ những gì bạn đang hỏi.
old_timer

2
Động lực của bạn đằng sau việc ngăn chặn mã chạy lần thứ hai là gì? Điều quan trọng là mã không thể được thiết kế ngược, trong trường hợp đặt cờ để bỏ qua nó có thể không đủ an toàn? Chạy mã lần thứ hai có làm hỏng phần cứng không? Đây có phải là một điều UX, giống như hiển thị thông báo hướng dẫn khi hệ thống được sử dụng lần đầu tiên, trong trường hợp đó có thể mong muốn chức năng "khôi phục cài đặt gốc" (nếu có) để kích hoạt mã để chạy lại?
Micheal Johnson

5
Nói chung, nên cho phép hiệu chỉnh lại trong trường hợp xảy ra sự cố trong lần đầu tiên hoặc hệ thống cần được hiệu chỉnh lại cho một thiết lập khác hoặc để bù cho sự lão hóa phần cứng, v.v. Tôi, ví dụ, có xu hướng làm rối loạn hiệu chuẩn Lần đầu tiên vì tôi không biết mình phải làm gì.
Micheal Johnson

3
Làm thế nào về việc bạn thiết lập mã để có một cách để ra lệnh cho nó chạy (Tôi gửi một cái gì đó qua một cổng nối tiếp). Bằng cách này, không cần phải bận tâm với bộ nhớ không biến đổi và bạn có thể kích hoạt hiệu chuẩn trong quá trình sản xuất một cách có kiểm soát.
alex.forencich

Câu trả lời:


18

Bộ vi điều khiển của bạn có thể có một số EEPROM, bộ nhớ OTP, các bit cầu chì của người dùng, nơi bạn có thể đặt cờ.

Không có "phương pháp tốt nhất trong C nhúng", việc ghi bộ nhớ không biến đổi là khác nhau ở mỗi vi điều khiển.

biên tập:

TỐC BIẾN

Nội dung bộ nhớ flash bị xóa trong khi lập trình thiết bị. Sau khi lập trình, tất cả các byte không được viết có chứa 0xFF. Tham khảo bảng dữ liệu để tìm một khu vực có thể được lập trình an toàn từ bên trong phần sụn đang chạy.

EEPROM

Mặc dù nó không được đảm bảo trong bảng dữ liệu, tất cả các EEPROM mà tôi đã thấy cho đến nay đều chứa 0xFF: s khi được vận chuyển từ nhà máy (ngoại trừ các địa chỉ được lập trình sẵn với một địa chỉ MAC duy nhất, nhưng đó là tài liệu rõ ràng). Một số thiết bị / phần mềm lập trình cũng có thể xóa hoặc lập trình nội dung EEPROM. Một số có thể được viết bảo vệ, vĩnh viễn hoặc đảo ngược.

OTP

Bộ nhớ lập trình một lần luôn chứa các giá trị ban đầu được xác định rõ, được ghi lại trong biểu dữ liệu.

Luôn luôn là một ý tưởng tốt để bao gồm một tổng kiểm tra tốt như CRC32 với dữ liệu được viết, để bảo vệ chống tham nhũng dữ liệu do các bộ phận bị lỗi, lỗi truyền, tia vũ trụ, bất cứ điều gì.


Nếu tôi sử dụng EEPROM hoặc Flash, chúng tôi sẽ đặt Cờ thành đúng hoặc Sai. Vì vậy, khi chúng tôi lần đầu tiên đọc vị trí bộ nhớ đó sẽ là giá trị ngẫu nhiên trong vùng nhớ đó.
ganeshredcobra

2
Trong quá trình sản xuất, thiết lập lại EEPROM (với lập trình viên, nếu có thể hoặc bằng cách tạo một chương trình gạt nước nhỏ câm, flash nó, cấp nguồn bình thường trong vài giây, sau đó tải chương trình sản xuất của bạn).
Nick T

13

Bạn đã nói:

Tùy chọn duy nhất để chạy mã đó phải flash lại bảng.

Những người khác đã nói sử dụng EEPROM để lưu trữ một cờ để cho biết khi nào hàm run_once () đã được chạy. Tuy nhiên, điều này có một nhược điểm là nếu bạn khởi động lại vi điều khiển, cờ ran_it_once trong EEPROM đã được đặt và hàm run_once () sẽ không được thực thi. Nếu vi điều khiển của bạn đã nhúng EEPROM thì có thể xóa cờ ran_it_once khi bạn khởi động lại vi điều khiển, nếu lập trình viên hỗ trợ điều này.

Cách tốt hơn là có số phiên bản trong cả EEPROM và mã. Khi mã chạy từ khi bật nguồn, nó sẽ đọc số phiên bản từ EEPROM và so sánh nó với số phiên bản được lưu trong mã. Nếu chúng không khớp thì hàm run_once () được gọi và hành động cuối cùng của mã run_once () là ghi số phiên bản phần sụn vào EEPROM. Mỗi lần bạn sửa đổi mã nguồn của phần sụn, bạn phải tăng số phiên bản được nhúng trong nó.


1
Điều này thực sự sẽ có cùng một vấn đề như một cờ boolean nếu tất cả người dùng đã làm lại bộ vi điều khiển và nó cần phải được chạy lại (trong kịch bản đó). Nó chắc chắn sẽ giải quyết vấn đề nếu phần sụn được cập nhật và nó cần được chạy lại.
Taegost

8

Chọn một vi điều khiển có thể ghi / xóa bộ nhớ chương trình của chính nó. Sau khi thực thi mã được đề cập, có phần cuối của mã đã nói thay thế lệnh đầu tiên bằng một bước nhảy bỏ qua nó. Tùy chọn, bạn cũng có thể xóa phần còn lại (có thể thay thế bằng nop), do đó hoàn toàn không có cơ hội nào để nó thực hiện lại.

Thông báo này sẽ tự hủy trong 5..4 ...


1
Thông minh như câu trả lời này có thể là, tôi nghĩ nó phức tạp không cần thiết. Có lẽ nó có thể sử dụng một ghi chú chỉ rõ rằng nó có lẽ chỉ nên được sử dụng nếu bộ nhớ liên tục bên ngoài bộ nhớ mã không có sẵn?
skrrgwasme

Ngay cả khi các giải pháp khác là có thể, tôi nghĩ rằng điều này dễ hiểu hơn những giải pháp khác.
Joshua

1
Ngay cả khi các giải pháp khác là có thể, tôi nghĩ rằng điều này sẽ rất khó hiểu ở cấp mã nguồn.
một CVn

Hầu hết các PIC chỉ có 35 hướng dẫn ... điều gì có thể sai? ;)
ndtsc

5

Khi bạn đang sử dụng mã này để hiệu chuẩn, đề xuất của tôi sẽ là tạo ra một quy trình nổ chạy mã hiệu chuẩn như là giai đoạn đầu tiên và thậm chí không có nó trên phiên bản sản xuất hoàn chỉnh của bảng. Điều này tương tự như câu trả lời của apalopohapa, ngoại trừ khác nhau theo nghĩa là bạn sẽ có hai lần tải chương trình riêng biệt: có một quy trình nổ làm chớp tải chương trình đầu tiên chạy tất cả các hiệu chuẩn và phun ra dữ liệu từ đó. Sau đó lấy dữ liệu đó và kết hợp nó vào dữ liệu của chương trình tải thứ hai.

Một lợi ích của phương pháp này là bạn giảm thiểu tối đa dung lượng lưu trữ bạn cần - bạn không cần lưu trữ mã một lần duy nhất của mình, chỉ dữ liệu mà nó tạo ra. Bằng cách có một quy trình nổ tải hai chương trình riêng biệt, bạn cũng tự bảo vệ mình một chút khỏi các lỗi trong mã khởi tạo có thể tồn tại xung quanh. Bạn cũng có một số tính linh hoạt bổ sung nếu bạn muốn chạy lại mã hiệu chuẩn của mình: thay vì phải viết thêm mã để xóa bất kỳ bit nào biểu thị rằng mã của bạn đã được chạy (có thể vô tình bị xóa), bạn chỉ cần chạy lại quá trình nổ mìn.

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.