Wednesday, September 14, 2016

الحمل و الولادة و التربية

تبدأ هذه الرحلة بتسعة أشهر من الحمل، يطرأ فيها على الزوجة تغيرات كثيرة، بعضها مؤلم جسديا، و بعضها مؤلم نفسيا. بعضها آمن لا يحتاج إلى متابعة، و بعضها خطر إذا لم يتم متابعته و اتخاذ التدابير اللازمة حياله!

ما ساعدني في هذه الفترة أن زوجتي كانت على دراية كاملة بكل التفاصيل التي قد تحدث في كل مرحلة. توقع الاحداث و معرفة أنها طبيعية ولا خطر منها، يسهل كثيرا المرور بكل هذه التغيرات و الاحاسيس التي تطرأ في هذه الفترة.

الكتاب الممتاز الذي ساعد زوجتي في ذلك هو كتاب بعنوان:
What to expect while you are expecting!

ثم يأتي يوم الولادة، قد يجبر الطبيب أن تكون الولادة قيصرية، و قد يترك لك الخيار. حينما خضت هذه التجربة فوجئت بسيل من المعلومات المتضاربة، و كلها ناتجة عن تجارب:
- الطبيعي أحسن بكتير، تاني يوم الزوجة تكون بصحة جيدة و تستطيع القيام بهامها.
- القيصري يتم شفاؤه في 3 أسابيع تعيش خلالهم الزوجة ألم شديد.
- القيصري صعب في أول يومين فقط، بعدها يكون كل شيء على ما يرام.
- القيصري يشوه جسد المرأة فلا يعود كما كان
- الطبيعي يشوه جسد المرأة في منطقة حساسة، فهو أسوأ من القيصري الذي يشوه البطن
أمام هذا السيل من التجارب التي عاشها الناس خلصت إلى قناعة شخصية، و هي أنه لا توجد ثوابت، وأن رأي الطبيب هام للغاية، فإذا كان المهبل والحوض واسعين و الطفل ذو حجم مناسب، فالولادة الطبيعية أفضل للأسباب الآتية:
- ألم الولادة الطبيعية أثناء الولادة من المعروف أنه أكبر من القيصرية، ولكن هذا الألم يقل إذا توافرت العوامل المذكورة.
- لا تحتاح الطبيبة لفتح أي جزء آضافي من المهبل، وبالتالي لا يحدث اي تشوه

أما إذا لم تتوفر هذه العوامل، فقد لا تكون الولادة الطبيعية أفضل، حيث أن الطبيبة قد تحتاج لعمل فتحة عند المهبل لتتسع لخروج الطفل، فتكون مؤلمة لأيام كما هي الحالة مع فتحة القيصرية، و لكن في مكان أكثر حساسية و بللا و إزعاجا.

فترة التعافي من القيصرية من تجربتي الشخصية تمر بثلاث مراحل:
- اليوم الأول: ألم شديد، الكثير المسكنات، يتم قضاء هذا اليوم و هو يوم الولادة في المستشفى
اليوم الثاني: يقل الألم كثيرا، و لكن المشي و القيام و الجلوس و النوم يكون فيه صعوبة
- اليوم الثالث حتى مرور أسبوع: لا يوجد ألم، و لكن صعوبة في القيام و الجلوس و الحركة، تقل تدريجيا
- الأسبوع الثاني حتى مرور 40 يوما: لا يوجد ألم، تستطيع الزوجة القيام و الجلوس و حمل الطفل و الحركة وحدها دون مساعدة

و خلاصة الأمر، أن الولادة القيصرية - في حالة زوجتي - لم تكن مرعبة لهذه الدرجة التي صورها لنا بعض الأصدقاء الذين لابد أن تجاربهم لسبب ما لم تكن بهذا اليسر. فالألم الشديد الذي لا يحتمل فقط أول يوم (يوم الولادة) ابتاء من اليوم الثاني هو ألم بسيط، و من الثالث تقريبا لا يوجد ألم.

لحظة الولادة، زوجتك تدخل إلى العمليات، طفلك يصرخ، زوجتك لا زالت في العمليات، يأتي أحدهم بطفلك لتراه:
- تؤذن في أذنه اليمنى
- تقيم في أذنه اليسرى
يأخذونه إلى الحضانة، ثم تخرج زوجتك من العمليات إلى الغرفة الني ستبيت فيها.

