IC nhớ FLASH,SDRAM và mô hình bộ nhớ của vi điều khiển khi sử dụng bộ nhớ ngoài

Một chương trình nạp cho vi điều khiển cơ bản gồm phần code (chứa trong .text) và data (dữ liệu có thể được khai báo giá trị trước hoặc không). Bên cạnh đó, tổ chức bộ nhớ cho chương trình vi điều khiển còn có các phân vùng gồm heap (chứa các biến được cấp phát vùng nhớ) và stack (chứa các biến lưu trữ trạng thái một số thanh ghi khi vào hàm và các biến cục bộ) phục vụ cho quá trình hoạt động của vi điều khiển. Để mở rộng bộ nhớ, người dùng sẽ cần sử dụng thêm bộ nhớ ngoài cho vi điều khiển STM32. Bài viết này sẽ cung cấp các thông tin giúp mọi người hiểu cơ bản về các IC nhớ Flash, SDRAM và Mô hình bộ nhớ của vi điều khiển khi có sử dụng thêm bộ nhớ ngoài. 

Giới thiệu về FLASH,SDRAM IC

1. Bộ nhớ FLASH

  • Bộ nhớ flash là bộ nhớ không bay hơi (không bị mất dữ liệu khi mất nguồn cung cấp điện) có thể được đọc và ghi, xóa. Việc ghi có thể thực hiện trên từng byte/word trong khi quá trình xoá được thực hiện theo các sector. Các sector thường có size là 4KB [1] (thông số này có thể thay đổi tuỳ thuộc loại vi điều khiển, loại flash các vendor tích hợp ví dụ như sector size = 128 bytes, 256 bytes, 1KB, 2KB, … [2]).
  • Flash có 2 loại chính là NAND và NOR. Trong các kit phát triển STM32, các chip flash theo công nghệ NOR được sử dụng (còn NAND thường được dùng trong các ổ cứng SSD của máy tính). Các bộ nhớ NOR thường phù hợp để lưu trữ một lượng nhỏ dữ liệu (so với các bộ nhớ trên các máy vi tính cá nhân); Vì NOR flash cho phép truy cập ngẫu nhiên nên tốc độ đọc của NOR flash nhanh hơn NAND nhưng NAND có khả năng ghi/xoá nhanh hơn NOR nhờ việc mắc nối tiếp các cell nhớ với nhau [4]. Chính vì thế, STMicroelectronics chọn NOR flash cho các kit phát triển sử dụng chip ARM-Cortex M.
  • NOR flash sử dụng các cell là các mosfet với 2 lớp cực cổng (control gate và floating gate cùng các lớp điện môi – dielectric).
  • Giá trị mặc định của các cell nhớ (1 bit trong bộ nhớ flash) là 1, nghĩa là khi chúng ta xoá toàn bộ bộ nhớ, toàn bộ cell nhớ đều được đưa lên mức logic 1. Khi nạp một chương trình thì các mức bit 1 trong chương trình được giữ nguyên như ban đầu trong khi các bit 0 sẽ được lập trình bằng cách đặt một điện áp cao vào lớp điện môi cùng với điện áp thấp (logic 0) trên cực máng của cell nhớ để đưa mức logic 1 về 0.


Hình 1: Cấu tạo 1 cell nhớ trong bộ nhớ flash
[3]

2. Bộ nhớ SDRAM

  • SDRAM có các cell nhớ được làm từ 1 cổng logic cùng tụ điện. Vì thế các quá trình đọc ghi hầu như không ảnh hưởng tới tuổi thọ của SDRAM cell. Tuy nhiên, việc sử dụng tụ điện để lưu trữ dữ liệu cũng đồng nghĩa là cell nhớ sẽ mất dữ liệu (về logic 0) sau khi ngắt nguồn và các cell SDRAM phải được làm tươi (refresh) định kỳ do các điện tích trong tụ điện bị rò (leakage) theo thời gian.


Hình 2: Tế bào nhớ trong bộ nhớ SDRAM

  • Tổ chức bên trong một bộ nhớ SDRAM thường được phân tách thành các bank, địa chỉ các word trong SDRAM sẽ được phân tích thành địa chỉ các hàng và cột của bank. Điều này làm cho quá trình đọc và ghi trên SDRAM (được dùng làm bộ nhớ RAM ngoài trên STM32) trở nên phức tạp hơn bộ nhớ SRAM (thường được dùng làm bộ nhớ RAM bên trong các chip STM32).

