Giao tiếp mở rộng bộ nhớ SDRAM vi điều khiển STM32 với IC IS42S32400F qua giao diện FMC

Để mở rộng bộ nhớ RAM cho nhu cầu lưu trữ các dữ liệu của vi điều khiển, người thiết kế dự án cần sử dụng IC nhớ SDRAM để ghép nối với vi điều khiển và thực hiện các cấu hình, khai báo cần thiết để sử dụng bộ nhớ mới này một cách bình thường như bộ nhớ RAM tích hợp.Giao diện Flexible Memory Controller(FMC) của vi điều khiển thường được sử dụng để giao tiếp với SDRAM, và nhiều loại bộ nhớ khác như PSRAM, NAND/NOR FLASH,…
Trong bài viết này, TAPIT chia sẻ cùng các bạn thông tin về bộ nhớ SDRAM, giao diện giao tiếp, các bước để thực hiện cấu hình, khai báo mở rộng bộ nhớ RAM và kết quả thử nghiệm. Bài viết sử dụng bảng mạch STM32F746 Discovery, board mạch này có sẵn IC nhớ SDRAM IS42S32400F.

Hình 1: Giao tiếp FMC của SDRAM trên board STM32F746 DISCO

Hình 2: Tổ chức bộ nhớ SDRAM của IC IS42S32400F dùng trong board STM32F746 DISCO

Các khối chân trong Hình 1 và các cấu tạo IC SDRAM trong Hình 2:

  • Address: 12 chân địa chỉ cho địa chỉ hàng và cột . Một lưu ý là trong Hình 2, dù phần cột chỉ dùng 8 chân địa chỉ nhưng vẫn phải có 12 chân địa chỉ để đáp ứng đủ 12 chân cho phần địa chỉ hàng.
  • Bank: IC SDRAM này có 4 banks nên cần 2 chân cho địa chỉ Bank là BA0 và BA1
  • Data: IC SDRAM IS42S32400F hỗ trợ truyền nhận 32 bits dữ liệu cùng lúc. Tuy nhiên lưu ý là trong thiết kế board của ST như Hình 10, 16 chân đại diện 16 bits cao đã bị nối xuống âm. Do đó, chỉ có thể truyền nhận 16 bits và ½ dung lượng bộ nhớ không thể sử dụng được.
  • Các chân control: 
  • CLK: xung clock cấp cho IC nhớ. Thông số này phải được kiểm tra ở datasheet
  • CKE: Clock Enable cho SDRAM
  • CS: Chip select
  • RAS: Row address strobe hay còn gọi là chân kích hoạt địa chỉ hàng. Khi vi điều khiển cấp địa chỉ hàng cho SDRAM thì kéo chân này xuống mức thấp
  • CAS: Column address strobe hay còn gọi là chân kích hoạt địa chỉ cột. Khi vi điều khiển cấp địa chỉ cột cho SDRAM thì kéo chân này xuống mức thấp
  • Lưu ý: RAS và CAS không thể đồng thời xuống mức thấp.
  • WE: Write enable ra lệnh ghi hay đọc vào SDRAM
  • DQM<0,1,2,3> (theo hãng sản xuất chip RAM) hay NBL<0,1,2,3> (theo kí hiệu của ST): Chân chọn byte hay gọi là Data Input/Output Mask. Ví dụ vi điều khiển cần 1 dữ liệu 1 byte nhưng lúc nào cũng có 2 bytes (16 bits) được truyền thì phải mask (mặt nạ) byte không cần thiết. Đối với IC SDRAM, thì có 4 chân DQM, tuy nhiên board STM32F746 DISCO chỉ dùng 16 bits nên chỉ cần 2 chân NBL0/1 còn 2 chân 2 và 3 sẽ được nối xuống âm.

1.Các tham số của SDRAM và cách đọc/sử dụng