بعدها بفترة يأتي الطفل ليشارككم الغرفة:
- تقوم بسنة التحنيك، في حالتي و بعد بعض البحث و سؤال الطبيبة، غسلت يدي جيدا، جئت بتمرة، ازحت جزء من قشرتها، ثم قطعت قطعة صغيرة من التمرة تحت القشرة، و أخذت افركه بين سبابتي و ابهامي، حتى اصبحت سبابتي بها طبقة من التمر، و لكن بدون اي قطع صلبة، مجرد ما يشبه الغشاء.
أدخلت سبابتي إلى فم ابني و أخذت أمسح حنكه الأعلى بالتمر.

في الايام الاولى للطفل تفاجأ بالعديد من الأعراض التي تحدث للطفل، ترتبك لأنك تجهل هل هذه أعراض طبيعية لا تحتاج لمتابعة او تدابير أم لا.

بالإضافة لاستشارة الطبيب و الأهل و الأصدقاء، و الانترنت، أنصح بقراءة هذه الكتب:
أنا و طفلي و الطبيب للدكتور إبراهيم شكري
كتاب دكتور سبوك

أما عن التربية، فقد قرأت كتاب عن تربية المونتسوري من 0 إلى 3 سنوات، كتاب صغير و لكن أفادني كثيرا، و هو بعنوان:
الطفل المرح - المونتيسوري الاساسي للطفل منذ الولادة حتى 3 سنوات - بقلم سوزان ميكلين ستيفنسون - 2011

بالإضافة إلى هذه القراءات، أود أن أشرك القارئ بعض الخبرات البسيطة:
في حالة الرضاعة الطبيعية، قد تحتاج لشراء ببرونة لاطعام الطفل في حالة عدم وجود أمه بجواره، على سبيل المثال أثناء نومها أو عملها.

إما أن تستخدم ببرونة معبأة بحليب صناعي او بحليب مشفوط من ثدي الأم بواسطة جهاز الpump

في الحالتين، يصعب على الطفل تقبل ثدي الام بعد الرضاعة من الببرونة، لأن اللبن يخرج من الببرونة بسهولة و بدون أن يبذل مجهودا في المص. فيعتاد الطفل على ذلك و يستسهل هذه التجربة.

الحل أن تستخدم ببرونة ذات حلمة طبيعية، و هي عبارة عن حلمة تحاكي ثدي الام، ولا تسمح بمرور اللبن إلا إذا قام الطفل بالعمل على المص، و من ثم يسهل الجمع بينها و بين الرضاعة الطبيعية.

في تجربتي الشخصية، استخدمت الادوات الآتية:
للشفط:
Medela mini electric pump
لتخزين اللبن:
Medela breast milk bottles
ببرونة بحلمة تحاكي الثدي:
Medela Calma bottle

من مميزات هذه الببرونة أن الحلمة المستخدمة فيها صالحة لكل الأعمار خلال فترة الرضاعة. في الأنواع الأخرى تحتاج لشراء حلمة مختلفة لكل مرحلة عمرية.

تجربة أخرى أضعها بين يدي القارئ، قد يحدث أن تتشقق حلمة ثدي الام في الاسبوع الاول من الرضاعة، نتيجة التكنيك الخاطئ من الأم و الطفل في الرضاعة.

تصبح عملية الرضاعة في ذلك الوقت عذابا، الطفل لا يزال يتعلم الرضاعة، و قد يفشل مرات حتى يستطيع الامساك بالحلمة و الرضاعة. اثناء هذه المحاولات، يبكي الطفل الجائع، و تتألم الأم نتيجة تشقق الحلمات الذي تعانيه، و يسود البيت كله حالة من الألم الجسدي و النفسي.

العديد من الاقتراحات قد يحل هذه المشكلة، سأتكلم فقط عن الطريقة التي اتبعتها انا و زوجتي و نجحت بفضل الله في تمكين الطفل من الرضاعة دون ألم للأم.

هذه الطريقة هي استخدام ال
Nipple protector (nipple sheild)
و هي حلمة اصطناعية توضع على حلمة الثدي أثناء الرضاعة، فلا تشعر الأم بأي ألم و تتعافى التشققات مع الوقت. شأنها شأن حلمة الثدي، قد يحتاح الطفل لبعض المحاولات قبل أن يتقن الرضاعة باستخدام الحلمات الاصطناعية. أيضا الأم قد تحتاج لبعض الوقت كي تتعلم تثبيت الحلمة و منعها من السقوط كثيرا. كنا نستخدم كريم تشققات الثدي لتثبيت الحلمة. بعد أن تأكدنا اولا انه لا يضر الطفل.

