Saturday, April 12, 2014

Bài 6.(MSP430_Basic) Flash Memory


            Trước hết trước khi bắt đầu các bạn nếu chưa có datasheet của dùng MSP430 thì có thể download tại đây : http://www.ti.com/general/docs/lit/getliterature.tsp?baseLiteratureNumber=slaa559&fileType=pdf.
Lưu ý Datasheet vẫn luôn là tài liệu quan trọng nhất khi bạn tiếp cận bất cứ dòng vi điều khiển nào , nên việc thành thạo tiếng Anh và khả năng đọc Datasheet vẫn là quan trọng nhất. 
Tài liệu được viết cho MSP430G2553,các chip khác có module khác mã sẽ không sử dụng được thư viện đi kèm.

1.  Giới thiệu chung về bộ nhớ Flash
Bài này sẽ hướng dẫn cách sử dụng bộ nhớ Flash của MSP430 làm bộ nhớ dữ liệu không bị mất khi mất điện(tương tự cách dùng EEPROM với các dòng khác).


          Bộ nhớ thông thường có 2 loại là bộ nhớ chỉ đọc ROM và bộ nhớ truy cập ngẫu nhiên RAM,  bộ nhớ Flash là một sự pha trộn của 2 loại bộ nhớ này.
Đặc điểm bộ nhớ Flash là:
+ Chi phí thấp
+ Đọc/Ghi nhanh
+ An toàn
+ Mật độ cao 

Bộ nhớ Flash MSP430 bao gồm nhưng Bít, Byte, địa chỉ từ và khả lập trình. Mỗi module bộ nhớ Flash được tích hợp sẵn bộ điều khiển dùng để điều khiển các hoạt động ghi, xóa bộ nhớ. Bộ điều khiển này gồm 3 bộ: Bộ tạo dao động chủ, bộ phát điện áp cho lập trình, bộ xóa.


Sơ đồ khối bộ nhớ Flash

Chú ý : Điện áp thấp nhất để có thể đọc ghi bộ nhớ Flash là 2.2V . Dưới mức này quá trình đọc ghi sẽ gặp lỗi.



2.  Cấu trúc bộ nhớ Flash

Bộ nhớ Flash của MSP430 được chia thành các phần đoạn , có thể được ghi theo các bit,byte,word nhưng khi xóa thì bắt buộc phải xóa cả Segment . Bộ nhớ flash được phân chia thành các phần bộ nhớ chính và thông tin. Không có sự khác biệt trong hoạt động của các phần bộ nhớ chính bộ nhớ dữ liệu. Lệnh hoặc dữ liệu có thể được đặt trong một trong hai phần. Sự khác biệt giữa hai phần có kích thước phân đoạn và các địa chỉ vật lý. Bộ nhớ thông tin bốn phân đoạn 64-byte. Bộ nhớ chính có một hoặc nhiều 512-byte phân đoạn. Xem bảng dữ liệu thiết bị cụ thể cho bản đồ hoàn chỉnh bộ nhớ của thiết bị.

Các phân đoạn được chia thành các khối:


2.1.              Segment A

Segment A của bộ nhớ dữ liệu có bit khóa riêng so với cái Segment còn lại bằng bit LOCKA trong thanh ghi FCTL1 . Lý do là vì dữ liệu trong Segment A có lưu một số biến mặc định được gọi ra trong một số mà có sẵn ( ví dụ như các biến định tần số DCO) ,vì vậy nó cần được bảo vệ.
-       LOCKA = 1 : Segment A không thể bằng ghi hoặc xóa và tất cả các thông tin bộ nhớ được bảo vệ khỏi tẩy suốt chương trình.
-       LOCKA = 0 : Segmenta có thể bị xóa và viết như bất kỳ phân đoạn bộ nhớ flash khác, và tất cả các ô nhớ thông tin được xoá hoàn toàn.


2.2.              Chế độ hoạt động

Khi khởi động , bộ nhớ flash được cài đặt mặc định ở chế độ đọc . Trong chế độ đọc, bộ nhớ flash không xóa hoặc ghi được, bộ định thời flash và bộ cấp nguồn tắt, và bộ nhớ hoạt động hệt ROM . Bộ nhớ flash MSP430 trong hệ thống lập trình (ISP) mà không cần thêm điện áp bên ngoài. CPU có thể lập trình bộ nhớ flash của riêng mình. Bộ nhớ flash viết và xóa các chế độ được lựa chọn với các BLKWRT, WRT, MERAS, và xóa các bit và là:      
-       Ghi byte hoặc word
-       Ghi 1 block
-       Xóa 1 Segment
-       Xóa bộ nhớ chính (tất cả các phân đoạn bộ nhớ chính)
-       Xóa tất cả (Bộ nhớ chính và bộ nhớ dữ liệu)
Đọc từ hoặc viết vào bộ nhớ flash trong khi nó đang được lập trình hoặc bị xóa đều bị cấm. Nếu CPU thực hiện được yêu cầu trong quá trình viết hoặc xóa, các mã được thực hiện phải có trong bộ nhớ RAM. Bất kỳ bản cập nhật Flash có thể được bắt đầu từ trong bộ nhớ flash hay bộ nhớ RAM.

