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

      คุณรู้หรือเปล่าว่าปัญหา memory เกิดขึ้นเมื่อไหร่? แน่นอนว่าหลาย ๆ คนคงมองข้ามสำหรับปัญหานี้ ซึ่งเราอย่าลืมว่าการเขียนโปรแกรมบน Microcontroller มันไม่ได้มีหน่วยความจำอะไรมากมายเหมือนกับคอมพิวเตอร์เลย มันเลยกลายเป็นเรื่องราวที่ทำให้เจ้าของบล็อกอยากเขียนบทความนี้ขึ้นมา


"  Working in this minimalist environment, you must use your resources wisely. 
การเขียนโปรแกรมบนสภาพแวดล้อมที่จำกัด คุณต้องใช้ทรัพยากรอย่างฉลาด  "

      สำหรับสิ่งที่เจ้าของบล็อกอยากจะเท้าความก่อนเลยไม่ใช่การแก้ปัญหา แต่เป็นความเข้าใจว่าอะไรทำให้เกิดปัญหา สิ่งสำคัญในการพัฒนา embedded คือคุณต้องใช้ทรัพยากรที่มีอยู่จำกัดนี้ อย่างคุ้มค่าที่สุด และสิ่งที่คุณต้องรู้ก่อนเลยคือ ต้องรู้ว่าขีดจำกัดของ platform ที่เรากำลังพัฒนาอยู่มีเท่าไหร่


https://cdn-learn.adafruit.com/downloads/pdf/memories-of-an-arduino.pdf


Arduino memory


      ในเรื่อง memory ของ Arduino จะถูกแบ่งออกเป็น 3 อย่างก็คือ Flash ,SRAM และ EEPROM ในตัวอย่างของบทความนี้เจ้าของบล็อกจะใช้ Processor เป็น Atmega328 หรือก็คือ Arduino UNO นั่นเอง จะเห็นว่า Flash มีพื้นที่ 32K byte SRAM 2K byte และ EEPROM อีก 1K byte เมื่อเรารู้ทรัพยากรของบอร์ดเราแล้ว เราก็มาทำความรู้จัก memory ในแต่ละแบบกัน




Flash


      Flash คือ memory ส่วนที่จะเก็บโปรแกรมที่เราเขียนไว้รวมทั้ง boot loader ในส่วนนี้เมื่อบอร์ดไม่มีไฟเลี้ยงก็ยังสามารถเก็บข้อมูลได้ นั่นเป็นเหตุว่าทำไมเรา reset ใหม่กี่ครั้งหรือไฟดับกี่ครั้ง เมื่อบอร์ดจิ้มไฟ ก็ยังสามารถทำงานโค้ดเดิมที่เคย Flash โปรแกรมไว้ได้ แต่ข้อจำกัดของการ Flash ก็คือสามารถ Flash ได้สูงสุดประมาณ 10,000 ครั้ง จริง ๆ เท่านี้ก็เพียงพอแล้ว เพราะบางทีบอร์ดอาจจะเจ๊งก่อนที่จะ Flash ครบก็ได้นะ (ฮ่า ๆ ๆ)

     เราสามารถเก็บข้อมูลต่าง ๆ ลงใน Flash ได้ แต่ว่าเราจะไม่สามารถแก้ไขข้อมูลที่อยู่ใน Flash ได้เลย ในระหว่างที่บอร์ดกำลังทำงาน แต่ถ้าอยากจะใช้ข้อมูลใน Flash จริง ๆ คือต้อง copy ค่าใน Flash เก็บไว้ใน SRAM หรือก็คือเก็บไว้ในซักตัวแปรนั่นแหละ แล้วค่อยแก้ค่าในตัวแปรที่เก็บไว้


SRAM


      ชื่อเต็ม ๆ ก็คือ Static Random Access Memory เจ้าตัว SRAM นี้สามารถทั้งอ่านทั้งเขียนข้อมูลได้ การสร้างตัวแปรต่าง ๆ สร้าง function ต่าง ๆ หรือแม้แต่การจองพื้นที่ขณะที่กำลังทำงาน ในส่วนนี้จะถูกทำใน SRAM ทั้งหมด ทั้งนี้ SRAM ยังแยกชนิดการเก็บไปอีก 3 แบบนะเนี่ย มี Static Data , Heap แล้วก็ Stack


Static Data


      ในส่วน Static Data ถ้าเรามองเป็นภาพรวม มันก็คือบล็อค ๆ นึง(สีเขียว) ที่เก็บพวกตัวแปร Global และ ตัวแปร static พวกนี้จะมีขนาดที่คงที่เพราะตัวแปรในนี้มันจะถูกประกาศครั้งเดียวตอนเริ่มต้นโปรแกรม ในขณะที่โปรแกรมทำงาน เจ้าของบล็อกสามารถเปลี่ยนแปลงค่าได้ตามปรกติ แต่ไม่สามารถเพิ่มลดขนาดของข้อมูลได้อีกแล้ว แต่ถ้าอยากจะเพิ่มมันก็จะไปว่าในเรื่องของพวก Heap กับ Stack แทน