أنهي هذه المشاركة، بأن أؤكد على ضرورة القراءة عن هذه المرحلة قبل و أثناء دخولها، حتى تمر أكثر سهولة و يسرا و أمانا. و المصادر المشار إليها في هذا المقال كافية جدا في رأيي لتكوين حد أدنى من الثقافة اللازمة لخوض غمار هذه الفترة. فترة الحمل و الولادة و الرضاعة.

Saturday, July 23, 2016

ألعاب منتيسوري للطفل حديث الولادة

 الخامات

 ثلاثة أعمدة اسطوانية من إيكيا : 60 جنيها
دوبارة من مكتبة ألوان: حوالي 5 جنيهات
قلمين رصاص طوال من مكتبة ألوان: 15 جنيها

التكلفة = 80 جنيها

الخطوات

عمل ترايبود لاشينج باستخدام الدوبارة و الأعمدة الثلاثة. يمكن تعلم ذلك بسهولة عند البحث على يوتيوب عن
  tripod lashing




لف الدوبارة على الأقلام، لتغطية لونها حتى يركز الطفل على الأشكال المعلقة و لا يتشتت بالأقلام، يستخدم مسدس الشمع في هذه الخطوة
ربط القلمين على شكل علامة الجمع + ، وذلك باستخدام الدوبارة أيضا، يمكن تعلم ذلك عن طريق بحث على يوتيوب عن 
square lashing



يمكن تدعيم ال
tripod
باستخدام الأقلام الرصاص الطويلة، بربط قلم رصاص بين كل عمودين، باستخدام ربطة
square lashing

استخدام خيط سنارة أو الخيط المستخدم في تخييط الملابس، لتعليق الأشكال المختلفة

الاشكال

الشهر الأول أشكال مسطحة أبيض و أسود >> يمكن طباعتها على ورق عادي، و عمل لامينيشن في محل طباعة: مثلا زيروكس 
التكلفة: 7 جنيهات

الشهر الثاني: أشكال مجسمة ألوان >> يتم طباعة الفايل المرفق
Color3D
ضع الورقة المطبوعة فوق ورق مقوى بلون مثلا أحمر، وقم بالسير على الرسم باستخدام القلم
بعد إزاحة الورقة المطبوعة تجد أثر ضغط القلم واضحا على الورق المقوى
باستخدام المقص و مسدس الشمع يمكنك صناعة الأشكال المجسمة باللون الأحمر
كرر العمل باستخدام ورق مقوى أزرق و أصفر
تكلفة الورق المقوى الميتاليك: 22.5 جنيها

الشهر الثالث: درجات لون معين

قم باحاطة كور البينج بونج بدرجات مختلفة من خيط باللون الأزرق مثلا
الشهر الرابع: مجسمات للإنسان

بطباعة الملف المرفق باسم
human
وورق ميتاليك فضي و ذهبي، يمكنك صناعة أشكال الإنسان بنفس الطريق المتبعة في أشكال الشهر الثاني
التكلفة: 19 جنيها



التكلفة الإجمالية: 128.5 جنيها

Saturday, February 13, 2016

Memory

Memories:

RAMs:

  • SRAM (Static RAM)
    • Each cell stores 1 bit
    • Each cell consists of a flip flop (6 transistors)  > Large size - Low storage - High cost - More Power
    • Faster than DRam
From Video: Embedded System Video 4 Memory Part 1 

  • DRAM (Dynamic RAM)
    • Each cell stores 1 bit
    • Each cell consists of 1 transistor + 1 capacitor > Small area - High storage - Low cost - Less Power
    • The smaller area than SRAM because u need 6 transistors for one cell in SRAM, while u need only one in a DRAM. The capacitor needed in DRAM cell is done built in into the transistor
      • From Qoura.Com
        • Slower than SRam
          • Mechanism
            • Write '1': capacitor charge from Input buffer
            • Write '0': capacitor discharge through Input buffer
            • Read : capacitor discharges through Output buffer
              • Then capacitor is recharged (refreshes through Refresh buffer)
        • Examples:
          • SDRAM (Synchronous DRAM)
          • DDR SDRAM (Double Data Rate SDRAM)
From Video: Embedded System Video 4 Memory Part 1 

Cache Memory:
  • Is used to save portions of the data and instructions, that are currently used by the processor
  • Requirements:
    • Storage capacity can be small.
    • Fast
  • Used RAM:
    • SRAM (Faster - Less Storage capacity)