1.1. Địa chỉ và bank

  • Như đã nói ở phần trên, SDRAM sử dụng địa chỉ theo hàng và cột. Tuy nhiên các thông số về hàng cột được lấy ở đâu?
  • Đầu tiên, ta cần xác định chip SDRAM mà chúng ta đang có. Trong trường hợp của tác giả bài viết là STM32F746-DISCO và chip SDRAM là IS42S32400F. Chúng ta cần tải datasheet của chip SDRAM [1].
  • Trong datasheet, ta chú ý đến phần Address Table ở Hình 3 bên dưới:

Hình 3: Address Table của SDRAM IS32S32400F

  • Ta có thể thấy được kí hiệu và từ đó có được số chân cho hàng, cột và banks

1.2. Clock

  • Mỗi chip SDRAM đều có giới hạn về tần số tối đa để có thể hoạt động ổn định. Nếu chạy ở tốc độ cao hơn tần số tối đa, các tham số Timing mà ta bàn ở phần C sẽ quá nhỏ và SDRAM sẽ không thể đáp ứng được tốc độ truyền cao; Hậu quả là dữ liệu ra sẽ bị corrupted.
  • Để biết được tần số tối đa mà chip SDRAM có thể hoạt động, ta cần xem phần Key Timing Parameter như Hình 4 dưới:

Hình 4: Tần số hoạt động của chip SDRAM

  • Đầu tiên, ta thấy có 3 version: -6, -7 và -75E còn được gọi là Speed/CL variation. Để xác định được thông số trên thì phải coi tên chip RAM; Ví dụ chip IC của tác giả có dòng -6BL như hình 5 dưới:


Hình 5: Speed/CL

  • Ở đây ta hiểu Speed/CL của IC này ở mục -6 trong datasheet, B là chỉ dạng Package (BGA), L xác định loại chì hàn cho IC SDRAM (L = SnAgCu cho package BGA).
  • Từ đây ta biết được chip SDRAM có thể chạy được ở 2 tần số tối đa với 2 tham số CL (CAS Latency) khác nhau là:
166MHz CL = 3
100MHz CL = 2
  • Ở trong bài viết này, tác giả sử dụng tham số là: 100MHz, CL = 2 để dễ cấu hình trong Mục 3 dưới đây. Nếu sử dụng 166MHz, thì phải rất cẩn thận trong việc cấu hình tần số cho core và các ngoại vi khác của vi điều khiển.

1.3.Timing

  • Trong SDRAM, việc hiểu và hiệu chỉnh các tham số timing chính xác là vô cùng quan trọng vì nó ảnh hưởng trực tiếp đến độ tin cậy khi truyền dữ liệu.
  • Trước khi đọc chi tiết về cái timing phía dưới, các bạn hãy xem sơ qua các bước cũng như lệnh để đọc 1 đơn vị dữ liệu ra khỏi SDRAM ở Hình 6:

Hình 6: Một số lệnh và timing cơ bản của SDRAM

  • Để cấu hình giao tiếp SDRAM với STM32 qua giao thức FMC, ta có 7 tham số timing sau cần chú ý:
    • tMRD(Mode Register Delay Time): Thời gian trễ từ việc set thanh ghi Mode của SDRAM tới lúc lệnh trong thanh ghi được thực thi
    • tRAS(Row Address Strobe Time): Thời gian tối thiểu từ lệnh ACTIVE đến lệnh PRECHARGE
    • tRC(Row Cycle Time): Thời gian tối thiểu giữa 2 lệnh READ/WRITE liên tiếp nhau khi không cùng 1 page trong SDRAM.
    • tDPL(Write Recovery Time): Thời gian tối thiểu từ lệnh WRITE đến PRECHARGE
    • tRP(Precharge to Row Time): Thời gian tối thiểu từ lệnh PRECHARGE tới ACTIVATE
    • tRCD(Row Column Delay Time): Thời gian tối thiểu từ lúc có lệnh ACTIVE (đưa địa chỉ hàng vào chân địa chỉ) đến lúc địa chỉ Cột được đưa vào chân địa chỉ
    • tCAS(Column Access Time): Thời gian tối thiểu từ lệnh READ (địa chỉ hàng được đưa lên chân địa chỉ) cho đến khi dữ liệu được đọc hoặc ghi. Thời gian này còn được gọi với tên gọi khác quen thuộc hơn là CAS Latency hay CL
  • Các thông số timing trên chỉ là một phần nhỏ mà chúng ta cần quan tâm khi thiết lập ngoại vi giao tiếp. Thực tế thì có rất nhiều thông số khác được ghi trong Datasheet như Hình 7 ở dưới (Phần lớn các tham số timing được thể hiện bằng cycle-chu kỳ tần số hoạt động của SDRAM):

