Skip to main content

How can embedded developer fix bug by fastest way?


Embedded bugs. Fix them by fastest ways.


Đặt vấn đề:
- Đối với người lập trình nhúng, việc viết driver cho 1 ngoại vi (ví dụ USART,SPI,I2C,CAN...), giao tiếp giữa các module phần cứng, là công việc khá quen thuộc. Tuy nhiên, chúng ta cũng thường xuyên gặp những lỗi khá "vớ vẩn" làm mất rất nhiều thời gian và công sức. Đặc biệt là khi làm việc với 1 board mạch mới được thiết kế (ver 0.1), chưa được validate về tính năng trước đó.Không biết chính xác lỗi phát sinh là do phần cứng hay phần mềm.
Vậy, làm thế nào để fix được bug nhanh nhất?

Cách làm:
Kinh nghiệm của tôi là:
Khi 2 thiết bị "nói chuyện" với nhau chúng cần có những điều kiện sau để "hiểu nhau":

1. Môi trường truyền thông tin (ví dụ, trong không gian thì ko thể truyền âm thanh, 2 ngoại vi định truyền dữ liệu cho nhau mà bản thân kết nối vật lý bị hỏng( do pcb lởm khởm hoặc chất lượng hàn kém, mối hàn gây chập chờn, lúc được lúc không) thì ko thể trao đổi dữ liệu được. Nhiều trường hợp, khi cắm que đo vào thì truyền dữ liệu tốt, bỏ ra thì chập chờn. Nguyên nhân là do mối hàn kém chất lượng, khi bạn đo, que đo đặt lên chân linh kiện, chân này sẽ tiếp xúc tốt hơn với pad, thế là nó chạy, khi không có que đo thì chân linh kiện bị kênh lên so với pad, tiếp xúc kém, nên giao tiếp bị chập chờn).
Cách phát hiện:
- Quan sát bằng mắt thường các chân giao tiếp, các trace ở trên PCB.
- Dùng đồng hồ ở chế độ đo thông mạch,đảm bảo chân của con nọ được nối chân của con kia.
- Kiểm tra lại mạch nguyên lý và mạch in. Chú ý là: footprint cũng có thể sai.
- Dùng oscilloscope để kiểm tra dạng tín hiệu tại 2 chân tương ứng.Quan sát dạng tín hiệu xem có vuông vắn, đẹp đẽ, biên độ có đủ mức hay ko? có bị can nhiễu hay ko? Có đúng theo giản đồ xung trong datasheet không? Tần số có đúng với tần số đã được init hay ko? Thông thường, người ta kiểm tra chân Clock (SCL,SCK,CLK....) hoặc những chân mà chỉ cẩn khởi tạo đơn giản đã có xung ra chuẩn.
(ví dụ SCK của SPI, SCL của I2C....)

2. Mỗi thằng đều có khả năng nói và nghe một cách độc lập. (1 trong 2 thằng bị chết thì thằng còn lại nói chuyện với ai? Trong trường hợp này, có thể các chân giao tiếp bị hỏng,chưa khởi tạo được Nhiều VĐK, 1 chân chết mà core vẫn chạy bình thường :D)
Cách phát hiện:
- Thử code điều khiển IO thông thường, bật tắt thử các chân giao tiếp.
- Khởi tạo giao thức, kiểm tra ở chế độ loopback.

3. Hai thằng phải nói cùng 1 ngôn ngữ. (thử hỏi,thằng dùng tiếng Tây nói chuyện với thằng dùng tiếng Tàu thì có hiểu nhau ko?)
Cách phát hiện:
- Phần này thì phải kiểm tra về mặt giao thức. Xem giản đồ xung đã đúng theo datasheet chưa (start,stop như nào, xung chốt ra sao, chân chip select thế nào..vvv)
- Thử truyền nhận dữ liệu dạng raw. (Đơn giản, hoặc hardcode dữ liệu để test).

Tóm lại:
- Tìm ra nguyên nhân cụ thể là do phần cừng hay phần mềm là fix được cái bug này ngay.