Main Memory:
  • The Big Ram that shall contain all the system data
  • Requirements:
    • Big storage capacity
    • Speed can be less than cache
  • Used RAM:
    • DRAM (Not as fast as SRAM - high storage capacity)
ROMs:
  • Mask ROM
    • Programmed in factory
  • PROM
    • Contains fuses, can be programmed only once
  • EPROM (Erasable Programmable ROM)
    • Ex: Ultra Violet EPROM, can be erased using ultraviolet light, then reprogrammed
    • Slow
  • EEPROM (Electrically Erasable Programmable ROM)
    • Flash memory: CMOS transistor with floating gate
  • Hard disk
    • Magnetic storage.
    • Very Slow, Large capacitance, used for long term data storage
  • Solid State Desk
    • Like hard disk, but faster

Sunday, January 24, 2016

Linker Script - Memory Map - Startup

Hi,

In this article, I will try to cover all the basics about:

  • Linker Script
  • Memory Map
  • Map file
  • Start up code
  • Interrupt vector
  • Fault Handlers
  • Non fault handlers
All these topics are correlated, and it suitable to cover them in one article.

Platform:


I will be using STM32F103x6 controller which is from ARM-Cortex M3 family.

Memory Map:


From Data sheet of the controller, Memory Map section, we can deduce that the micro controller memory map is as follows:
  • 0x0800 0000 > 0x0801 FFFF: Flash Memory    (128 K)
  • 0x1FFF F000 > 0x1FFF F800: System Memory (2 K)
    • Carries the bootloader.
    • The bootloader is used to reprogram the flash memory using USART.
  • 0x2000 0000 > 0x2000 2800: SRam                (10 K)
  • 0x0000 0000 > 0x0800 0000: Aliased to one of the memories as follows
Screen shot from the controller datasheet
Vector table is a memory section, which contains some info needed by the controller:
  • Initial Stack Pointer Value (SP)
  • Initial Program Counter Value (PC)
  • Addresses of fault handlers
  • Addresses of non-fault handlers
  • Addresses of IRQ handlers
You shall place the vector table in the memory you are booting from.

Screen shot from the controller datasheet

Vector Table Offset Register:

  • TBLBASE
    • Vector table base
      • 0: Code
      • 1: RAM
  • TBLOFF
    • vector table offset from the bottom of the SRAM or Code memory
Both of these values are set to 0 on power on.
You have to change them if needed inside the initialization code.

From Cortex M3 Technical Ref Manual

Linker Script

Assume that we have a small program, consists of 2 files:

  • main.c
  • delay.c
The compiler generates:
  • main.o
  • delay.o
Then the linker generates
  • elf
lets have a look into main.o and appl.elf file, with any elf viewer (ex: "arm-none-eabi-readelf.exe"):

In the symbol table:
  • main.o > functions and  global variables mem addresses are not defined
  • appl.elf > functions and  global variables mem addresses are defined




Taking a further look at the addresses, you can find that:
  • Global Variable B is placed into address "0x20000020"
  • Function main is placed into address "0x08000769"
This is because:
  • Global variables normally are allocated in RAM, which starts at the address "0x20000000"
  • Functions, are allocated inside the code segment into the Flash, which starts at the address "0x08000000"
How can the linker know the addresses where it can allocate the variables, and the functions?
  • The Linker Script contains this info. The linker script contains:
    • The different memories exists into the system
    • The different segments exists and where shall they be allocated
    • Global variables, contains addresses info, which can be used by your C modules.
      • Ex: "_sdata" which contains the start address of the data section, and is needed by start up code to initialize data section
Linker script can be divided into more than one file, for convenience. 
Below is a linker script, divided into two files:
  • mem.ld
    • Where we will get familiar to some linker script keywords:
      • MEMORY
      • ENTRY
      • Variables definitions
        • you can define variables, that can be used inside the code
          • Ex: "_sdata" which contains the start address of the data section, and is needed by start up code to initialize data section
        • the variable is externed into the c file (ex:startup.c), and used, then the linker links it to the variable defined into the linker
      • PROVIDE
  • sections.ld
    • Where we will get familiar to
      • How to define different sections
        • vector table
        • init values of data
        • text
        • data
        • bss
        • noinit
        • stack
      • "KEEP" keyword
      • The '.' operator (location counter)