Hình 7: Các thông số timing của chip SDRAM IS42S32400F

  • Thực tế thì việc đọc/ghi trên SDRAM phức tạp hơn nhiều vì nó còn liên quan đến việc đọc/ghi theo burst (đọc một chuỗi các bytes hay words liên tiếp nhau trong 1 page) cùng với các policies đọc/ghi như open-page/closed-page/limited-open-page/… policies.
  • Đối với bài hướng dẫn nãy, vì ở phần Clock ta đã chọn tham số Clock/CL = 100MHz/2 nên toàn bộ tham số timing ở Hình 7 ta phải chọn phần có CAS Latency (CL) là 2 và ở cột “-6”.

2.Cấu hình ngoại vi FMC trên CubeMX

  • Dựa vào tần số hoạt động và các thông số timing datasheet để ta có thể cấu hình clock cũng như ngoại vi FMC của vi điều khiển.
  • Đầu tiên về clock, ngoại vi FMC được nối trực tiếp vào cầu chia bus AXI ra AHB; Do đó, tần số của ngoại vi SDRAM chung tần số với AHB, với core của vi điều khiển. Chính vì thế, ta cài đặt tần số của HCLK (ngay sau bộ chia tần của AHB) lên 200MHz như Hình 8:

Hình 8: Cấu hình tần số HCLK

  • Có một lưu ý là chúng ta có thể set tần số này thấp hơn 200 MHz, IC SDRAM có thể chạy ổn định ở tần số thấp hơn tần số tối đa. Chỉ khi ta set cao hơn tần số tối đa thì mới xảy ra lỗi dữ liệu.
  • Tiếp đến ta cấu hình cho ngoại vi FMC:
    • Đầu tiên, ta phải kích hoạt và cấu hình các tham số cơ bản cho ngoại vi FMC như Hình 9:
  • Hình 9: Cấu hình một số tham số cơ bản cho SDRAM
    • Kích hoạt “SDRAM 1” lên, nếu có 2 SDRAM thì phải kích hoạt cả “SDRAM 2”. Việc chọn SDRAM 1 hay 2 sẽ ảnh hưởng đến địa chỉ bắt đầu và kết thúc của SDRAM. Ví dụ: SDRAM 1 có không gian địa chỉ từ 0xC000_0000 đến 0xCFFFFFFF còn SDRAM 2 có không gian địa chỉ từ 0xD000_0000 đến 0xDFFFFFFF [8].
    • Ở “Clock and chip enable”, ta chọn “SDCKE0+SDNE0”. Thông số này người dùng phải kiểm tra Schematic của board phát triển để biết chính xác. Như Schematic của STM32F746-DISCO ở Hình 20 thì chip SDRAM được kết nối với SDCKE0 và SDNE0.
  • Hình 10: chip SDRAM trên board STM32F746-DISCO kết nối với SDCKE0 và SDNE0
    • “Internal bank number: 4 banks”: Thông số này chúng ta kiểm tra trong Datasheet của chip SDRAM, chip SDRAM IS42S32400F có 4 banks
    • “Address: 12 bits”: Tương tự như Bank, cần phải có 12 bits đại diện cho 12 chân địa chỉ kết nối với SDRAM
    • “Data: 16 bits”: chip SDRAM IS42S32400F hỗ trợ 32 bits dữ liệu nhưng 16 chân tương ứng 16 bits cao đã bị nối đất. chính vì thế, ta chỉ có thể để 16 bits.
    • “Byte enable: 16-bit byte enable”: Khi kích hoạt mục này, ta cho phép 2 chân FMC_NBL0/1 ở Hình 20 được sử dụng để mask đi các byte không cần thiết trong 16 bit dữ liệu được truyền đi mỗi lần đọc/ghi. Việc mask bằng phần cứng giúp giảm thời gian và giảm tải cho lõi vi xử lý.
  • Sau khi cấu hình được các tham số cơ bản, chúng ta phải cấu hình chi tiết về địa chỉ, clock và timing như ở Hình 11:


