Do It Now

Chỉ tập trung những người có đầu óc thông minh ngồi lại với nhau và suy nghĩ không thôi thì doanh nghiệp không thể lớn mạnh được. Phải hành động. __Chung Ju Yung__

Monday, June 20, 2016

Kỹ năng Đi Trước Đam mê


Rảnh rỗi sinh nông nổi, cuối tuần ngồi nhà cày cuốc hết cuốn sách "Kỹ năng đi trước đam mê" của Cal Newport do TGM books xuất bản. Cuốn sách đã trả lời khá nhiều trăn trở của bản thân từ lúc học năm cuối cho đến tận thời điểm bây giờ. Hiện tại, mình đã nghỉ việc (một công việc, nơi làm việc mà mình từng rất yêu thích) được 2 tháng 20 ngày :D. Lí do là mình nghĩ nếu tiếp tục, nó sẽ hút "kiệt" nhiệt huyết "chiến đấu" của mình. Mình cũng chưa sẵn sàng tìm một bến đỗ mới bởi bản thân cũng chưa rõ thực sự  mình muốn gì về công việc tiếp theo. Làm chủ? Tìm bến đỗ mới tiếp tục nghề nghiệp mình đã chọn? Rẽ sang một hướng khác thú vị hơn? Hay ở đâu có tiền thì ta lao tới :)). 

Overview về cuốn sách

Cuốn sách bao gồm 5 phần viết về 4 quy tắc và phần cuối tổng kết của tác giả

- Quy tắc 1: Đừng bao giờ theo đuổi đam mê 

Quy tắc này có cái tên khá là gọi đòn :)). Nó động chạm đến cái mọi người hay nghĩ về đam mê hay còn gọi là "thuyết đam mê".  Tác giả cho rằng "theo đuổi đam mê" là một lời khuyên tồi tệ. Bởi vì, Mọi người hầu hết không có những đam mê tồn tại từ trước, đang chờ đưọc khám phá và gắn liền với một sự nghiệp nào đó. Tác giả tin rằng những trải nghiệm khiến cho cuộc sống của bạn trở nên thú vị không nhất thiết phải đi theo tiếng gọi

- Quy tắc 2: Hãy trở nên giỏi đến mức họ không thể phớt lờ bạn

Trong phần này, tác giả đi tìm kiếm điều thực sự quan trọng trong việc tạo nên một công việc yêu thích. Câu trả lời là nếu như bạn không nỗ lực để trở nên "giỏi đến mực họ không ai dám phớt lờ bạn" thì nhiều khả năng bạn sẽ không thể yêu thích công việc mình làm. Bạn phải tích lũy đưọc vốn liếng sự nghiệp (những kĩ năng xuất sắc trong công việc) để sau này đánh đổi lấy những điều thú vị. Điều này sẽ đưọc làm rõ hơn trong quy tắc 3.

- Quy tắc 3:  Từ chối cơ hội thăng tiến (tầm quan trọng của sự kiểm soát)

Quy tắc này nói về việc công việc của bạn sẽ là mơ ước nếu như bạn kiểm soát nó (tức là bạn có quyền tự chủ trong công việc của mình). Điều này sẽ có được chỉ khi bạn tích lũy đưọc đủ vốn liếng sự nghiệp. Nó giống như kiểu "người thành công nói cái gì chả đúng " (mình nghĩ thế :))

- Quy tắc 4:Nghĩ nhỏ, làm lớn (tầm quan trọng của sứ mệnh) 

Sứ mệnh sự nghiệp là một mục đích trong đời sống công việc. Sứ mệnh sẽ xuyên suốt, dẫn đường cho bạn trong suốt sự nghiệp

- Kết luận 

Trong phần này tác giả trình bày lại cách phương pháp mà ông áp dụng các quy tắc này trong công việc. Bạn sẽ tìm thấy những lời khuyên về chọn lựa công việc như thế nào vì "không phải gà vịt nào cũng liên hoan được" , làm thế nào để "giỏi đến mức không ai dám phớt lờ bạn", hay vận dụng việc kiểm soát và sứ mệnh nghề nghiệp như thế nào trong các quyết định.

Cảm nhận về cuốn sách
"Hãy ngừng lo nghĩ về những gì bạn muốn làm (và những gì thế giới nợ bạn) mà thay vào đó, hãy bắt đầu tạo ra một thứ có ý nghĩa rồi trao tặng cho thế giới. Cal thật sự gửi gắm thông điệp này qua quyển sách" _SETH GODIN, tác giả quyển Linchpin
Ý kiến cá nhân
Mình thấy cuốn sách này khá hay và đáng để tham khảo cho những ai đang "hoang mang" trên con đường sự nghiệp. "LÀM VIỆC ĐÚNG HƠN LÀ TÌM ĐÚNG VIỆC"  là thông điệp mà tác giả muốn truyền tải qua cuốn sách. Tỉnh dậy thôi!


