Thiết lập Fuse Bits

( 29 Votes )
Nội dung Các bài cần tham khảo trước
  1. JTAGEN.
  2. OCDEN.
  3. BODEN.
  4. EESAVE
  5. BOOT LOADER
  6. NGUỒN XUNG GIỮ NHỊP

 

      AVR có sẵn một số mạch điện và các thiết bị hỗ trợ bên trong, việc “điều khiển” các mạch điện này được thực hiện thông qua các Fuse bits. Ví dụ bên trong các chip AVR có bộ tạo dao động cho chip, nếu muốn sử dụng hoặc vô hiệu hóa bộ tạo dao động này chúng ta sẽ set các Fuse bits điều khiển nguồn xung clock(cụ thể ở phần sau). Như thế, Fuse bits cũng giống như các “cầu chì” hay các “công  tắc cứng”  nối AVR với các mạch điện hỗ trợ. Vì là các “công tắc cứng” nên chúng phải được set riêng biệt, không set được bằng lệnh "mềm". 

      Mỗi loại AVR có số lượng mạch điện hỗ trợ khác nhau và vì thế số lượng Fuse bits sẽ khác nhau. Vị trí các Fuse bits cũng khác nhau trên mỗi dòng chip tuy nhiên tên gọi thì như nhau. Tôi sẽ dùng chip ATmega32 làm minh họa. Chip ATmega32 có 16 Fuse bits được bố trí trong 2 byte gọi là “Fuse High Byte” và “Fuse Low Byte”. Vị trí các Fuse bits không quan trọng (vì chúng ta dùng phần mềm hỗ trợ set từng Fuse bit) nhưng tên gọi và chức năng thì cần khảo sát. Bảng 1 tóm tắt các bits trong Fuse High Byte và bảng 2 tóm tắt các bits trong Fuse Low Byte.

Bảng 1. Fuse High Byte 

ngắt  

Bảng 2. Fuse Low Byte 

ngắt

     Đa số các chương trình nạp chip đều hỗ trợ nạp Fuse bits. Các Fuse được nạp độc lập đối với file chương trình. Các phần mềm nạp như PonyProg, phần mềm nạp trong CodevisionAVR, Bascom, ICCAVR…hỗ trợ set từng Fuse bit một trong khi một số chương trình như avrdude chỉ hỗ trợ nạp các byte Fuse, nếu muốn sử dụng các chương trình nạp này để nạp Fuse bạn cần tính toán giá trị 2 byte Fuse trước. Một chú ý rất quan trọng là đối với các Fuse bits, gán giá trị  0 cho 1 Fuse bit đồng nghĩa với Fuse bit đó được lập trình (programmed), trong khi 1 nghĩa là không được lập trình (unprogrammed).

     Tôi sẽ sử dụng phần mềm PonyProg để làm minh họa nạp Fuse bits cho chip ATmega32. Trước khi nạp Fuse bits bạn cần chọn device và loại mạch nạp trong PonyProg (xem lại bài Mạch nạp). Để nạp Fuse bits bạn hãy chọn menu “Command/Security and Configuration Bits…” hoặc nhấn “Ctrl+S” (mạch nạp phải được nối sẵn với máy tính và mạch AVR). Nhấn nút “Read” để đọc các cấu hình Fuse bits trên chip của bạn, nếu đây là lần đầu tiên chip ATmega32 của bạn được nạp Fuse bits thì bạn sẽ thu được kết quả cấu hình các Fuse bits như trong hình 1. 

ngắt

