Bài 20: Lập trình STM32 Flash đọc, ghi và xóa dữ liệu

bai 20 lập trình stm32 flash

Flash là gì, cách lập trình flash trên STM32, tổ chức bộ nhớ STM32 flash, cách đọc, ghi, xóa bộ nhớ Flash và tại sao nó rất quan trọng trong lập trình. Đó là những kiến thức chúng ta sẽ học trong bài hôm nay.

Bài 20 trong Serie Học STM32 từ A tới Z

Flash là gì?

Bộ nhớ flash là một loại bộ nhớ không bay hơi (non-volatile memory), tức là không mất dữ liệu khi mất điện, và có thể xóa rồi lập trình lại (reprogram) nhiều lần.

Về mặt kỹ thuật thì bộ nhớ flash có thể được dùng như một loại EEPROM: nó được đọc/ghi bằng điện và không mất dữ liệu khi ngừng cung cấp điện. Có 2 kiểu bộ nhớ flash chính là NAND và NOR, đặt theo tên cách các ô nhớ được nối với nhau (giống cấu trúc cổng logic NAND và NOR).

Bộ nhớ flash được cấu thành từ các phần tử (cell) nhớ riêng rẽ, mỗi cell lưu 1 bit (hoặc nhiều bit với các loại flash dung lượng lớn).

Tại sao chúng ta phải sử dụng Flash, EEPROM

Bộ nhớ flash ngoài việc lưu chương trình mà lập trình viên nạp vào, còn có một công dụng khác là lưu trữ dữ liệu quan trọng, không bị mất đi mỗi khi reset hoặc tắt điện.

Lấy ví dụ: chiếc điều hòa nhà bạn, khi bạn đặt 27 độ rồi ngắt điện điều hòa, thì khi bật lại nó vẫn chạy ở 27 độ. Điều đó nghĩa là cài đặt của bạn đã được lưu lại, trong Flash hoặc EEPROM (ROM thì chỉ đọc được, không ghi lại được).

Khác biệt giữa flash và EEPROM

Bộ nhớ flash kiểu cổng NAND được đọc ghi theo từng trang (page) nhớ, dung lượng lớn và rẻ (thẻ nhớ, USB, SSD). Còn bộ nhớ flash kiểu cổng NOR thì đọc ngẫu nhiên được từng byte, từng word, nên CPU có thể chạy code trực tiếp từ nó.

Bộ nhớ Flash nhúng trong vi điều khiển (như STM32) là loại NOR: đọc được từng byte/word bất kì, ghi theo từng half-word/word, nhưng muốn xóa thì phải xóa cả page (đưa tất cả các bit về 1).

EEPROM thì xóa và ghi được theo từng byte riêng lẻ.

Vậy nên hãy lưu ý phần này khi lập trình với Flash trên vi điều khiển nhé: muốn sửa 1 byte trong Flash, bạn phải xóa cả page chứa nó rồi ghi lại toàn bộ.

Tổ chức bộ nhớ flash trên STM32f103c8t6

Với dòng medium-density, bộ nhớ STM32 Flash được tổ chức gồm 1 khối chính (main block) 64 KB (STM32F103C8) hoặc 128 KB (STM32F103CB), chia thành các page 1 KB (tức 64 hoặc 128 page), và 1 khối thông tin (information block). Main block bắt đầu từ địa chỉ 0x0800 0000, chương trình bạn nạp vào sẽ được lưu ở đây.

stm32 flash memory

Đọc, ghi, xóa dữ liệu trên flash

STM32 có một bộ nhớ Flash (kiểu NOR) được nhúng sẵn trong vi điều khiển. Tất cả mô tả về việc lập trình được mô tả trong mục 3.3.3 Embedded flash memory của reference manual stm32 , chi tiết thao tác ghi/xóa nằm trong tài liệu PM0075 (Flash programming manual).

Để đọc chính xác dữ liệu từ bộ nhớ Flash, số lượng trạng thái chờ (LATENCY) phải được cài trong thanh ghi FLASH_ACR (Flash access control register) đúng với tần số clock hệ thống (SYSCLK): 0 wait state khi SYSCLK ≤ 24MHz, 1 wait state khi 24MHz < SYSCLK ≤ 48MHz, 2 wait state khi 48MHz < SYSCLK ≤ 72MHz.

Lưu ý: Nếu bạn không cài đúng LATENCY, khi nâng xung nhịp hệ thống lên cao, CPU sẽ đọc sai lệnh từ Flash và chương trình bị treo hoặc HardFault.

Khi dùng CubeMX, phần cài đặt này đã được sinh sẵn trong hàm SystemClock_Config() (tham số FLASH_LATENCY_x truyền vào HAL_RCC_ClockConfig()) theo đúng tần số bạn chọn, nên các bạn có thể yên tâm sử dụng nhé.