2.3.              Bộ định thời cho Flash Memory

Bộ định thời của bộ nhớ Flash phải được cấp tần số trong khoảng 257 kHz đến 476 kHz để có thể ghi và xóa được.



Các nguồn lấy xung nhịp có thể là ACLK , MCLK , SMCLK và được cài đặt chia tần để được tần số fFTG phù hợp . Dù cho CPU ở bất cứ chế độ nào ,khi bộ nhớ Flash đang trong chế độ ghi hoặc xóa đều không bị ảnh hưởng cho đến khi hoạt động này hoàn tất ( tức là không thể vô hiệu hóa các nguồn xung cấp cho Flash ).


2.4.              Chế độ xóa Flash Memory


Mức độ xóa của một bit bộ nhớ flash là 1. Mỗi bit có thể được lập trình 1->0 độc lập nhưng để lập trình lại 0->1 đòi hỏi phải xóa . Phạm vi xóa nhỏ nhất là 1 segment . Có ba chế độ xóa lựa chọn với các bit ERASE và MERAS liệt kê trong Bảng 7-1 .


Sauk hi set bit ERASE ,bất kỳ lệnh ghi nào vào dải địa chỉ sẽ kích hoạt bộ cấp điện và quá trình xóa diễn ra. Hình 7-4 cho thấy thời gian chu kỳ xóa . Bit BUSY được thiết lập ngay lập tức sau khi lệnh Write được gọi và tồn tại đến hết quá trình xóa  . BUSY, MERAS , và ERASE sẽ được tự động xóa khi chu kỳ hoàn thành . Thời gian chu kỳ xóa không phụ thuộc vào số lượng bộ nhớ flash hiện trên một thiết bị . Thời gian xóa  là tương đương cho tất cả thiết bị.

Lệnh ghi ra ngoài vùng bộ nhớ dữ liệu sẽ không có tác dụng gì và toàn bộ quá trình bị bỏ qua.

2.5.              Các thanh ghi điều khiển Flash Memory


Để có thể đọc ghi được bộ nhớ flash , đơn giản thì chúng ta chỉ cần quan tâm đến thanh ghi :
-       FCTL1 ( WRT , ERASE )
-       FCTL2
-       FCTL3 (LOCKA , LOCK, BUSY )

Thanh ghi FCTL1

Thanh ghi FCTL2

Thanh ghi FCTL3



2.6.              Ghi 1 byte vào Flash Memory


Theo như ở trên , để ghi được 1 byte vào bộ nhớ , chúng ta cần làm một vài thủ tục sau:
-       Xóa toàn bộ segment chứa byte đó,để giữ lại dữ liệu của các byte khác trong segment đó,chúng ta có thể đọc toàn bộ segment đó ra trước ghi xóa,và ghi lại sau khi ghi byte cần lưu vào flash.Để xóa được segment chúng ta cần set bit ERASE =1,sau đó ghi 1 byte bất kỳ vào vị trí bất kỳ trên segment.
-       Chờ cho đến khi quá trình xóa hoàn tất.
-       Set cờ WRT cho phép ghi
-       Ghi dữ liệu vào vị trí cần lưu
-       Clear cờ LOCK để không làm thay đổi dữ liệu trong flash

Dưới đây là minh họa hàm ghi 1 byte vào segment C , có giữ lại các byte khác trong segment.


void flash_write_segmentC (unsigned int value, unsigned char position)
{
    char *Flash_ptr;                          // Flash pointer
    unsigned char i=0;
    char Data_temp[64];
    //Ghi 64 byte cua segment ra truoc
    Flash_ptr = (char *) 0x1040;    // Initialize Flash segment C pointer
    for(i=0;i<64;i++) Data_temp[i]= *Flash_ptr++;// copy value segment C


    Flash_ptr = (char *) 0x1040;              // Initialize Flash pointer
    FCTL1 = FWKEY +ERASE;                    // Set Erase bit
    FCTL3 = FWKEY;                           // Clear Lock bit
    *Flash_ptr = 0;             // Dummy write to erase Flash segment

    while(FCTL3&BUSY);        //Wait for complete erase
    FCTL1 = FWKEY + WRT;        // Set WRT bit for write operation

    for(i=0;i<64;i++)
    {
      if(i==position)*Flash_ptr++ =value;
      else *Flash_ptr++ = Data_temp[i];   // Write value to flash
      }
    FCTL1 = FWKEY;                            // Clear WRT bit
    FCTL3 = FWKEY +LOCK;                    // Set LOCK bit
}



2.7.              Đọc 1 byte vào Flash Memory

Việc đọc bộ nhớ Flash đơn giản hơn nhiều so với việc ghi,bạn chỉ đơn giản là dùng con trỏ đọc địa chỉ của đúng byte Flash đó là được.
VD:

void flash_read_segmentC (unsigned int *var, unsigned char position)
{
      char *Flash_ptr;              // Segment C pointer

      Flash_ptr = (char *) 0x1040;   // Initialize Flash segment C pointer
      Flash_ptr +=  position;       // Jump to desired address
      *var = *Flash_ptr;          // copy value segment C to variable
}