Hình 1. Cấu hình Fuse bits mặc định trên chip ATmega32. 

       Chúng ta sẽ lần lượt khảo sát các Fuse bit theo nhóm chức năng của chúng. 

      1. JTAGEN (JTAG Enable): trên AVR có tích hợp sẵn bộ JTAG, đó là một module giao tiếp với phần cứng của chip. Nhìn chung, JTAG thường được dùng để kiểm tra hoạt động của chip. Trên AVR, JTAG có thể được dùng để nạp chương trình nhưng phổ biến hơn là dùng để debug lỗi chương trình (gỡ rối chương trình). Module JTAG làm việc thông qua 4 chân TCK, TMS, TDO và TDI, trên chip ATmega32 4 chân lần lần lượt là PC2, PC3, PC4 và PC5. Theo mặc định JTAG được kích hoạt, bit JTAGEN=0 (programmed) như trong hình  1. Vì thế với các chip ATmega32 mới mua về, các chân PC2:5 trên PORTC có thể không sử dụng để xuất nhập thông thường được. Nếu bạn không muốn sử dụng chức năng Debug trực tiếp trên chip thì hãy uncheck bit JTAGEN(uncheck tương đương unprogrammed, tương đương JTAGEN=1) để dùng các chân JTAG như các chân xuất nhập thông thường. 

      2. OCDEN (On Chip Debug Enable): như đã trình bày ở trên, AVR cho phép chúng ta gỡ rối chương trình trực tiếp trên chip thông qua module JTAG. Trong khi bit JTAGEN cho phép kích hoạt JTAG thì bit OCDEN cho phép thực hiện Debug trên chip (Nghĩa là cho dù đã kích hoạt JTAG bạn chưa thể dùng chức năng debug nếu chưa kích hoạt OCDEN). Nếu bạn có một mạch Debug cho AVR như mạch JTAG ICE của Atmel (xem bài Debug với JTAG ICE) và bạn muốn debug chương trình thì hãy set bit OCDEN bằng 0 (check vào ô OCDEN). Bạn cần nhớ rằng, khi lập trình cho bit OCDEN thì AVR sẽ hoạt động trong mode Debug, trong mode này chip  sẽ ở trong trạng thái “ngủ” (Sleep mode), bạn chỉ có thể thực hiện Debug mà không thể chạy chương trình thật. Theo mặc định, OCDEN không được lập trình và chế độ Debug được vô hiệu hóa. Lời khuyên là bạn nên để bit này unprogrammed trước khi đưa chip vào sử dụng. (đừng đụng vào bit này nếu bạn không có ý định Debug trên chip).

     3. BODEN (Brown-Out Detection Enable) và BODLEVEL(BOD Level): AVR có sẵn một mạch điện Brown-Out Detection, hiểu nôm na là mạch phát hiện sụt điện áp nguồn. Nếu fuse BODEN được lập trình  thì mạch BOD được kích hoạt, khi đó fuse bit BODLEVEL chọn mức điện áp của BOD (mức điện áp dùng so sánh sụt nguồn). Nếu BODLEVEL=1 (unprogrammed) thì mức điện áp BOD mặc định là 2.7V, ngược lại nếu BODLEVEL được lập trình thì mức điện áp BOD là 4.0V. Khi mạch BOD được sử dụng, nếu điện áp VCC giảm xuống thấp hơn mức điện áp BOD thì 1 Reset BOD xảy ra. Nếu không thật sự cần thiết hãy để các bit này không được lập trình như mặc định. Hình 2 mô tả một sự kiện BOD trên AVR.    

Hình 2. Sự kiện BOD trên AVR. 

      4. EESAVE (EEPROM Erase SAVE): nếu bit EESAVE được lập trình (bằng 0), thì  bộ nhớ EEPROM sẽ không bị xóa khi xóa chip, ngược lại EESAVE =1 (unprogrammed) thì EEPROM sẽ bị xóa theo chip.

      5. BOOT LOADER: đây là một tính năng rất hay trên các chip AVR mới (chú ý không phải dòng AVR nào cũng có Boot Loader), Boot Loader là phần bộ nhớ chương trình được kích hoạt đầu tiên khi khởi động chip. Boot Loader trên các chip AVR được bố trí phía dưới của bộ nhớ chương trình (xem lại bài 2, cấu trúc AVR). Boot Loader thường được sử dụng để ghi hoặc đọc nội dung bộ nhớ chương trình, vì thế ứng dụng phổ biến nhất của nó là update chương trình cho chip một một cách nhanh chóng mà không cần mạch nạp. Cơ chế như sau: 

 -Trước hết chúng ta cần có 1 chương trình Boot Loader được nạp sẵn trong phần bộ nhớ Boot Loader (phía dưới bộ nhớ chương trình). Chương trình này có khả năng giao tiếp với máy tính (thông qua UART chẳng hạn) và đọc, ghi bộ nhớ chương trình của chip.

 -Khi cần update chương trình mới cho AVR, trên máy tính có 1 chương trình giao tiếp với Boot Loader, kết nối AVR với máy tính, chương trình trên máy tính sẽ gởi nội dung cần update cho AVR, chương trình Boot Loader sẽ đọc nội dung này và ghi vào bộ nhớ chương trình của AVR. Bằng cách này chúng ta đã “nạp” chương trình cho AVR mà không cần dùng mạch nạp.

      Nạp chương trình bằng Boot Loader cho phép khách hàng của bạn tự cập nhật các chức năng mới mà không cần trao chip cho bạn. Sử dụng hay không sử dụng Boot Loader sẽ được xác lập thông qua các Fuse bits BOOTRST, BOOTSZ1BOOTSZ0. 