Hình 11: Cấu hình địa chỉ, clock và timing

  • “Number of column address… 8 bits”: Được thể hiện ở Hình 2 phía trên
  • “Number of row address bits 12 bits”: Được thể hiện ở Hình 2 phía trên
  • “CAS latency 2 memory clock cycles”: Ở Hình 7, ta thấy rằng CL cần 2 cycle tối thiểu nên ta chọn “2 memory clock cycles”
  • “SDRAM common clock 2 HCLK clock cycles”: chip SDRAM chạy ở tần số 100MHz trong khi HCLK chúng ta thiết lập ở Hình 8 là 200MHz nên ta phải chọn là “2 HCLK clock cycles” để chia đôi 200MHz ra
  • “SDRAM common burst read Enabled”: Kích hoạt chế độ đọc theo burst. Nghĩa là các từ liên tiếp nhau trong cùng page của chip SDRAM sẽ được đọc mà không cần phải thực hiện lệnh PRECHARGE. Điều này sẽ tăng tốc độ đọc tuần tự vào 1 mảng dữ liệu
  • “SDRAM common read pip… 0 HCLK clock cycles”: Thời gian trễ khi đọc hai words 16 bits liên tiếp ra từ SDRAM. Có thể hiểu đây là thời gian vi điều khiển chờ để SDRAM chuẩn bị dữ liệu khi đọc theo burst. Vì chip SDRAM IS42S32400F không yêu cầu nên ta để là 0
  • “Load mode register to acti… 2”: Đây chính là tMRD; Kết hợp Hình 16, ta để là 2
  • “Exit self-refresh delay 7”: Đây là thời gian delay khi chip SDRAM dừng việc refresh tự động đến khi ta có thể kích hoạt lệnh ACTIVE. Thông số này được ghi trong bảng “AC ELECTRICAL CHARACTERISTICS” của chip IS42S32400F như Hình 22. Tuy nhiên, nhà sản xuất ghi là 70ns thì ta hiểu là 7 chu kì của SDRAM ở tần số SDRAM là 100MHz


Hình 12: Exit self-refresh delay

  • “Self-refresh time 5”: Đây chính là tRAS; Kết hợp Hình 16, ta để là 5
  • “SDRAM common row cycle 6”: Đây chính là tRC; Kết hợp Hình 16, ta để là 6
  • “Write recovery time 3”: Đây chính là tDPL; Kết hợp Hình 16, ta để là 2. Tuy nhiên trong STM32 yêu cầu  tDPL≥ tRAS– tRCD=5 (phía trên) – 2 (phía dưới) = 3
  • “SDRAM common row prec… 2”: Đây chính là tRP; Kết hợp Hình 16, ta để là 2
  • “Row to column delay 2”: Đây chính là tRCD; Kết hợp Hình 16, ta để là 2

*Lưu ý: Phải kiểm tra toàn bộ chân của FMC đã khớp với các chân được vẽ trong Schematic của board chưa. Nếu chưa, phải tiến hành tìm các chân thay thế phù hợp.