mem.ld:
/* -----------------------------------------------------------------------------------------------
// MEMORY
// Describe available memory
// MEMORY command is optional
// If MEMORY command is not used the linker assumed sufficient memory is available for different sections
// -----------------------------------------------------------------------------------------------*/
MEMORY
{
  RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 10K /*read-write-exec*/
  FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 128K /*read-execute*/
}

/* -----------------------------------------------------------------------------------------------
// Stack
// -----------------------------------------------------------------------------------------------

// ------------------- 0x20000000 (RAM Origin) ---------------------------------------------------
//          |  data   |                                       |
//          |---------|---------------------------------------|
//    R     |  bss    |                                       |
//          |---------|---------------------------------------|
//    A     |         |                                     | 
//          |  heap   |                                       |
//    M     |---------|---------------------------------------| <-- Limit of stack
//          |         |                                    |
//  (10K)   |  stack  |          stack size = 1K              |
//          |         |                                       |
// ------------------- 0x20002800 (RAM Origin + RAM LENGTH) --  <-- end of stack -----------------
// ---------------------------------------------------------------------------------------------*/

/* _estack (End of stack)*/
__stack = ORIGIN(RAM) + LENGTH(RAM);
_estack = __stack; /* STM specific definition */

/* Stack Size */
__Main_Stack_Size = 1024 ;
PROVIDE ( _Main_Stack_Size = __Main_Stack_Size ) ;
/* PROVIDE, defines the variable only if referenced and not defined 
 * (if defined in the cmd files or in object file, then do not define it)*/

/* Stack Limit */
__Main_Stack_Limit = __stack  - __Main_Stack_Size ;
PROVIDE ( _Main_Stack_Limit = __Main_Stack_Limit );

/* There will be a link error if there is not this amount of 
// RAM free at the end. */
_Minimum_Stack_Size = 256 ;

/* ------------------------------------------------------------------------------------------------
// -- Heap
// ----------------------------------------------------------------------------------------------*/
PROVIDE ( _Heap_Begin = _end_noinit ) ;
PROVIDE ( _Heap_Limit = __stack - __Main_Stack_Size ) ;

/* ------------------------------------------------------------------------------------------------
// -- ENTRY
// -- Define entry point for debuggers and simulators
// ----------------------------------------------------------------------------------------------*/
ENTRY(_start)


sections.ld
/* Sections Definitions */

/*
 * FLASH
 *  (.isr_vector) Vector Table
 *  (.inits) Initializations of .data and .bss
 *  (.text) Text
 * RAM
 *  (.data) initialized variables
 *  (.bss) uninitialized variables (initialized to zeros)
 *  (.noinit) uninitialized variables (uninitialized)
 *  (.checkstack) to check that the minimum size of stack fits in the RAM 
 * */