-BOOTRST (Select Reset Vector) : Nếu Fuse bit BOOTRST không được lập trình (bằng 1) thì khi vừa khởi động chip, con trỏ chương trình sẽ nhảy đến vị trí đầu tiên trong chương trình (0x0000) để lần lượt thực thi phần chương trình như thông thường. Nếu BOOTRST được lập trình (bằng 0) thì vị trí Reset là địa chỉ đầu của phần Boot Loader, không phải địa chỉ 0x0000 như thường lệ. Khi đó phần chương trình trong Boot Loader sẽ được thực thi thay cho chương trình chính phía trên (xem hình 3). 

Hình 3. Ảnh hưởng của Fuse bit BOOTRST.

-BOOTSZ1 BOOTSZ0 (Select Boot Size): kích thước phần bộ nhớ dành cho Boot Loader không cố định, nếu Boot Loader không được kích hoạt (fuse BOOTRST=1) thì toàn bộ bộ nhớ chương trình dành cho chương trình chính. Khi Boot Loader được kích hoạt, 2 Fuse bits BOOTSZ1 và BOOTSZ0 sẽ quyết định kích thước Boot Loader. Bảng 3 tóm tắt các kích thước của phần Boot Loader phụ thuộc vào 2 bit BOOTSZ1:0. Chú ý là kích thước tính theo INSTRUCTION WORD, với AVR 1 INSTRUCTION WORD = 2 bytes. Phải nhắc lại đối với Fuse bits, giá trị 1 nghĩa là không được lập trình (không check trong PonyProg). Nếu bit BOOTRST không được lập trình thì 2 bit BOOTSZ không có tác dụng.

Bảng 3. Kích thước Boot Loader.

      Trong các ứng dụng lập trình thông thường, Boot Loader không được quan tâm, vì thế tối khuyên bạn nên để các Fuse bit BOOTRST, BOOTSZ1:0 như mặc định, khi nào cần sử dụng tôi sẽ nói rõ (xem bài Debug với mạch JTAG ICE).

      6. Chọn Nguồn Xung giữ nhịp và thời gian khởi động (start-up times): Đây là phần rất được quan tâm khi set Fuse bits. Có đến 7 Fuse bits tham gia vào việc này đó là 4 bits CKSEL3:0, 2 bis SUT1:0 và bit CKOPT. Trong đó 2 bit SUT1:0 chủ yếu dùng để chọn thời gian khởi động, phần này không ảnh hưởng nhiều trong hầu hết các trường hợp (ít nhất là các ví dụ trong Cùng học AVR) vì thế tôi sẽ bỏ qua, chúng ta để 2 fuse bits  như mặc định. Nếu start-up time thật sự ảnh hưởng đến chương trình của bạn, bạn hãy tham khảo thêm phần “System Clock and Clock Option” trong datasheet của chip. Phần này tôi chủ yếu trình bày cách chọn nguồn xung giữ nhịp cho chip.

      Có tất cả 5 loại nguồn xung giữ nhịp chính cho chip nhưng để đơn giản chúng ta chỉ xét 2 trường hợp là dùng nguồn thạch anh ngoài và dùng xung giữ nhịp được tạo bởi mạch RC trong chip. 

      Xung giữ nhịp trong chip (xung nội): Hầu hết các chip AVR được trang bị 1 mạch tạo xung giữ nhịp RC bên trong, nếu sử dụng nguồn xung giự nhịp này chúng ta có thể bỏ qua mạch tạo xung bên ngoài. Nguồn xung giữ nhịp được tạo ra bên trong chip được cố định ở 1 trong 4 mức : 1MHz, 2 MHz, 4 Mhz và 8 MHz. Các Fuse bits CKSEL3:0 quyết định việc chọn nguồn xung này. Bảng 4 tóm tắt cách phối hợp các Fuse bits CKSEL để chọn nguồn xung nội.