3. Khởi tạo module SDRAM trong hàm MX_FMC_Init()

  • Khi sinh code thì STM32CubeIDE-MX sẽ sinh ra một hàm “void MX_FMC_Init(void)”. Hàm này chỉ mới khởi tạo ngoại vi FMC, ta cần phải viết thêm các đoạn mã để ngoại vi FMC khởi tạo các chế độ hoạt động cho SDRAM; Nếu không thì SDRAM sẽ không thể được đọc/ghi.
  • Đoạn mã hàm “void MX_FMC_Init(void)” sau khi sửa lại như bên dưới:

 

 

 

  • Toàn bộ đoạn code trong phần “USER CODE BEGIN/END FMC_Init 1” và “USER CODE BEGIN/END FMC_Init 2” là các đoạn mã ta cần thêm vào.
  • Như ta thấy trong phần  ”USER CODE BEGIN/END FMC_Init 2”, có  steps cần được thực hiện:
  • Step 1: Gửi lệnh kích hoạt clock cho các mảng nhớ trong SDRAM
  • Step 2: Chờ ít nhất là 100μs
  • Step 3: Precharge toàn bộ các hàng trong SDRAM
  • Step 4: Kích hoạt chế độ Auto-Refresh trong SDRAM. Nếu không kích hoạt chế độ này thì phải lập trình cho vi điều khiển để gửi lệnh refresh định kỳ tới SDRAM còn không thì SDRAM sẽ bị mất dữ liệu
  • Step 5: Cấu hình Mode/Burst/CL cho SDRAM
  • Step 6: Cấu hình counter bên trong SDRAM cho chế độ Auto-Refresh ở bước 4. Từ Hình 11, chip IS42S32400F gồm 4096 hàng và dựa vào Datasheet của chip ở Hình 22, thời gian để refresh toàn bộ là 64ms ở nhiệt độ < 70 độ. Ta có (64ms/4096)*100MHz – 20 ≃ 1292

Hình 13: Thời gian để refresh toàn bộ các hàng của SDRAM

  1. Edit file “main.h”

  • Ở bước 4, ta thấy có 1 số macro trong phần “USER CODE BEGIN/END FMC_Init 2” được sử dụng nhưng chưa được khai báo. Vì thế, ta cần phải thêm các macros này vào trong “main.h” như đoạn code dưới đây:

 

 

  • Toàn bộ các macro để thiết lập cấu hình cho SDRAM đều được tham khảo từ Datasheet của chip SDRAM. Nếu board được sử dụng là các kit phát triển của ST thì trong file “main.h” trong các ví dụ của ST đều có phần này.
  1. Cấu hình trong file Linker

  • Đối với mục Memory trong Linker, ta thêm mục SDRAM như đoạn mã dưới đây:

 

 

  • Ta thêm vùng nhớ để sử dụng khi khai báo biến: 

 

Kiểm tra khả năng đọc ghi của SDRAM

  • Ta thêm đoạn code sau vào hàm “main” trong file “main.c”

 

Ta cho debug thử và dừng ngay câu lệnh đầu tiên trong hàm “while(1)” như Hình 23. Sau đó vào mục Memory như Hình 14, ta thấy toàn bộ các byte trong SDRAM đã được set về 1 như mong muốn tại hàm memset.

Hình 14: Chương trình dừng ngày trước hàm lệnh đầu tiên trong while(1)

Hình 15: Toàn bộ các byte trong RAM đều được set về 1

  • Để test đọc/ghi, ta cho chương trình chạy và tiếp tục dừng ở lệnh đầu trong while(1). Vì biến count là biến 8 bits đầu tiên trong SDRAM nên khi chạy qua lệnh “count++”, ta mong muốn byte đầu tiên trong SDRAM được tăng lên 1 đơn vị. Kết quả được cho thấy ở Hình 16


Hình 16: Byte đầu được tăng từ 1 lên 2

Đến đây, chúng ta đã làm quen và thực hiện được việc đọc/ghi trên SDRAM. Phần tiếp theo sau đây sẽ hướng dẫn các bạn mở rộng bộ nhớ Flash ngoài.

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