Hình 3: Ví dụ về tổ chức bộ nhớ SDRAM [5]

Giới thiệu về mô hình bộ nhớ có sử dụng bộ nhớ ngoài

1. Giao tiếp giữa bộ nhớ ngoài và vi xử lý

  • Đối với các dòng vi điều khiển STM32, các phần cứng ngoại vi (Timer, UART, SPI, I2C, FMC, QSPI, RAM, Flash,…) được kết nối với vi xử lý ARM-Cortex M thông qua các hệ thống bus như AHB, APB, AXI, các ma trận bus (được cấu thành từ nhiều mạch chọn kênh) và các cầu bus để chuyển đổi giữa các hệ thống bus khác nhau.
  • Các hệ thống bus đóng một vai trò quan trọng không kém so với vi xử lý và bộ nhớ trong việc quyết định đến hiệu năng của vi điều khiển. Tùy vào mục đích ứng dụng của bộ vi xử lý mà loại bus nào sẽ được các hãng thiết kế chip lựa chọn. Ví dụ đối với các máy bàn có hiệu năng rất cao và chạy ở tần số vài GHz (Intel Core I, AMD Ryzen,…) thì một hệ thống bus được sử dụng rất phổ biến là PCI; Toàn bộ sự kết nối của ổ cứng, USB, card màn hình, card wifi,… đều được nối trực tiếp hoặc qua cầu nối đến hệ thống bus PCI trên mainboard và vào CPU. Còn đối với vi điều khiển chạy ở tần số nhỏ hơn 1GHz (sub GHz) thì hệ thống bus như AHB, APB, AXI, AXI Lite thường được sử dụng. 
  • Đối với các dòng vi điều khiển STM32 được thiết kế dựa trên lõi vi xử lý ARM-Cortex M7 (tham khảo trên vi điều khiển STM32F764)  thì có 3 giao diện bus được sử dụng là AXI, AHB, APB (các dòng STM32F4 và STM32F3 chỉ sử dụng AHB và ABP). Cùng một tốc độ xung clock thì hiệu năng của AXI>AHB>ABP [1]. Trong STM32F7, bus AXI kết nối giữa vi xử lý và một cầu bus chia ra 4 hệ thống bus AHB, trong bài hướng dẫn này, chúng ta chỉ quan tâm đến bộ nhớ SDRAM và QSPI Flash nên chúng ta chỉ quan tâm tới hệ thống bus AHB 1 và 2 từ cầu bus:

Bảng 2: Kết nối của ngoại vi phục vụ bộ nhớ ngoài vào hệ thống bus

APB1 Kết nối với ngoại vi FMC Phục vụ cho bộ nhớ SDRAM
APB2 Kết nối với ngoại vi QSPI Phục vụ cho QSPI flash

Hình 4: Kết nối của các ngoại vi phục vụ bộ nhớ ngoài vào ma trận bus [2]

  • Các ngoại vi phục vụ bộ nhớ ngoài là FMC và QSPI lần lượt được kết nối vào hệ thống bus AHB 1 và 2 qua các đường màu đỏ. Các đường nối xanh được đánh dấu cho thấy ta có thể sử dụng DMA để vận chuyển dữ liệu vào và ra khỏi bộ nhớ ngoài, đây là một tính năng rất mạnh tuy nhiên điều này gây ra vấn đề về xung đột dữ liệu khi sử dụng chung với cache; Vấn đề này sẽ được thảo luận ở phần cuối của tài liệu này.

*Lưu ý: các tiền tố 1,2,3,4 được đặt cho bus AHB sau cầu bus là theo ý kiến chủ quan của mình để mọi người dễ hình dung. Thực tế, STMicroelectronics sắp xếp các tiền tố này khác hình 4, bạn đọc cần phải đọc kĩ datasheet để nắm rõ hơn.

2. Việc đọc/ghi tại bộ nhớ ngoài được thực hiện thế nào

