ว่าด้วยเรื่องหน่วยความจำ สิ่งที่หลายคนมองข้าม : Stack Overflow & EEPROM


      ตอนนี้ก็ดำเนินการมาถึงตอนที่ 4 เรียบร้อยแล้ว ใกล้จบแล้ว ๆ คิดว่าคงไม่เกิน 5 ตอนหรอกมั้ง (ฮ่า ๆ) เพราะยังเหลือเรื่อง EEPROM แล้วก็การ Optimize code กันอีกนิดหน่อย

      แต่ก่อนจะเริ่มเนื้อหาถัดไป อยากพูดเรื่อง stack overflow อีกนิดนึง เพิ่มเติมจากบทความก่อนหน้านี้ ซึ่งเป็นตัวอย่างปัญหาที่เกิดขึ้นจากการใช้ Very deep recursion การเรียก function ซ้ำ ๆ ที่มีความลึกมากเกินไป บางทีอาจจะต้องใช้เวลาค่อนข้างนาน กว่าที่ program จะประมวลผลเสร็จ เดี๋ยวเจ้าของบล็อกจะลองเขียนกับ ESP8266 12e ดูนะว่าจะมีผลยังไง



      เดี๋ยวเรามาดูว่าผลลัพธ์จะเป็นยังไง

ส่ง 10 เข้าไปใน Fibonacci function

      โอเคผลลัพธ์ก็จะออกมาประมาณนี้นะครับ จะยังเห็นว่า process การทำงานยังใช้เวลาไม่ถึง 1 วินาทีเลย ใครที่สงสัยเรื่อง fibonacci อ่านเพิ่มเติม ตรงนี้ได้นะ ทีนี้เราลองมาค่อย ๆ เพิ่มค่าที่จะส่งไปให้ดีกว่า

ส่ง 20 เข้าไปใน Fibonacci function


ส่ง 30 เข้าไปใน Fibonacci function

      โอ้วว มาถึงตรงนี้ โปรแกรมมันใช้เวลาประมวลผลเกือบครึ่งวินาทีเลยแฮะ แต่ยัง ยังไม่หมดหรอก เราจะลองต่อกันไปเรื่อย ๆ

ส่ง 40 เข้าไปใน Fibonacci function

      เมื่อส่ง 40 เข้าไปใน Fibonacci function ปรากฎว่า ตัว ESP8266 12e reset นะครับ แต่นี่ไม่ใช่การ reset จาก stack overflow แต่เป็น reset จาก WDT หรือก็คือ Watch dog timer ของตัว ESP8266 นั่นหมายความว่า Process ที่เราใช้ไปมันนานเกินไปจนเกิด interrupt timer ขึ้นนั่นเอง

      ก็เป็นอีก 1 ตัวอย่างที่ค่อนข้างเจอบ่อยกับตัว ESP8266 การเขียน call stack ที่ลึกมาก ๆ จนทำให้มีผลกับเวลาที่ใช้ในการประมวลผล จะเกิดปัญหา wdt reset ขึ้นบ่อย เพราะฉะนั้นการเขียนโปรแกรมจึงค่อนข้างที่จะละเอียดอ่อน และพยายามให้ optimize อยู่เสมอ




EEPROM


      ในบทความ ว่าด้วยเรื่องหน่วยความจำ สิ่งที่หลายคนมองข้าม ตอนที่ 1 ได้อธิบายไปแล้วว่า EEPROM เป็นหน่วยความจำแบบ non-volatile memory หรือก็คือเป็นหน่วยความจำถาวร ข้อดีของมันคือสามารถอ่านเขียนข้อมูลได้ในขณะที่โปรแกรมกำลังทำงาน แต่ก็ยังช้ากว่า SRAM อยู่มาก เพราะฉะนั้นการเก็บข้อมูลลงใน EEPROM จะเป็นการเก็บข้อมูลที่ไม่ได้ถูกใช้บ่อยมาก และไม่เหมาะกับการเก็บข้อมูลแบบ Stream เช่นการรับข้อมูล package จาก Serrial ตรง ๆ 

      โดยปรกติแล้วเจ้าของบล็อกมักจะเก็บค่าสถานะหรือ state ของโปรแกรมไว้ใน EEPROM เพราะเผื่อว่า เกิดกรณีที่ไฟดับ หรือ Microcontroller มีปัญหาอะไรบางอย่าง ทำให้เกิดการ reset ขึ้น ตัว Microcontroller เองก็จะดึงข้อมูล state จาก EEPROM เพื่อให้โปรแกรมพร้อมทำงานต่อจาก state เดิมล่าสุดที่ถูกเก็บไว้