SECTIONS
{
    /* VECTOR TABLE*/
    .isr_vector : ALIGN(4)
    {
        FILL(0xFF) /* initialize this segment to 0xFF*/
        
        __vectors_start = ABSOLUTE(.) ;  /* __vectors_start = 0x00000000*/
        __vectors_start__ = ABSOLUTE(.) ; /* STM specific definition */
        KEEP(*(.isr_vector))     /* Interrupt vectors */ 
        /* KEEP: keep this section even if no one referencing it*/
    
        /* Put Startup code and ISRs after the vector table, for convinience!*/
        *(.after_vectors .after_vectors.*) /* Startup code and ISR */

    } >FLASH

_sidata = .;
/* INIT values of DATA and BSS */
    .inits : ALIGN(4)
    {
    /* data and bss initial values*/
         
        __data_regions_array_start = .; 
        /*without using ABSOLUTE, the locaation counter '.' value, is relative to the curretnt section*/
        /*here, the location counter "." = 0, because we did not use ABSOLUTE*/
        
        LONG(LOADADDR(.data)); /*initial values address in FLASH*/
        LONG(ADDR(.data)); /* Copy Target start address (in RAM)*/
        LONG(ADDR(.data)+SIZEOF(.data)); /* Copy Target End address (in RAM)*/

        
        __data_regions_array_end = .;
        __bss_regions_array_start = .;
        
        LONG(ADDR(.bss));         /* Copy Target start address (in RAM)*/
        LONG(ADDR(.bss)+SIZEOF(.bss)); /* Copy Target start address (in RAM)*/
                
        __bss_regions_array_end = .;

        /* End of memory regions initialisation arrays. */  
      

    } >FLASH


    
/* CODE */
    .text : ALIGN(4)
    {
        *(.text .text.*) /* all remaining code */

  /* read-only data (constants) */
        *(.rodata .rodata.* .constdata .constdata.*)

    } >FLASH


/* Initialized Data */
    .data : ALIGN(4)
    {
    FILL(0xFF)
        /* This is used by the startup code to initialise the .data section */
        _sdata = . ;         /* STM specific definition */
        __data_start__ = . ;
*(.data_begin .data_begin.*)

*(.data .data.*)

*(.data_end .data_end.*)
   . = ALIGN(4);

   /* This is used by the startup code to initialise the .data section */
        _edata = . ;         /* STM specific definition */
        __data_end__ = . ;

    } >RAM AT>FLASH
/*place .data section in RAM | initialize it in FLASH*/
    
   

    /* uninitialized data (initialized to zeros) */
    .bss (NOLOAD) : ALIGN(4)
    {
        __bss_start__ = .;     /* standard newlib definition */
        _sbss = .;              /* STM specific definition */
        *(.bss_begin .bss_begin.*)

        *(.bss .bss.*)
        *(COMMON)
        
        *(.bss_end .bss_end.*)
   . = ALIGN(4);
        __bss_end__ = .;        /* standard newlib definition */
        _ebss = . ;             /* STM specific definition */
    } >RAM
    

/*noinit section*/
    .noinit (NOLOAD) : ALIGN(4)
    {
        _noinit = .;
        
        *(.noinit .noinit.*) 
        
         . = ALIGN(4) ;
        _end_noinit = .;   
    } > RAM
    
    /* Mandatory to be word aligned, _sbrk assumes this */
    PROVIDE ( end = _end_noinit ); /* was _ebss */
    PROVIDE ( _end = _end_noinit );
    PROVIDE ( __end = _end_noinit );
    PROVIDE ( __end__ = _end_noinit );
    
    /*
     * Used for validation only, do not allocate anything here!
     *
     * This is just to check that there is enough RAM left for the Main
     * stack. It should generate an error if it's full.
     */
    ._check_stack : ALIGN(4)
    {
        . = . + _Minimum_Stack_Size ;
    } >RAM
    
}


Build Process


Map File

A map file is an output file from the linker.

It contains the start and end addresses of different memory sections as described inside the linker script.

Example:

In linker script, bss section is defined as follows:

  • It comes after the data section inside the RAM

/* uninitialized data (initialized to zeros) */
    .bss (NOLOAD) : ALIGN(4)
    {
        __bss_start__ = .;      /* standard newlib definition */
        _sbss = .;              /* STM specific definition */
        *(.bss_begin .bss_begin.*)

        *(.bss .bss.*)
        *(COMMON)
        
        *(.bss_end .bss_end.*)
    . = ALIGN(4);
        __bss_end__ = .;        /* standard newlib definition */
        _ebss = . ;             /* STM specific definition */
    } >RAM

The linker does these calculations:

  • RAM start address is 0x2000000  (defined in linker script)
  • data section size is equal to the size of all global vars = 0x8C (calculated by the linker)
  • __bss_start__ = _sbss = location counter after placing .data section 
  • __bss_start__ _sbss RAM start addr data section size 
  • __bss_start__ _sbss 0x2000000        0x8C                   0x20000008C
  • __bss_end__ = _ebss = location counter after placing .bss section
  • __bss_end__ _ebss __bss_start__  + .bss section size 
  • __bss_end__ = _ebss =  0x20000008C  + 0xA0 0x20000012C
Here is a snapshot from the Map file generated from the above linker script:

Map:
                0x20000000                _sdata = .
                0x20000000                __data_start__ = .
 *(.data_begin .data_begin.*)
 .data_begin    0x20000000        0x4 ./system/src/newlib/_startup.o
 *(.data .data.*)
 .data.argv.4231
                0x20000004        0x8 ./system/src/newlib/_syscalls.o
 .data.AHBPrescTable
                0x2000000c       0x10 ./system/src/cmsis/system_stm32f10x.o
                0x2000000c                AHBPrescTable
 .data.SystemCoreClock
                0x2000001c        0x4 ./system/src/cmsis/system_stm32f10x.o
                0x2000001c                SystemCoreClock
 .data.B        0x20000020        0x4 ./src/main.o
                0x20000020                B
 .data.impure_data
                0x20000024       0x60 d:/program files/gnu tools arm embedded/5.2 2015q4/bin/../lib/gcc/arm-none-eabi/5.2.1/../../../../arm-none-eabi/lib/armv7-m\libg_nano.a(lib_a-impure.o)
 .data._impure_ptr
                0x20000084        0x4 d:/program files/gnu tools arm embedded/5.2 2015q4/bin/../lib/gcc/arm-none-eabi/5.2.1/../../../../arm-none-eabi/lib/armv7-m\libg_nano.a(lib_a-impure.o)
                0x20000084                _impure_ptr
 *(.data_end .data_end.*)
 .data_end      0x20000088        0x4 ./system/src/newlib/_startup.o
                0x2000008c                . = ALIGN (0x4)
                0x2000008c                _edata = .
                0x2000008c                __data_end__ = .

