17
Other MCUs / Re: [IAR for STM8] warning นี้ มีวิธีทำให้มันหายไปไหมครับ
« on: September 09, 2018, 10:26:58 pm »
เกิดจากใน 1 statement มีการ access ตัวแปร volatile มากกว่า 1 ตัวครับ
เดาว่าน่าจะเป็น CNTRH กับ CNTRL เพราะส่วนใหญ่ Register มักจะมีการนิยามให้เป็น volatile
การที่เรานิยามตัวแปรให้เป็น volatile คือการนิยามว่าตัวแปรตัวนั้นมีการเปลี่ยนแปลงได้ตลอดเวลา
คาดการณ์ไม่ได้ ดังนั้น compiler จึงไม่ optimize ตัวแปรที่นิยามว่าเป็น volatile เพื่อให้เวลา
cpu ทำการ access ตัวแปร volatile จะต้องไปอ่านค่าจาก memory จริง ๆ ของตัวแปร volatile ตัวนั้น
การ access ตัวแปร volatile มากกว่า 1 ตัว ใน 1 statement นั้นไม่ได้ผิด แต่จะทำให้เกิดการคาดเดาพฤติกรรม
ของโปรแกรมไม่ได้
เช่น statement นี้
ใน statement นี้มีการอ่านค่าจาก CNTRH และ CNTRL พร้อมกัน แต่ในความเป็นจริงแล้ว
การทำงานของ cpu มันจะอ่านทีละตัว จะอ่านตัวไหนก่อนก็ขึ้นอยู่กับ compiler ที่ใช้ในการ compile และ
ช่วงเวลาที่ cpu อ่านค่าจาก volatile ตัวแรกอยู่ ค่าของ volatile ตัวที่ 2 อาจเปลี่ยนแปลงไปแล้ว
เรื่องนี้ไม่ได้เป็นเรื่องร้ายแรงถ้าเรารู้ตัวว่าเรากำลังทำอะไรอยู่ เช่นกรณีนี้ เรารู้ว่าเราตัวว่าเราอ่านค่า counter ของ timer
ซึ่งมีการเพิ่มขึ้นเป็นเชิงเส้นเสมอ แต่ compiler มันไม่รู้ด้วย IAR มันเลยเตือนไปตาม ISO/ANSI standard
แต่ถ้าจะต้องการเลี่ยงไม่ให้เกิดการ warning เราก็ต้องทำให้ใน 1 statement มีการ access ตัวแปร volatile ตัวเดียว
เช่น
หรือเอาตัวแปรธรรมดามาช่วย
หรือถ้าเรามันใจว่าโปรแกรมเราจะทำงานได้ถูกต้องแน่นอน เราสามารถไปปิดการ warning สำหรับ case นี้ได้
โดยคลิกขวาที่ Project เลือก Option ไปที่ C/C++ Compiler เลือกแทบ Diagnostics
แล้วในช่อง Suppress these diagnostics: ให้พิมพ์ Pa082 แล้ว OK
เท่านี้มันจะไม่ warning case Pa082 อีกแล้ว
เดาว่าน่าจะเป็น CNTRH กับ CNTRL เพราะส่วนใหญ่ Register มักจะมีการนิยามให้เป็น volatile
การที่เรานิยามตัวแปรให้เป็น volatile คือการนิยามว่าตัวแปรตัวนั้นมีการเปลี่ยนแปลงได้ตลอดเวลา
คาดการณ์ไม่ได้ ดังนั้น compiler จึงไม่ optimize ตัวแปรที่นิยามว่าเป็น volatile เพื่อให้เวลา
cpu ทำการ access ตัวแปร volatile จะต้องไปอ่านค่าจาก memory จริง ๆ ของตัวแปร volatile ตัวนั้น
การ access ตัวแปร volatile มากกว่า 1 ตัว ใน 1 statement นั้นไม่ได้ผิด แต่จะทำให้เกิดการคาดเดาพฤติกรรม
ของโปรแกรมไม่ได้
เช่น statement นี้
Code: [Select]
tim1_rec_[0] = (( TIM1->CNTRH << 8 ) | (TIM1->CNTRL) );
ใน statement นี้มีการอ่านค่าจาก CNTRH และ CNTRL พร้อมกัน แต่ในความเป็นจริงแล้ว
การทำงานของ cpu มันจะอ่านทีละตัว จะอ่านตัวไหนก่อนก็ขึ้นอยู่กับ compiler ที่ใช้ในการ compile และ
ช่วงเวลาที่ cpu อ่านค่าจาก volatile ตัวแรกอยู่ ค่าของ volatile ตัวที่ 2 อาจเปลี่ยนแปลงไปแล้ว
เรื่องนี้ไม่ได้เป็นเรื่องร้ายแรงถ้าเรารู้ตัวว่าเรากำลังทำอะไรอยู่ เช่นกรณีนี้ เรารู้ว่าเราตัวว่าเราอ่านค่า counter ของ timer
ซึ่งมีการเพิ่มขึ้นเป็นเชิงเส้นเสมอ แต่ compiler มันไม่รู้ด้วย IAR มันเลยเตือนไปตาม ISO/ANSI standard
แต่ถ้าจะต้องการเลี่ยงไม่ให้เกิดการ warning เราก็ต้องทำให้ใน 1 statement มีการ access ตัวแปร volatile ตัวเดียว
เช่น
Code: [Select]
tim1_rec_[0] = TIM1->CNTRH;
tim1_rec_[0] = (( tim1_rec_[0] << 8 ) | (TIM1->CNTRL));
หรือเอาตัวแปรธรรมดามาช่วย
Code: [Select]
uint8_t tmp1, tmp2;
tmp1 = TIM1->CNTRH;
tmp2 = TIM1->CNTRL;
tim1_rec_[0] = ((tmp1 << 8 ) | (tmp2);
หรือถ้าเรามันใจว่าโปรแกรมเราจะทำงานได้ถูกต้องแน่นอน เราสามารถไปปิดการ warning สำหรับ case นี้ได้
โดยคลิกขวาที่ Project เลือก Option ไปที่ C/C++ Compiler เลือกแทบ Diagnostics
แล้วในช่อง Suppress these diagnostics: ให้พิมพ์ Pa082 แล้ว OK
เท่านี้มันจะไม่ warning case Pa082 อีกแล้ว