Kinh nghiệm:
- Dùng code chuẩn nạp vào mạch lởm khởm (mạch đang code). Nếu, mạch chạy đúng chức năng => code "thối"
- Mượn kít chuẩn để nạp code test. Nếu mạch chạy đúng chức năng => phần cứng lởm khởm.
- Còn nếu bạn đã dùng hết các bài rồi thì phải cầu viện bác google thôi. Đặc biệt, bạn nên xin ý kiến của các bậc tiền bối, các chuyên gia "vườn".
- Và đừng bao giờ bị băn khoăn bởi câu hỏi bất hợp lý này:
"TẤT CẢ ĐỀU ĐÚNG RỒI MÀ TẠI SAO NÓ VẪN KO GIAO TIẾP ĐƯỢC"
- Đối với những bug ngáo ngơ, ko biết là tại đâu thì nguyên nhân chính là liên quan đến memory (RAM) hay việc kiểm soát các biến. Một số nguyên nhân hay gặp:
+ Thiếu RAM (chú ý lúc build, stack over flow)
+ Cấp phát động mà ko giải phóng bộ nhớ (alloc, calloc, malloc mà ko free)
+ Chia cho số 0, phép khai căn của những số nhỏ hơn 0....(đương nhiên, biến là số được truyền vào trong các phép tính toán số học này)
+ Giá trị của các phần tử mảng bị truy xuất ngoài mảng. (ví dụ: mảng có 10 phần tử mà ông lại ghi ra phần tử thứ 11 là đi rồi)
+ Biến bị tràn. (out of range)
+ Hai hay nhiều tác vụ (task) cùng truy xuất vào 1 vùng nhớ (liên quan đến mutex)
....
Chúc các bạn fix bug nhanh!
Để hạn chế bug ngay từ đầu dự án, bạn nên "keep coding convention" và biết một vài cái rules thường xuyên đụng tới khi làm embedded:

Ten bug-killing rules for C

Thân ái.

//=======================================================================
3:40 PM 6/8/2013
How can embedded developer fix bug by fastest way?

Introducing:
When you start coding any driver for new hardware (new board with some protocol like SPI, I2C, USART, CAN...). You always face with a basic bug: "It doesn't work well".
You was confusing about where did bug come from? hardware or software issues? And ofcourse, you must spend many time, my efford to fix them and keep deliver deadline?

My solution:
I supposed, we have 2 devices what are conneted via SPI. My connection didn't work. How can i do in this stuation?
1. Check physical connection between 2 devices 
Root cause:
- Some route is broken on PCB or unstable.
- Soldering is not good or unstable.
You should:
- Use your eye, focus in trace and pad on PCB to find out where is broken.
- Using VOM, make sure 2 device is connected to each other.
- Using oscilloscope, check signal form on bus. (expecially SCL(I2C) or SCK(SPI)). Signal amplitude level is enough or not? Signal frequency? Timing diagram?

2. Check device in standalone mode. Both of them must be worked well in standalone mode.
Root cause:
- Peripheral is broken.
- Pin out of peripheral are broken.
You should:
- Create simple source code project to control peripheral pin in IO mode. You can try turn on or turn off peripheral IO.
- Intialise protocol, try it in loopback mode.

3. Make sure protocol isn't wrong.
- Using oscilloscope to monitor protocol. Validate all input/output signal (select slave or chip select, SCL, SCK...)
- Try it using raw or simple data.