Đây là thư viện Flash.h các dòng MSP430 .Chú ý là không nên tùy tiện sử dụng Segment A vì trong này lưu trữ nhiều tham số quan trọng của VĐK .
Download Project tại đây : Đọc ghi bộ nhớ Flash
Chúc các bạn thành công 

Bài tiếp theo :Bài 7.(MSP430_Basic) ADC10

14 comments:

  1. em chào anh !! em muốn ghi một mảng số vào trong flash rồi gọi lần lượt ra LCD đề test thì làm sao ạ !! em cảm ơn anh giúp đỡ !!



    ReplyDelete
    Replies
    1. Trong thư viện Flash.h có hàm Flash_Write_Block(...) và Flash_Read_Block đó bạn dùng để đọc ghi 1 mảng

      Delete
  2. em muốn xuất giá trị trong flash trong code của anh ra LCD de test dùng lệnh sau
    Flash_Read_Block(SegmentC,Temp,0,5);

    lcd_printf(buff,"C0:%d C1:%d C2:%d C3:%d C4:%d",Temp[0],Temp[1],Temp[2],Temp[3],Temp[4]);

    nhưng ko đc , mong anh giúp đỡ ạ !!

    ReplyDelete
    Replies
    1. Như anh thì anh để tần số hoạt động 1Mhz,nói chung là phải để tần số nuôi flash trong khoảng 500Khz đến 900Khz,mà nói báo lỗi gì em cho lên đây xem

      Delete
  3. không báo lỗi gì anh ạ !! em muốn hỏi cách hiển thị giá trị trong thanh ghi lên LCD thay bằng qua UART SAO anh ạ !!

    ReplyDelete
    Replies
    1. À thế mà không nói trước,em download thư viện LCD trong mục MSP430_Library ý có thư viện LCD đấy.có thể viết
      while(1)
      {
      LCD_Home();
      sprintf (buff,"C0:%d C1:%d ",Temp[0],Temp[1]);
      LCD_PrintString(buff);
      _delay_cycles(100000);
      }
      //Chú ý là để trong vòng while để hiển thị được liên tục,và khai báo stdio.h thì mới dùng dc sprintf()
      Em nên tìm hiểu kỹ về hiển thị LCD chứ còn về bộ nhớ thì Flash_Read_Block(SegmentC,Temp,0,5); là xong rồi

      Delete
  4. thanks anh !! em làm được rồi ạ !! a cho em hỏi thêm có cách nào để xem trực tiếp giá trị mà đã ghi vào thanh ghi trực tiếp trên CCS không ạ !!

    ReplyDelete
    Replies
    1. Em chạy debug rồi pause lại,trỏ chuột vào thanh ghi nào trong code nó hiện ra địa chỉ và cả giá trị thanh ghi đấy ở thời điểm hiện tại

      Delete
  5. anh giải thích giúp em các con số 5,4,12,7,8 trông đây là gì ạ
    Flash_Write_Byte(SegmentD,5, 0);
    Flash_Write_Byte(SegmentD,4, 1);
    Flash_Write_Byte(SegmentD,12, 2);
    Flash_Write_Byte(SegmentD,7, 3);
    Flash_Write_Byte(SegmentD,8, 4);

    ReplyDelete
    Replies
    1. Nó là giá trị cần ghi vào các vị trí trong segmentD ở vị trí 0 1 2 3 4.Trong code có chú thích rõ ràng rồi mà em

      Delete
  6. mình muốn ghi 1 mảng các giá trị vào flash thì làm như thế nào nhỉ ? như 1 mảng số điện thoại 01225413069 thì đọan code đó như thế nào AD, với hàm Flash_Read_Block() ak.

    ReplyDelete
    Replies
    1. Bạn dùng Hàm Flash_Write_Block nhé,ở trên mình đã nói rồi đấy,trong code cũng có giải thích rồi

      Delete
    2. ý mình là không biết cách đưa các ham số vào hàm. Minh có thể dùng : Flash_Write_Byte(SegmentD,5, 0);
      Flash_Write_Byte(SegmentD,0, 1);
      Flash_Write_Byte(SegmentD,1, 2);
      Flash_Write_Byte(SegmentD,2, 3);
      Flash_Write_Byte(SegmentD,2, 4);
      Flash_Write_Byte(SegmentD,5, 5);
      Flash_Write_Byte(SegmentD,4, 6);
      Flash_Write_Byte(SegmentD,1, 7);
      Flash_Write_Byte(SegmentD,3, 8);
      Flash_Write_Byte(SegmentD,0, 9);
      Flash_Write_Byte(SegmentD,6, 10);
      Flash_Write_Byte(SegmentD,9, 11);

      để lưu số điện thoại được không Văn Thận Phạm :)

      Delete
    3. Chán quá.bạn có thể tạo 1 mảng abc[10] chẳng hạn .Gán abc[0]=5;abc[1]=0;abc[2]=1;...v v sau đó dùng hàm Flash_Write_Block(SegmentD,&abc,5,5); như thế chẳng hạn

      Delete

END COMMENT FACEBOOK-->