Để vi xử lý có thể truy cập bộ nhớ ngoài như một không gian nhớ ở trong hệ thống như bộ nhớ nội, thì các instruction được dùng để đọc/ghi với bộ nhớ nội như mov, str, ldr cũng phải thực hiện được trên bộ nhớ ngoài. Tuy nhiên, các IC SDRAM và Flash ngoài không hỗ trợ sẵn điều này vì chúng ko có khả năng giao tiếp trực tiếp với vi xử lý qua hệ thống bus AHB, mà phải qua ngoại vi giao tiếp. Các ngoại vi FMC và QSPI phải làm công việc này. Có thể hiểu ngoại vi FMC và QSPI như một máy phiên dịch, chuyển đổi các tín hiệu data, address và các handshake protocol (giao thức bắt tay) của hệ thống bus AHB sang các address, data và command (lệnh) cho các bộ nhớ ngoài. Vậy thì từ các ngoại vi “phiên dịch” đó, giao tiếp đọc ghi với bộ nhớ ngoài được thực hiện như thế nào

  • Với SDRAM: Việc đọc hoặc ghi được thực thi bằng cách đưa địa chỉ hàng trước (Row address), sau đó đưa địa chỉ cột lên và cuối cùng là thực hiện lệnh đọc/ghi. Lưu đồ thời gian cho việc đọc hoặc ghi (được đơn giản hoá) trên SDRAM được thể hiện như hình 5 ở dưới. Hoạt động đưa địa chỉ và nạp lệnh đọc/ghi được khái quát thành các lệnh như “Active, Read, Data out”. Ngoài ra, còn có khoảng thời gian như tRP, tRCD…cần được cấu hình hình cho ngoại vi FMC.

Hình 5: Lệnh và timing giữa các lệnh trong SDRAM

  • Đối với bộ nhớ QSPI Flash: Giao thức giao tiếp phức tạp hơn so với SDRAM. Một chân trong bộ nhớ QSPI Flash có thể có nhiều vai trò như nạp lệnh, nạp địa chỉ, đọc/ghi dữ liệu. Đối với QSPI Flash, để đọc dữ liệu, ta phải thực hiện các bước sau:
    • Nạp lệnh vào các chân IO của giao diện QSPI. Lệnh có thể được nạp trên 1 hoặc cả 4 chân IO của QSPI (điều này phụ thuộc vào dòng chip nhớ Flash hoặc việc setup chế độ hoạt động cho chip nhớ Flash)
    • Nạp địa chỉ vào các chân IO. Tương tự như lệnh, địa chỉ có thể được nạp trên 1 hoặc cả 4 chân IO của QSPI
    • Chờ một số chu kì máy được gọi là dummy cycles nếu đang cần đọc dữ liệu từ Flash (để cho Flash chuyển các chân từ trạng thái input sáng output). Số clock cho dummy cycles nằm trong datasheet của IC bộ nhớ Flash. Đối với việc ghi, không có sự chuyển từ input sang output cho các chân IO nên không có dummy cycles.
    • Đọc hoặc ghi dữ liệu.
    • Quá trình đọc từ một bộ nhớ QSPI Flash được miêu tả như trong hình 6
    • Trên thực tế, quá trình đọc/ghi đối với với bộ nhớ QSPI Flash còn được chia làm nhiều loại, ví dụ như đọc (read), fast read (đọc nhiều word liên tiếp), word read (đọc 1 từ duy nhất),…

Hình 6: Đọc dữ liệu của QSPI Flash

3. Mô hình lưu trữ chương trình bộ nhớ

  • Một chương trình nạp cho vi điều khiển về cơ bản gồm phần code (chứa trong .text) và data (dữ liệu có thể được khai báo giá trị trước hoặc không). Ngoài ra, tổ chức bộ nhớ cho chương trình vi điều khiển còn bao gồm heap (chứa các biến được cấp phát vùng nhớ) và stack (chứa các biến lưu trữ trạng thái một số thanh ghi khi vào hàm và các biến cục bộ).
  • Cấu trúc thông thường của một chương trình giữa bộ nhớ Flash và RAM trong STM32 thông thường sẽ được sắp xếp như hình 7:

Hình 7: cấu trúc chương trình C trong bộ nhớ Flash (bên trái) và Ram (bên phải). 