Chi tiết được mô tả trong bảng sau:

stm32 flash number o wait

Thao tác xóa trên STM32 Flash phải thực hiện theo page (trang) hoặc xóa toàn bộ chip (mass erase). Thao tác ghi thì thực hiện theo từng half-word (16 bit), hàm HAL ghi word (32 bit) thực chất là ghi 2 lần half-word.

Ngoài ra Flash luôn được khóa sau reset để tránh ghi nhầm, nên chúng ta cần mở khóa trước khi xóa/ghi và khóa lại sau khi xong.

Lập trình STM32 Flash đọc ghi dữ liệu trên STM32

Đầu tiên chúng ta sẽ định nghĩa page bắt đầu và kết thúc.

stm32 flash code

Lưu ý: Hãy chọn page để lưu dữ liệu ở cuối bộ nhớ Flash (ví dụ page 63 bắt đầu từ 0x0800 FC00 với chip 64KB), và đảm bảo chương trình của bạn không lớn tới vùng đó. Nếu chọn trùng vào vùng chứa code, lệnh xóa page sẽ xóa luôn chương trình đang chạy.

Ghi dữ liệu vào Flash

  1. Mở khóa STM32 Flash
  2. Tạo biến struct để xóa
  3. Chọn kiểu xóa theo Page
  4. Địa chỉ bắt đầu xóa
  5. Số lượng page cần xóa
  6. Sau đó gọi câu lệnh xóa và truyền vào struct xóa
  7. Tiếp theo chúng ta có thể ghi dữ liệu vào bằng lệnh Program. Vì ghi kiểu word (32 bit = 4 byte), nên để ghi ô nhớ ngay sau đó, chúng ta sẽ cộng thêm 4 vào địa chỉ ghi nhé.

stm32 flash write

Vì sao phải xóa trước khi ghi? Thao tác ghi Flash chỉ có thể đổi bit từ 1 về 0, không đổi ngược lại được. Xóa page là đưa tất cả bit về 1 (giá trị 0xFF), rồi mới ghi được giá trị mới. Giống như viết bút chì lên giấy: muốn viết lại thì phải tẩy trắng trước đã.

Đọc dữ liệu từ STM32 Flash

Đọc dữ liệu ra thì không cần mở khóa, chúng ta chỉ cần truy xuất trực tiếp theo địa chỉ bằng con trỏ kiểu 32 bit.

stm32 flash read

Cuối cùng, trước while (1) hãy thử ghi dữ liệu vào và đọc ra nhé.

Lưu ý: Flash cần một khoảng thời gian để xóa và ghi (xóa 1 page mất khoảng 20ms), trong thời gian đó CPU bị dừng chờ. Ngoài ra mỗi page chỉ chịu được khoảng 10.000 lần xóa/ghi. Vì vậy không nên xóa và ghi liên tục như biến, hãy chỉ lưu Flash khi có 1 sự kiện cần thiết (ví dụ người dùng đổi cài đặt).

stm32 flash programing

Kết quả

Nạp code và nhấn Debug. Trong tab Memory, chúng ta nhập địa chỉ start page, nhấn Run và xem kết quả.

stm32 flash ket qua

Kết

Lập trình STM32 Flash rất quan trọng, đa phần các ứng dụng đều cần sử dụng flash để lưu trữ dữ liệu. Lập trình với Flash cũng tương đối đơn giản và dễ dàng. Tuy nhiên các bạn không nên xóa và ghi flash quá nhiều lần, vì Flash có giới hạn số lần xóa/ghi, vượt quá thì dữ liệu lưu vào sẽ không còn tin cậy.

Nếu cảm thấy bài viết này có ích hãy chia sẻ với bạn bè nhé. Đừng quên gia nhập hội những anh em Nghiện lập trình nhé!!

5/5 - (1 bình chọn)

4 những suy nghĩ trên “Bài 20: Lập trình STM32 Flash đọc, ghi và xóa dữ liệu”

  1. Tú Huỳnh nói:

    Tạo biến struct để xóa
    Chọn kiểu xóa theo Page
    Địa chỉ bắt đầu xóa
    Số lượng page cần xoá
    —————————–
    chỗ này ban đầu em đọc 3 dòng cuối hơi lúng túng vì không biết nó ở đâu ra. may là xuống dưới tí có cái ảnh ví dụ em mới : à 3 dòng đó là các biến định nghĩa trong struct xóa của cái dòng ở trên ^^.

  2. Trung nói:

    anh cho em hỏi là tại sao anh dùng 2 page cuối là 126 và 127 mà ko dùng các page đầu như page 1, 2, 3? Em cảm ơn anh

Để lại một bình luận

Email của bạn sẽ không được hiển thị công khai. Các trường bắt buộc được đánh dấu *