Heap

      ในส่วน heap คือส่วนที่เป็น Dynamic memory หรือก็คือเป็นหน่วยความจำที่เพิ่มลดขนาดตัวเองได้(สีน้ำตาล) ต่างจาก static memory ที่มีขนาดคงที่ 



      การทำงานบางครั้ง เราไม่สามารถรู้ได้ว่า เราจะต้องใช้หน่วยความจำเท่าไหร่ การขอพื้นที่หน่วยความจำตามจำนวนข้อมูลที่เราใช้ก็ถือว่าเป็นวิธีที่ดี แต่จะดีกว่าถ้าไม่ทำในงาน Embedded เพราะบางทีมันอาจจะสิ้นเปลือง Memory มากเกินความจำเป็น และเป็นสิ่งที่ควบคุมยาก เพราะเวลาเราจองพื้นที่มาแล้ว ในส่วนของ Heap ก็จะสูงขึ้นเรื่อย ๆ สำคัญเลยคือ เราต้องคืนพื้นที่หน่วยความจำทุกครั้งที่เราใช้งานเสร็จด้วย

Stack

      Stack เป็นส่วนที่เก็บข้อมูลจำพวกตัวแปร local ต่าง ๆ เวลาที่เราเรียกใช้ function หรือสร้างตัวแปร local ข้อมูลทุกอย่างจะถูกเก็บไว้ใน Stack ทั้งหมด 

      ความคิดเห็นส่วนตัวของเจ้าของบล็อกคิดว่าตรงนี้ไม่ต้องระวังอะไรมาก ไม่เหมือนส่วน Heap เพราะเป็นส่วนที่ต้องจัดการดี ๆ ใช้งานเสร็จคืนพื้นที่ ไม่งั้นส่วนอื่นก็จะมีทรัพยากรน้อยลง แต่เมื่อมาลองดูในส่วนของ Stack ซึ่งการทำงานของ local มันจะตายเองหลังจากที่ออกจากขอบเขตการทำงานของมัน ทำให้ส่วนนี้ไม่จำเป็นต้องจัดการอะไรมาก แต่ก็ไม่ใช่ว่าเราจะวางใจได้เลย เพราะ stack ยังมีปัญหาอย่าง stack overflow ที่จะพูดถึงในบทความต่อ ๆ ไป


EEPROM


      EEPROM เป็นหน่วยความจำแบบ non-volatile memory หรือก็คือเป็นหน่วยความจำถาวร เวลาไม่มีไฟเลี้ยงมันก็ยังสามารถเก็บข้อมูลไว้ได้อยู่ คล้าย ๆ กับ Flash แต่ข้อดีของมันคือ มันสามารถอ่านเขียนข้อมูลได้ในขณะที่บอร์ดกำลังทำงานอยู่เหมือน SRAM แต่ว่าในการอ่านเขียนข้อมูลแต่ละครั้งจะทำได้เพียงทีละ byte เท่านั้น ทำให้มันช้ากว่า SRAM มาก และมันสามารถอ่านเขียนข้อมูลได้สูงสุดประมาณ 100,000 ครั้ง


รูปสุดท้ายไม่เกี่ยวอะไรนะครับ พักสายตาเฉย ๆ ^^

     ถ้าให้พูดคร่าว ๆ memory แต่ละชนิดมีข้อดีข้อเสียต่างกัน แต่ในการทำงานจริง ๆ ถ้าสามารถใช้ memory ทั้ง 3 แบบนี้เป็น รู้ว่าจะใช้ตอนไหนยังไง จะช่วยทำให้ใช้ Microcontroller ได้อย่างมีประสิทธิภาพมาก พูดง่าย ๆ ไม่เสียของอะแหละ

     ในบทความตอนนี้เจ้าของบล็อกแค่อยากให้ผู้อ่านได้รู้จักกับ memory ในแต่ละแบบก่อน ในบทความต่อไปเจ้าของบล็อกจะพาไปดูปัญหาและสาเหตุของการใช้ memory ที่ใช้แบบไม่ระวัง และบทความต่อไปอีกคงจะเป็นวิธีแก้ปัญหาและทำให้มันมีประสิทธิภาพมากขึ้น ^^

บทความนี้มาจากความเข้าใจส่วนตัวส่วนนึงและแปลจาก adafruit ด้วยส่วนนึง

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

ความคิดเห็น

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

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

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