Sunday, June 19, 2016

Tư duy hướng đối tượng (OOP) từ góc nhìn embedded C Developer

    Xuất thân từ điện-điện tử, mình chủ yếu lập trình với vi điều khiển sử dụng ngôn ngữ C (lập trình thủ tục), quen với việc sử dụng các hàm để giải quyết vấn đề. Nhược điểm của cách làm này là nếu quản lý không tốt, không chia tách thành được các module độc lập thì khó control đưọc project,  dễ phát sinh bug. Do đó mình tìm hiểu thêm về tư duy hướng đối tượng để có cách quản lý chương tình tốt hơn

 Định nghĩa

   + Tư duy lập trình hướng đối tượng là tư duy lập trình mà theo đó tất cả mọi thứ có thể định nghĩa được thuộc tính (properties) và phương thức (method) đều được coi là các đối tượng.
  + Như vậy tư duy lập trình hướng đối tượng là cách nhìn nhận một sự vật, sự việc dưới dạng một đối tượng (bao gồm thuộc tính và hành vi ). Thuộc tính của đối tượng sở hữu có thể phơi ra hoặc đưọc ẩn đi, hành vi có thể do đối tượng tự thực hiện hoặc đối tượng khác tác động vào. Ví dụ con người có thuộc tính (mắt, mũi, mồm,..) và các hành vi (ăn, ngủ, đi vệ sinh :D, đánh nhau). Một cái cây có thuộc tính (lá, rễ, cao, đường kính thân) và hành vi (quang hợp, chặt cây,...)

Phân tích

Trừu tượng hóa đối tượng
+ Ngôn ngữ lập trình bản chất chỉ là một công cụ để giải quyết một vấn đề thực tế -> khi thiết kế ta phải nhìn từ góc độ thực tế hay nói cách khác đó là trừu tượng hóa (mô hình hóa) sự vật, sự việc cụ thể. Trừu tượng hóa là tìm các thuộc tính và hành vi của đối tượng từ thực tế và mô tả lại bằng ngôn ngữ lập trình
+ Phân tích module gsm
- Thuộc tính

  • loại module (SIM900, HL6528, SIM908,..)
  • hãng sản xuất (SIMCOM, Serria Wireless)
  • cường độ sóng
  • nhà mạng
  • có đăng kí 3g không
  • sim bị khóa không
- Hành vi

  • gọi
  • nhắn tin
  • bật 3G/GPRS
  • Truy cập website qua http request
  • gửi/nhận dữ liệu qua tcp
  • gửi/nhận dữ liệu qua udp
  • download file từ ftp sever

Class và đối tượng
  + Sau khi trừu tượng hóa đối tượng thực tế ta sẽ có một class bằng cách tìm những loại thuộc tính và hành vi giống nhau nhất của các đối tượng gom thành class. 
  + Phân tích ví dụ về module gsm ở trên
     Module gsm có nhiều loại, có loại chỉ có thể nhắn tin gọi điện (trong "stupid" phone), có loại có khả năng kết nối GPRS, có loại cao hơn có kết nối 3G/4G ("smart phone"). Tuy nhiên tất cả đều có tính năng GSM (nhắn tin, gọi điện). Do đó ta sẽ tạo một class STUPID_GSM
  - Thuộc tính

  •   cường độ sóng
  •   nhà mạng
  •   các cell mà module gsm nhìn thấy
  •   thuộc tính liên quan đến SIM (liên quan đến SIM ta cũng có thể tạo một class SIM)
  - Hành vi

  •   gọi điện
  •   nhắn tin đi
  •   đọc tin nhắn đến
      Với các module gsm có thêm tính năng GPRS, 3G/4G thì ta sẽ tạo một class SMART_GSM kế thừa từ class STUPID_GSM tức là có đầy đủ thuộc tính và hành vi của class STUPID_GSM ngoài ra thêm một số thuộc tính và hành vi về data
  - Thuộc tính

  •   Loại kết nối (GPRS/3G/4G)
  - Hành vi

  •   http request/http response
  •   tcp client
  •   udp client
  •   ftp client
  + Đối tượng là một thể hiện của class trong thực tế ví dụ như class SMART_GSM sẽ có các đối tượng như SIM900, HL6528,,...Trong một project nếu chúng ta sử dụng một module gsm chỉ có nhắn tin, gọi điện và một module gsm có cả data  thì chúng ta cần khởi tạo 2 đối tượng

  •   STUPID_GSM  SIMxx;
  •   SMART_GSM  SIM900;


Tổng kết