Bảng 4. Chọn xung giữ nhịp nội bằng các Fuse bits CKSEL.

(Nomial frequency: tần số danh nghĩa, giá trị thực có thể khác do sai số)

     Đối với chip ATmega32, nguồn xung nội 1MHz được set mặc định trên các chip mới. Xem lại hình 1 bạn thấy CKSEL3=0 (được checked), CKSEL2=0 (được checked), CKSEL1=0 (được checked), CKSEL0=1 (không check). Các hình 4, 5, 6 và 7 bên dưới gợi ý bạn cách chọn nguồn xung nội bằng phần mềm nạp PonyProg, chú ý sau khi chọn các bits bạn phải nhấn bút “Write” để ghi vào chip. 

Hình 4. Chọn nguồn xung nội 1MHz (đồng thời tắt JTAG, Boot Loader, BOD). 

Hình 5. Chọn nguồn xung nội 2MHz (đồng thời tắt JTAG, Boot Loader, BOD). 

Hình 6. Chọn nguồn xung nội 4MHz (đồng thời tắt JTAG, Boot Loader, BOD). 

Hình 7. Chọn nguồn xung nội 8MHz (đồng thời tắt JTAG, Boot Loader, BOD). 

       Xung giữ nhịp từ mạch thạch anh bên ngoài (Crystal): dùng xung nội có nhược điểm là tấn số xung đã được giữ cố định trong 4 mức và tấn số cao nhất có thể đạt là 8MHz trong khi AVR cho phép làm việc ở 16Mhz, mặc khác sai số cũng tương đối lớn khi xùng xung nội. Dùng thạch anh để tạo xung giữ nhịp là một giải pháp tốt, có thể tạo một mạch thạch anh đơn giản và nối với 2 chân XTAL1 và XTAL2 của AVR như trong hình 8. 

Hình 8. Mạch tạo xung ngoài bằng thạch anh. 

     Để “báo” cho AVR biết là chúng ta muốn sử dụng thạch anh ngoài làm mạch tạo xung, hãy set các Fuse bits CKSEL3:0 thành 1 trong 2 giá trị: 1111 hoặc 1010 (nhị phân). Trong trường hợp này, Fuse bit CKOPT có tác dụng chọn giữa 2 chế độ khuyếch đại, chế độ CKOPT = 0 (programmed)  thích hợp với thạch anh có tần số lớn nhất là 16MHz và CKOPT=1 (unprorgammed) khi tần số thạch anh nhỏ hơn hoặc bằng 8MHz. Các hình 9 và 10 gợi ý cách set Fuse bits để chọn nguồn xung nhịp là mạch thạch anh ngoài với  các tần số lớn nhất 8MHz và lớn nhất 16MHz. 

Hình 9. Chọn xung giữ nhịp từ thạch anh ngoài với tần số lớn nhất là 8MHz. 

Hình 10. Chọn xung giữ nhịp từ thạch anh ngoài với tần số lớn nhất là 16MHz. 

    Sau khi đã chọn các Fuse bits, việc cuối cùng và rất quan trọng là ghi các Fuse bits này vào chuip bằng cách nhấn nút “Write” (PonyProg).

    Đối với các chương trình nạp chip khác, Fuse bits cũng được set tương tự.