Conclusion:
Is BUG still alive?
Bug comes from hardware or software?
- Using evaluation board to check source code, remember wave form in best case for compare with wrong case. Try to find out a differences?
- Using example source code from IC's producer to confirm hardware's stability.
//=======================================================================
9:41 PM 3/11/2014
Some bullshit bugs make me a bit crazy because ...my crass mind :-(...
01. What is difference between 2 below source code:
"This is example to get date time from RTC IC via I2C bus"
Làm việc với 1 ic bất kỳ thì phải chú ý đến việc đường bus bị busy, không nhận được lệnh...Debug cho nhanh, đừng ngồi đoán mò..
Foo1:
while(1)
{
                printf("%02d:",rtc_data_read(RTC_MCP7491X_MIN_ADDR));
printf("%02d",rtc_data_read(RTC_MCP7491X_SEC_ADDR));
                sys_delay(1000);   // delay 1 second
}

Foo2:
while(1)
{
printf("%02d:%02d",rtc_data_read(RTC_MCP7491X_MIN_ADDR),
                rtc_data_read(RTC_MCP7491X_SEC_ADDR));
                sys_delay(1000);   // delay 1 second
}
or
while(1)
{
                min = rtc_data_read(RTC_MCP7491X_MIN_ADDR);
                sec = rtc_data_read(RTC_MCP7491X_SEC_ADDR)
printf("%02d:%02d",min,sec);
                sys_delay(1000);   // delay 1 second
}

Finally, foo1 run well...foo2 is foolish. We can't get date time from RTC IC
Reason is: foo1 spend more time to run than foo2 what make I2C bus busy.
How to fix: You should insert delay function between 2 continuously rtc_data_read() like this:
 while(1)
{
                min = rtc_data_read(RTC_MCP7491X_MIN_ADDR);
                sys_delay(1);         //about 1 ms
                sec = rtc_data_read(RTC_MCP7491X_SEC_ADDR)
printf("%02d:%02d",min,sec);
                sys_delay(1000);   // delay 1 second
}

Bonus, you can prevent several bug by keep coding convention. This link will show you method to kill bug

Ten bug-killing rules for C



Good luck for you.
Thank for reading,

Comments

Popular posts from this blog

[Git] Handle trailing space when patching with git

After complete coding one module in development branch. Next phase is merging. Obviously, you can merge source code automatically without no errors happen. However, life is not dream. Create a patch git diff HEAD > newTariff.patch Apply patch git apply newTariff.patch then problem happens Problem git apply newTariff.patch:106: trailing whitespace. patch does not apply Route cause: Nguyên nhân: Do trong source code có những dấu space thừa (ô vuông màu đỏ hình dưới) Some whitespaces is existed in your patch. (red area in below pictures) Fix Clean white space and patch again. Cách khắc phục Xóa những dấu space này đi và thực hiện patch lại Make up after complete coding. Find and clean whitespace before create patch file. Sửa sau khi code xong Kiểm tra sau khi code xong có lỗi này không git diff HEAD --check Prevent whitespace by manually when typing source code Sửa ngay khi đang code =>Bật chức năng hiển thị các dấu whitespace, hoặc remove trailing ...

How to test frame buffer in linux

The intended goal of this article is to provide the user with enough information so they can display an image onto a screen of their choosing. How to re-build frame buffer testing application. Base knowledge http://trac.gateworks.com/wiki/OpenEmbedded/Video_Out Frame buffer test application - rebuild fb-test-app step 1: Download soure code ( git installed on your machine and account in git-hub is required) https://github.com/prpplague/fb-test-app Command in git: git init git clone https://github.com/prpplague/fb-test-app.git step 2: Change makefile vi Makefile //open Makefile by vim editor :set nu //show line number replace from line 6 to line 12 by folow code: CC=arm-linux-gnueabi-gcc CFLAGS=-02 -Wall Save change command :wq step 3: Rebuid Type “make” command step 4: Copy execute file to target system by filezilla or something like that step 5: Remote target by root account, change mode of execute file (what copied from host) ...

[GTK] Example of using GtkBox with label and button

[1]Source code 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 #include <gtk/gtk.h> void on_window_closed (GtkWidget * window, gpointer data) { gtk_main_quit(); } static void destroy (GtkWidget * widget, gpointer data) { gtk_main_quit(); } static void button_clicked (GtkWidget * button, gpointer data) { g_print( "Button clicked \n " ); } int main ( int argc, char * argv[]) { GtkWidget * window, * label, * box, * button ; gtk_init( & argc, & argv); window = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_title(GTK_WINDOW (window), "Test GTK" ); gtk_window_set_default_size (GTK_WINDOW (window), 500 , 200 ); #if 1 //Use gtk3: change 0->1, Use gtk2: keep it is 0 //Using gtk3 box = gtk_box_new(GTK_ORIENTATION_VERTICAL, 5 ); ...