.igot.plt       0x2000008c        0x0 load address 0x08001248
 .igot.plt      0x2000008c        0x0 ./system/src/stm32f1-stdperiph/misc.o

.bss            0x2000008c       0xa0 load address 0x08001248
                0x2000008c                __bss_start__ = .
                0x2000008c                _sbss = .
 *(.bss_begin .bss_begin.*)
 .bss_begin     0x2000008c        0x4 ./system/src/newlib/_startup.o
 *(.bss .bss.*)
 .bss.current_heap_end.3942
                0x20000090        0x4 ./system/src/newlib/_sbrk.o
 .bss.name.4230
                0x20000094        0x1 ./system/src/newlib/_syscalls.o
 *fill*         0x20000095        0x3 
 .bss.buf.5078  0x20000098       0x80 ./system/src/diag/Trace.o
 .bss.__malloc_sbrk_start
                0x20000118        0x4 d:/program files/gnu tools arm embedded/5.2 2015q4/bin/../lib/gcc/arm-none-eabi/5.2.1/../../../../arm-none-eabi/lib/armv7-m\libg_nano.a(lib_a-nano-mallocr.o)
                0x20000118                __malloc_sbrk_start
 .bss.__malloc_free_list
                0x2000011c        0x4 d:/program files/gnu tools arm embedded/5.2 2015q4/bin/../lib/gcc/arm-none-eabi/5.2.1/../../../../arm-none-eabi/lib/armv7-m\libg_nano.a(lib_a-nano-mallocr.o)
                0x2000011c                __malloc_free_list
 *(COMMON)
 COMMON         0x20000120        0x4 ./system/src/newlib/_syscalls.o
                0x20000120                errno
 COMMON         0x20000124        0x4 ./src/main.o
                0x20000124                A
 *(.bss_end .bss_end.*)
 .bss_end       0x20000128        0x4 ./system/src/newlib/_startup.o
                0x2000012c                . = ALIGN (0x4)
                0x2000012c                __bss_end__ = .
                0x2000012c                _ebss = .


  • When I try to add a global initialized variable int C to my code.int C;
     Then build
    • checking the map file, I find bss start and end are shifted by four bytes
    • __bss_start__ = _sbss = 0x20000090
    • __bss_end__ = _ebss = 0x20000130

0x20000090                __bss_start__ = .
0x20000090                _sbss = .
...
...
...
0x20000130                __bss_end__ = .
0x20000130                _ebss = .

Vector Table

When the controller starts

  • it gets the vector table address from the "Vector Table Offset Register".
  • Initializes the PC to the value defined in the vector table
  • When fault or non fault exception happens, the controller knows the address of the exception handler from the vector table.
  • When IRQ (Interrupt Request) happens, the controller knows the address of its handler from the vector table

Vector Table: Micro controller Data sheet


Here is a snapshot of the first part of the vector table as defined in the data sheet:


Microcontroller Data sheet: Vector Table


Vector Table: In C code



In your code, you shall define your vector table according to the data sheet.