Hướng đối tượng là tính năng của một số ngôn ngữ C++, C#,.. nhưng chúng ta cũng có thể áp dụng tư duy hướng đối tượng trong lập trình C để có thể quản lý các thành phần ngoại vi tốt hơn bằng cách coi mỗi ngoại vi như một đối tượng (SD card, gsm module, LAN module đều có thể coi như những đối tượng) và sử dụng kiểu cấu trúc struct là công cụ để thể hiện thay cho class

Sunday, June 12, 2016

Sử dụng từ khóa Volatile trong C như thế nào?



Bạn lập trình nhúng C?  Bạn đã gặp trường hợp khi build với chế độ debug thì code chạy đúng , nhưng khi bạn build release ( hoặc build để tối ưu) thì chương trình lại chạy lung ta lung tung chưa? Nếu bạn đã gặp rồi thì vấn đề có thể do bạn không khai báo volatile cho biến. Bài viết dưới đây sẽ cho bạn biết khi nào cần khai báo volatile.

Volatile là gì?

Volatile có nghĩa là không dự đoán được. Một biến sử dụng với volatile qualifier có nghĩa là nói với compiler là biến này có thể sẽ được thay đổi ở bất kì chỗ nào

Cú pháp khai báo
- Biến: int volatile var = 0;
- Con trỏ: int volatile *ptr;

Sử dụng Volatile

Chúng ta sẽ sử dụng volatile khi khai báo biến trong các trường hợp dưới đây:
- Con trỏ trỏ tới địa chỉ của các thanh ghi trong bộ nhớ (Memory - mapped peripheral register)
- Biến toàn cục dùng chung cả trong và ngoài ngắt (ISR Routine)
- Biến toàn cục dùng chung trong nhiều task trong ứng dụng multi-thread

Memory - mapped peripheral register

Xem xét đoạn code sau
//gan con tro ptr tới thanh ghi trạng thái có địa chỉ 0x1234
uint32_t *ptr = (uint32_t *) (0x1234);
//vòng lặp kiểm tra nếu giá trị thanh ghi khác 0 thì thoát
while (*ptr == 0);

Dòng code đầu tiên khai báo con trỏ ptr. Giả sử giá trị thanh ghi tại thời điểm này là 0 tức *ptr = 0. Khi build tối ưu, compiler có thể sẽ không nhìn thấy giá trị *ptr được sửa ở đâu nữa nên nó sẽ coi như đây là vòng lặp vô hạn luôn (do giá trị *ptr lúc đầu = 0). Do đó để tránh trường hợp trên chúng ta cần khai báo volatile cho biến con trỏ ptr


uint32_t volatile *ptr;


Nếu bạn mở file .h định nghĩa các thanh ghi của một vi điều khiển sẽ thấy họ sử dụng từ khóa volatile


ISR Routine

Xem xét đoạn code
uint8_t flag  = 0;
void main(void) {
while (!flag) {
//do something
}
}

void ISR_UART(void) {

//nhan ki tu tu UART
char c = UART_GetChar();
if (c = 'A') {
flag = 1;
}
}

Chúng ta thường hay sử dụng đoạn code như trên khi có ngắt sẽ set một cờ (flag) và sau đó trong hàm main() sẽ kiểm tra cờ để thực hiện một hành động nào đó. Tuy nhiên compiler không hề nhìn thấy là giá trị của flag có thể bị thay đổi ở trong ngắt, do đó nó tối ưu dẫn đến while(!flag) có thể trở thành một vòng lặp vô hạn. Do vậy trong trường hợp này chúng ta cũng nên thêm volatile vào trước biến flag

uint8_t volatile flag = 0;

Multi-thread

Xem xét đoạn code
uint8_t cnt;
void taskA() {
    cnt = 0;
    while (!cnt) {
    //do something
    }
}
void taskB() {
    cnt++;
}

Tương tự như 2 phần trên, compiler không biết là giá trị của biến cnt có thể thay đổi ở bên task B nên khi tối ưu sẽ dẫn đến việc chạy không đúng như ý muốn.

Một nhầm lẫn là tưởng sử dụng mutex để bảo vệ dữ liệu dùng chung sẽ giải quyết được vấn đề này.

int cnt ; 

task_a() { 
take(mutex); 
cnt += 1; 
give(mutex); 
}

task_b() { 

cnt = 0; 
take(mutex); 
if (cnt == 0) ... else ...; 
give(mutex); 
}

Trong đoạn code trên, compiler không biết cnt có thể thay đổi nên nó có thể lờ đi cả đoàn code if....else.

Tổng kết
Những lỗi gây ra do không sử dụng volatile có thể phát hiện ra sớm, nhưng với những trường hợp như sử dụng biến trong ngắt thì có thể rất lâu sau mới phát sinh lỗi. Vì vậy hãy sử dụng volatile bất cứ khi nào có thể :)


Tài liệu tham khảo

[1]. http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.faqs/ka3750.html
[2]. http://www.barrgroup.com/Embedded-Systems/How-To/C-Volatile-Keyword