https://www.arduino.cc/en/Reference/EEPROM
      ข้อควรระวังอย่างนึงเลยสำหรับการใช้งาน EEPROM ก็คือเราต้องรู้ว่า IC ที่เราเลือกใช้นั้นมีขนาดของ EEPROM เท่าไหร่ เพราะแต่ละรุ่นก็มีขนาดไม่เท่ากัน เพราะการที่เราอ้างอิง Address ที่เกินขอบเขต ก็อาจจะทำให้เกิด overflow ได้เช่นเดียวกัน

      ก็นึกไม่ค่อยออกหรอกว่าปัญหาใน EEPROM มันจะมีอะไรบ้าง ก็จะอ้างอิงจากประสบการณ์ตรงของเจ้าของบล็อกเลยก็แล้วกัน ฮ่า ๆ


Clear buffer ใน EEPROM ก่อนนน

      ปัญหาจากที่ไม่ได้ clear buffer ใน EEPROM ก่อนจะมาใช้งาน คือบางที ก่อนหน้านี้เจ้าของบล็อกเคยใช้เขียนเกี่ยวกับ EEPROM ของอีกงานนึง เสร็จแล้วก็ไม่ได้ทำไรต่อ นาน ๆ ไปก็ลืมแล้วว่าเคยเขียน EEPROM ไว้กับ board ไหนบ้าง พอจะเอามาใช้งานอีกครั้ง ก็เขียนโปรแกรมเผลอไปอ่านค่าใน address ซักที่ แล้วมันได้เป็นค่า EEPROM ของงานก่อนหน้า เพราะงั้นก่อนที่เราจะใช้งาน EEPROM เราควร Clear buffer ออกก่อน ซึ่งตรงนี้เจ้าของบล็อกไม่อธิบายละกันเพราะไม่ได้ยากมากและก็มีคนอธิบายเยอะแล้วด้วย เพราะฉะนั้นก็ไปอ่านต่อในนี้เอาแล้วกันนะ :) EEPROM Clear 


ระวังสับสน EEPROM ของ Arduino Library กับ ESP8266 Library ไม่เหมือนกัน !!


      เนื่องจากว่า Chip IC ของทั้งสองตัวนี้อยู่คนละตะกูลกัน การเขียนโปรแกรมให้เข้าถึง hardware จึงต่างกัน เพราะฉะนั้นอาจจะทำให้เราสับสนได้ตอนเรียกใช้งาน function


ข้างบนนี้เป็น function ที่มีใน EEPROM ของ ESP8266 library


ส่วนอันนี้เป็น function ที่มีใน EEPROM ของ Arduino library


      สิ่งที่แตกต่างกันคือ ESP8266 จะต้องบอกขนาด size ตอนเริ่มทำงานด้วยโดยใช้คำสั่ง begin ถ้าไม่ใช้คำสั่งนี้จะไม่สามารถเข้าถึงการใช้งาน EEPROM ได้เลย และที่แตกต่างอีกอย่างคือ เมื่อเรา write ข้อมูลลงใน EEPROM แล้วเราต้อง commit() มันทุกครั้งด้วย ถ้าไม่ commit มันก็ถือว่ายังไม่ได้เขียนข้อมูลลง EEPROM

      แต่เมื่อมาดู EEPROM ในส่วนของ arduino lirbrary แทบจะไม่ต้องทำอะไรเลย แค่ write read ก็ได้ละ เพราะใน library มันจะไปเช็คเองว่า EEPROM ใน chip มันมีขนาดเท่าไหร่ เออง่ายดี

      ตอนนี้ปัญหาที่นึกออกก็มีแค่นี้แหละฮะ ไว้ไปต่อกันบทความหน้า เกี่ยวกับการ optimize code กัน แต่ไม่รู้ว่าจะ optimize ได้แค่ไหนนะ ฮ่า ๆ ก็เช่นเดิม ถ้าหากมีอะไรสงสัยก็ comment ถามได้ หรือช่วย feedback กลับมาด้วยจะดีมากเพื่อเป็นการปรับปรุงเนื้อหาไปในตัว

อ่านตอนต่อไปได้ที่ ว่าด้วยเรื่องหน่วยความจำ สิ่งที่หลายคนมองข้าม ตอนที่ 5

reference : EEPROM Library , Memory of an arduino 

ความคิดเห็น

Unknown กล่าวว่า
มีประโยชน์มากครับ

โพสต์ยอดนิยมจากบล็อกนี้

ว่าด้วยเรื่องหน่วยความจำ สิ่งที่หลายคนมองข้าม : รู้จักกับ Memory

คณิตศาสตร์กับโปรแกรมมิ่งมันเป็นยังไงนะ ตอนที่ 1 เกริ่นพีทาโกรัส

Pointer กับตัวแปร Array นะจ๊ะ.. [Back to basic แต่ไม่ basic]