__attribute__ ((section(".isr_vector"),used))
pHandler __isr_vectors[] =
  {
  // Core Level - CM3
      (pHandler) &_estack, // The initial stack pointer
      Reset_Handler, // The reset handler
      NMI_Handler, // The NMI handler
      HardFault_Handler, // The hard fault handler
      MemManage_Handler,                        // The MPU fault handler
      BusFault_Handler,                        // The bus fault handler
      UsageFault_Handler,                        // The usage fault handler
      0,                                        // Reserved
      0,                                        // Reserved
      0,                                        // Reserved
      0,                                        // Reserved
      SVC_Handler,                              // SVCall handler
      DebugMon_Handler,                         // Debug monitor handler
      0, // Reserved
      PendSV_Handler, // The PendSV handler
      SysTick_Handler, // The SysTick handler

      WWDG_IRQHandler, // Window WatchDog
      PVD_IRQHandler, // PVD through EXTI Line detection

      TAMPER_IRQHandler, // Tamper through the EXTI 


  • __isr_vector, will not be placed in .data section as any other initialized array.
  • Instead it will be placed in the memory section ".isr_vector".
  • The linker does this as a result of the line: __attribute__ ((section(".isr_vector"),used))
  • Note that the variable _estack used in the above code, is not defined in the code, it is defined in the linker script (Check mem.ld above).



Vector Table: Linker Script


You shall define a memory section for vector table in the linker script.
You shall place it in the same place reported by the "Vector Table Offset Register" at start up (normally in the start of the flash)


.isr_vector : ALIGN(4)    {
    FILL(0xFF) /* initialize this segment to 0xFF*/
    __vectors_start = ABSOLUTE(.) ;  /* __vectors_start = 0x00000000*/
    __vectors_start__ = ABSOLUTE(.) ; /* STM specific definition */
    
    KEEP(*(.isr_vector))      /* Interrupt vectors */
    /* KEEP: keep this section even if no one referencing it*/
    
    /* Put Startup code and ISRs after the vector table, for convinience!*/
    *(.after_vectors .after_vectors.*) /* Startup code and ISR */
} >FLASH


What happens when the controller resets?


  • Get the PC from vector table
    • In our example: PC = Reset
  • Reset function calls the start up function
void __attribute__ ((section(".after_vectors"),noreturn))Reset_Handler (void){  _start ();} 
    • attribute: section(".after_vectors")
      • Tells the linker to place this function into the memory section .after_vectors defined into the linker script
    • attribute: noreturn
      • Tells the compiler that this function will not return
      • This makes sense, because no one calls this function, hence no need to save any values in the stack, no need to save return address inside link register
  • The startup function:
    • Makes some initialization
    • Calls the main (Or may call the bootloader, and the bootloader calls the main)

Start up Code:

Start up code is a code that usually is provided by the compiler, however you can modify it, or even write your own.

Normally start up code shall make the following:

  • Initialize RCC (Reset and Clock Controller)
  • PLL initialization
  • initialize .data section
__initialize_data(&_sidata, &_sdata, &_edata);
    • Note that _sidata, _sdata and _edata, are all defined in the linker script (check sections.ld above)
      • they represent
        • .inits section start addr
        • .data section start addr
        • .data section end addr
    • The function implementation can be
      • memcpy(_sidata_sdata_edata - _sdata);
  • initialize .bss section
__initialize_bss(&__bss_start__, &__bss_end__);

    • Note that __bss_start__ and __bss_end__, are defined in the linker script (check sections.ld above)
      • they represent
        • .bss section start addr
        • .bss section end addr
    • The function implementation can be 
      • memset (__bss_start__, 0, __bss_end__ - __bss_start___);
    • Call the main
main ();


Fault Handlers

Usually, fault handlers try to:

  • Print an error on RS232 for example
  • Reset the system.

So, you do not return from a fault handler.
Hence, they shall be no return functions.
so, use naked attribute, to prevent the compiler adding any stack push/pop stuff 
__attribute__ (naked)

  • This is also useful in the case where the fault happened in the stack pointer.
    • Assume that the stack pointer is pointing to a wrong value
      • you can do this using a debugger
        • Set a break point before a function call
        • Overwrite the stack pointer with a value out of RAM
        • Step into the function call 
        • The fault handler of busfault will be called due to undefined address access
    • If you did not define the fault handler as naked function
    • Each time the fault handler will be invoked, it will try to push some data on the stack.
    • Since the stack pointer carries a wrong value, the fault handler will be called again.
    • This will happen again and again, and the system will never reset.

Non Fault handlers


  • Non fault exceptions are not critical.
  • You can define handlers for non fault exceptions if you want.
  • In case you do not want to define non fault handlers, you can just define "Unhandled_exception" function, which for example prints "unhandled exception".
  • You can make weak aliasing for all non fault handlers to the unhandled_exception function

void __attribute__ ((weak, alias ("unhandled_exception"))) SysTick_Handler(void);


    • If you defined the function SysTick_Handler, then, the linker will link it
    • If you did not, the linker will link it to the function "unhandled_exception
  • The same concept can be applied to the IRQ handlers

void __attribute__ ((weak, alias ("Default_Handler"))) WWDG_IRQHandler(void);