Như hình trên, ta thấy rằng chỉ có các biến được khởi tạo giá trị ban đầu mới được sao chép dữ liệu từ Flash qua RAM. Tuy nhiên, sự sắp xếp này là không bắt buộc hay cố định, đây chỉ là cấu hình mặc định của STMicroelectronics khi người lập trình không can thiệp vào file linker. Trên thực tế, chỉ có Reset vector (trong vector table) là cố định vì mọi chương trình được khởi động từ instruction ở vị trí 0x00000004 còn lại toàn bộ các phần khác đều có thể được thay đổi vị trí.

  • Ví dụ, người lập trình muốn chương trình ứng dụng (application code) chạy từ flash ngoài còn dữ liệu thì vẫn lưu trong flash nội thì trong application code (ở vùng nhớ nội) phải có bootloader trỏ đến vùng nhớ chứa application code ở flash ngoài như hình 8, bootloader cũng cần thực hiện khởi tạo trước một số ngoại vi để phục vụ việc giao tiếp bộ nhớ ngoài, đọc lỗi, nạp code cho bộ nhớ ngoài,… Người ta còn gọi kỹ thuật này là XIP (Execute In Place). (trích dẫn)

Hình 8: Khởi chạy code từ bộ nhớ ngoài

 

  • Ví dụ được thực hiện trong tài liệu, toàn bộ application code nằm trong bộ nhớ nội (để đảm bảo tốc độ thực thi vì tốc độ QSPI Flash chậm hơn Flash nội), các weights của mô hình AI sẽ được đặt ở Flash ngoài, Activations và các buffer chứa dữ liệu thô từ cảm biến sẽ được đặt ở SDRAM (RAM ngoài) như hình 9.

Hình 9: Tổ chức bộ nhớ cho một ứng dụng EdgeAI

  • Sự sắp xếp như trong hình 9 là không bắt buộc, nghĩa là người lập trình có thể di chuyển các weights, variable qua lại giữa các bộ nhớ khác nhau tùy ý. 
  • Ví dụ: 
    • Weight cho một mô hình 10 lớp sẽ được lưu thành 10 mảng khác nhau cho mỗi lớp; Người lập trình có thể cho 5 lớp ở Flash ngoài còn 5 lớp còn lại ở Flash nội; Khi CPU reference tới mảng đó (bằng các lệnh str, ldr, etc) trên bus địa chỉ sẽ xuất hiện địa chỉ tương ứng và chip nhớ tương ứng sẽ đưa dữ liệu lên bus dữ liệu. Nhớ đó, ta không cần các instruction đặc biệt nào để truy xuất bộ nhớ ngoài; Điều này không chỉ giảm tải cho người lập trình còn giúp giảm đi sự phức tạp cho lõi vi xử lý (tăng tốc độ thực thi).
    • Tương tự cho SDRAM, người lập trình có thể để activation ở RAM nội trong khi Input buffer ở RAM ngoài,…
  • Từ đó, ta thấy được sự tự do trong thiết kế tổ chức bộ nhớ của các vi điều khiển STM32, chỉ có một điều bắt buộc phải giữ nguyên, đó là địa chỉ base của các bộ nhớ ngoài phải theo thiết kế của vi xử lý (sẽ được trình bày khi nói đến ngoại vi và bộ nhớ ngoài cụ thể).

Qua bài viết này mình đã trình bày các thông tin cơ bản về các IC nhớ Flash, SDRAM và Mô hình bộ nhớ của vi điều khiển khi có sử dụng thêm bộ nhớ ngoài.
Cùng đón chờ phần tiếp theo của nội dung này với chủ đề “Sử dụng Linker Script trong khai báo bộ nhớ”.  Chúc các bạn thành công!

Các tài liệu đã tham khảo:

[1]https://community.nxp.com/t5/LPCXpresso-IDE/Flash-wear-out/m-p/547098
[2]https://hub.digi.com/dp/path=/support/asset/technical-note-tn226-supported-flash-devices-for-rabbit-2000/3000-based-boards
[3]https://www.iue.tuwien.ac.at/phd/windbacher/node14.html
[4]https://www.tuxera.com/blog/nand-nor-flash-embedded-developers-guide/
[5]https://www.issi.com/WW/pdf/42-45S32400F.pdf


Nhóm tác giả
Ng.Q.Phương
Ng.H.N.Thương
Ng.H.Phúc