From 40442bff4c40bcf2e1d7a4fc19018cef68513ca5 Mon Sep 17 00:00:00 2001 From: Terraneo Federico <fede.tft@hotmail.it> Date: Fri, 5 Apr 2013 00:34:12 +0200 Subject: [PATCH] Constructors of global objects moved from stage_1_boot to stage_2_boot --- miosix/Makefile | 1 + .../lpc2138_miosix_board/core/stage_1_boot.s | 42 --------- .../lpc2138_miosix_board/drivers/serial.cpp | 87 ++++++++++++------- .../cortexM3_stm32/common/drivers/serial.cpp | 83 ++++++++++++------ .../board_settings.h | 2 +- .../core/stage_1_boot.cpp | 31 +------ .../stm32f103ve_mp3v2/core/stage_1_boot.cpp | 31 +------ .../interfaces-impl/hwmapping.h | 2 +- .../core/stage_1_boot.cpp | 31 +------ .../interfaces-impl/hwmapping.h | 4 + .../core/stage_1_boot.cpp | 31 +------ .../interfaces-impl/hwmapping.h | 4 + .../core/stage_1_boot.cpp | 33 +------ .../core/stage_1_boot.cpp | 31 +------ .../interfaces-impl/console.cpp | 44 +++++++--- .../core/stage_1_boot.cpp | 31 +------ .../interfaces-impl/console.cpp | 44 +++++++--- .../core/stage_1_boot.cpp | 31 +------ .../interfaces-impl/console.cpp | 44 +++++++--- .../core/stage_1_boot.cpp | 31 +------ .../interfaces-impl/console.cpp | 45 +++++++--- .../core/stage_1_boot.cpp | 31 +------ .../interfaces-impl/console.cpp | 44 +++++++--- .../core/stage_1_boot.cpp | 31 +------ .../interfaces-impl/console.cpp | 44 +++++++--- miosix/check_global_objects.pl | 70 +++++++++++++++ miosix/compiler/Readme.txt | 4 +- miosix/config/Makefile.inc | 4 +- miosix/doc/textdoc/Changelog.txt | 16 ++++ miosix/kernel/filesystem/filesystem.cpp | 37 +++++--- miosix/kernel/stage_2_boot.cpp | 26 ++++++ miosix/testsuite/testsuite.cpp | 12 +++ miosix/util/version.cpp | 2 +- miosix_np_2/nbproject/private/private.xml | 2 +- 34 files changed, 472 insertions(+), 534 deletions(-) create mode 100644 miosix/check_global_objects.pl diff --git a/miosix/Makefile b/miosix/Makefile index d5c6e82a..7944924a 100644 --- a/miosix/Makefile +++ b/miosix/Makefile @@ -46,6 +46,7 @@ AFLAGS := $(AFLAGS_BASE) ## The file stage_1_boot.o is compiled separately because ## it must not end up in libmiosix.a all: $(OBJ) $(BOOT_FILE) + perl check_global_objects.pl $(OBJ) $(AR) rcs libmiosix.a $(OBJ) clean: diff --git a/miosix/arch/arm7_lpc2000/lpc2138_miosix_board/core/stage_1_boot.s b/miosix/arch/arm7_lpc2000/lpc2138_miosix_board/core/stage_1_boot.s index 348783b5..6aeaaf06 100644 --- a/miosix/arch/arm7_lpc2000/lpc2138_miosix_board/core/stage_1_boot.s +++ b/miosix/arch/arm7_lpc2000/lpc2138_miosix_board/core/stage_1_boot.s @@ -83,16 +83,6 @@ Reset_Handler: 2: cmp r1, r2 strlo r0, [r1], #4 blo 2b - /* call static constructors. Supports both eabi and elf binary formats */ - ldr r0, =__preinit_array_start - ldr r1, =__preinit_array_end - bl _call_constructors - ldr r0, =_ctor_start - ldr r1, =_ctor_end - bl _call_constructors - ldr r0, =__init_array_start - ldr r1, =__init_array_end - bl _call_constructors /* enter stage_2_boot. the lr (return address) is set to 0x00000000, so if main returns, it will jump to the reset vector, rebooting the system. Using bx instead of b to support thumb mode */ @@ -101,37 +91,5 @@ Reset_Handler: bx r12 .endfunc - -/* -Some info about static constructors: by reading newlib and gcc sources, and by -searching on the web it looks like static constructors are handled in a -different way in every binary format. The common part is this: the compiler -creates an array of function pointers, in a particular section. The startup -code, before calling main(), calls every function in the array, initializing -all static and global objets. But the name of the section is diferent: eabi -compilers (like codesourcery gcc) place the array in .preinit_array, -.init_array (for constructors) and .fini_array (for destructors) while elf -compilers (like arm-elf-g++) place the array in .ctor (for constructors) and -.dtor (for destructors). Constructors in .preinit_array and .init_array -sections are called by the function __libc_init_array (defined in -newlib-1.16.0/newlib/libc/misc/init.c). This function also calls _init, which -is supposed to call constructors in .ctor section. -By callng all constructors in .preint_array, .ctor and .init_array all -consructors will be called regardless of the binary format (elf or eabi). -This file has been used for over a year, so it is believed to be accurate. -*/ -.func _call_constructors -_call_constructors: - stmfd sp!, {lr} -4: cmp r0,r1 - beq 5f /* 5f = forward reference to label */ - ldr r2, [r0], #4 - stmfd sp!, {r0-r1} - mov lr, pc - bx r2 - ldmfd sp!, {r0-r1} - b 4b /* 4b = backward reference to label */ -5: ldmfd sp!, {pc} -.endfunc .end diff --git a/miosix/arch/arm7_lpc2000/lpc2138_miosix_board/drivers/serial.cpp b/miosix/arch/arm7_lpc2000/lpc2138_miosix_board/drivers/serial.cpp index 17e7703e..76cb5a75 100644 --- a/miosix/arch/arm7_lpc2000/lpc2138_miosix_board/drivers/serial.cpp +++ b/miosix/arch/arm7_lpc2000/lpc2138_miosix_board/drivers/serial.cpp @@ -34,20 +34,35 @@ namespace miosix { -//Configure the software queue here -const int SOFTWARE_TX_QUEUE=32;///<\internal Size of tx software queue -const int SOFTWARE_RX_QUEUE=32;///<\internal Size of rx software queue +class SerialData +{ +public: + static SerialData& instance() + { + static SerialData s; + return s; + } + + //Configure the software queue here + static const int SOFTWARE_TX_QUEUE=32;///<\internal Size of tx software queue + static const int SOFTWARE_RX_QUEUE=32;///<\internal Size of rx software queue -//The hardware queues cannot be modified, since their length is hardware-specific -const int HARDWARE_TX_QUEUE_LENGTH=16; -const int HARDWARE_RX_QUEUE_LENGTH=8; + //The hardware queues cannot be modified, since their length is hardware-specific + static const int HARDWARE_TX_QUEUE_LENGTH=16; + static const int HARDWARE_RX_QUEUE_LENGTH=8; -//Static (local) variables -static Mutex txMutex;///<\internal Mutex used to guard the tx queue -static Mutex rxMutex;///<\internal Mutex used to guard the rx queue + //Static (local) variables + Mutex txMutex;///<\internal Mutex used to guard the tx queue + Mutex rxMutex;///<\internal Mutex used to guard the rx queue -static Queue<char,SOFTWARE_TX_QUEUE> tx_queue;///<\internal Tx software queue -static Queue<char,SOFTWARE_RX_QUEUE> rxQueue;///<\internal Rx software queue + Queue<char,SOFTWARE_TX_QUEUE> txQueue;///<\internal Tx software queue + Queue<char,SOFTWARE_RX_QUEUE> rxQueue;///<\internal Rx software queue + +private: + SerialData() {} + SerialData(const SerialData&); + SerialData& operator= (const SerialData&); +}; ///\internal True if a rx character found the queue full static volatile bool rxLostFlag=false; @@ -63,6 +78,7 @@ static bool serialEnabled=false;///<\internal True if serial port is enabled void serial_irq_impl() __attribute__((noinline)); void serial_irq_impl() { + SerialData& s=SerialData::instance(); char c; int i; bool hppw=false; @@ -73,21 +89,21 @@ void serial_irq_impl() c=U0RBR;//Read U0RBR to discard char that caused error break; case 0x4: //RDA - for(i=0;i<HARDWARE_RX_QUEUE_LENGTH;i++) + for(i=0;i<SerialData::HARDWARE_RX_QUEUE_LENGTH;i++) { - if(rxQueue.IRQput(U0RBR,hppw)==false) rxLostFlag=true; + if(s.rxQueue.IRQput(U0RBR,hppw)==false) rxLostFlag=true; } case 0xc: //CTI while(U0LSR & (1<<0)) { - if(rxQueue.IRQput(U0RBR,hppw)==false) rxLostFlag=true; + if(s.rxQueue.IRQput(U0RBR,hppw)==false) rxLostFlag=true; } break; case 0x2: //THRE - for(i=0;i<HARDWARE_TX_QUEUE_LENGTH;i++) + for(i=0;i<SerialData::HARDWARE_TX_QUEUE_LENGTH;i++) { //If software queue empty, stop - if(tx_queue.IRQget(c,hppw)==false) break; + if(s.txQueue.IRQget(c,hppw)==false) break; U0THR=c; } break; @@ -115,8 +131,9 @@ void serial_IRQ_Routine() void IRQserialInit(unsigned int div) { - tx_queue.IRQreset(); - rxQueue.IRQreset(); + SerialData& s=SerialData::instance(); + s.txQueue.IRQreset(); + s.rxQueue.IRQreset(); PCONP|=(1<<3);//Enable UART0 peripheral U0LCR=0x3;//DLAB disabled //0x07= fifo enabled, reset tx and rx hardware fifos @@ -141,8 +158,9 @@ void IRQserialInit(unsigned int div) void IRQserialDisable() { + SerialData& s=SerialData::instance(); serialEnabled=false; - while(!(tx_queue.isEmpty() && IRQserialTxFifoEmpty())) ; //wait + while(!(s.txQueue.isEmpty() && IRQserialTxFifoEmpty())) ; //wait //Disable VIC VICIntEnClr=(1<<6); //Disable UART0 @@ -159,9 +177,10 @@ bool IRQisSerialEnabled() void serialWrite(const char *str, unsigned int len) { + SerialData& s=SerialData::instance(); if(!serialEnabled) return; int i; - Lock<Mutex> l(txMutex); + Lock<Mutex> l(s.txMutex); { FastInterruptDisableLock dLock; while(len>0) @@ -169,10 +188,10 @@ void serialWrite(const char *str, unsigned int len) //If somebody disables serial port while we are transmitting if(!serialEnabled) break; //If no data in software and hardware queue - if((U0LSR & (1<<5))&&(tx_queue.isEmpty())) + if((U0LSR & (1<<5))&&(s.txQueue.isEmpty())) { //Fill hardware queue first - for(i=0;i<HARDWARE_TX_QUEUE_LENGTH;i++) + for(i=0;i<SerialData::HARDWARE_TX_QUEUE_LENGTH;i++) { U0THR=*str; str++; @@ -180,13 +199,13 @@ void serialWrite(const char *str, unsigned int len) if(len==0) break; } } else { - if(tx_queue.IRQput(*str)==true) + if(s.txQueue.IRQput(*str)==true) { str++; len--; } else { FastInterruptEnableLock eLock(dLock); - tx_queue.waitUntilNotFull(); + s.txQueue.waitUntilNotFull(); } } } @@ -196,28 +215,30 @@ void serialWrite(const char *str, unsigned int len) bool serialTxComplete() { //If both hardware and software queue are empty, tx is complete. - return tx_queue.isEmpty() && IRQserialTxFifoEmpty(); + return SerialData::instance().txQueue.isEmpty() && IRQserialTxFifoEmpty(); } char serialReadChar() { char result; - rxMutex.lock(); - rxQueue.get(result); - rxMutex.unlock(); + SerialData& s=SerialData::instance(); + s.rxMutex.lock(); + s.rxQueue.get(result); + s.rxMutex.unlock(); return result; } bool serialReadCharNonblocking(char& c) { bool result=false; - rxMutex.lock(); - if(rxQueue.isEmpty()==false) + SerialData& s=SerialData::instance(); + s.rxMutex.lock(); + if(s.rxQueue.isEmpty()==false) { - rxQueue.get(c); + s.rxQueue.get(c); result=true; } - rxMutex.unlock(); + s.rxMutex.unlock(); return result; } @@ -230,7 +251,7 @@ bool serialRxLost() void serialRxFlush() { - rxQueue.reset(); + SerialData::instance().rxQueue.reset(); } void IRQserialWriteString(const char *str) diff --git a/miosix/arch/cortexM3_stm32/common/drivers/serial.cpp b/miosix/arch/cortexM3_stm32/common/drivers/serial.cpp index 77b7e842..469ebab3 100644 --- a/miosix/arch/cortexM3_stm32/common/drivers/serial.cpp +++ b/miosix/arch/cortexM3_stm32/common/drivers/serial.cpp @@ -81,11 +81,38 @@ void DMA1_Channel4_IRQHandler() } #endif //__ENABLE_XRAM -namespace miosix { +namespace miosix { -static Mutex rxMutex;///<\internal Mutex used to guard the rx queue -const unsigned int SOFTWARE_RX_QUEUE=32;///<\internal Size of rx software queue -static Queue<char,SOFTWARE_RX_QUEUE> rxQueue;///<\internal Rx software queue +/** + * Groups objects used by the serial driver + */ +class SerialData +{ +public: + /** + * \return an instance of this class (singleton) + */ + static SerialData& instance() + { + static SerialData s; + return s; + } + + Mutex rxMutex;///<\internal Mutex used to guard the rx queue + Mutex txMutex;///<\internal Mutex used to guard the tx queue + static const unsigned int SOFTWARE_RX_QUEUE=32;///<\internal Size of rx queue + Queue<char,SOFTWARE_RX_QUEUE> rxQueue;///<\internal Rx software queue + #ifndef __ENABLE_XRAM + static const unsigned int SOFTWARE_TX_QUEUE=32;///<\internal Size of tx queue + char tx_dma_buffer[SOFTWARE_TX_QUEUE];///<\internal Tx dma buffer + Queue<char,1> tx_queue;///<\internal Tx queue. Size is 1 because of dma + #endif //__ENABLE_XRAM + +private: + SerialData() {} + SerialData(const SerialData&); + SerialData& operator= (const SerialData&); +}; ///\internal True if a rx character found the queue full static volatile bool rxLostFlag=false; @@ -101,6 +128,7 @@ static bool serialEnabled=false;///<\internal True if serial port is enabled void serial_irq_impl() __attribute__((noinline)); void serial_irq_impl() { + SerialData& s=SerialData::instance(); bool hppw=false; unsigned int status=USART1->SR; if(status & USART_SR_ORE) //Receiver overrun @@ -108,24 +136,19 @@ void serial_irq_impl() rxLostFlag=true; char c=USART1->DR; //Always read data, since this clears interrupt flags if((status & USART_SR_RXNE) && ((status & 0x7)==0)) - rxQueue.IRQput(c,hppw); + s.rxQueue.IRQput(c,hppw); } else if(status & USART_SR_RXNE) //Receiver data available { char c=USART1->DR; //Always read data, since this clears interrupt flags if((status & 0x7)==0) //If no noise nor framing nor parity error { - if(rxQueue.IRQput(c,hppw)==false) rxLostFlag=true; + if(s.rxQueue.IRQput(c,hppw)==false) rxLostFlag=true; } } if(hppw) Scheduler::IRQfindNextThread(); } -static Mutex txMutex;///<\internal Mutex used to guard the tx queue - #ifndef __ENABLE_XRAM -const unsigned int SOFTWARE_TX_QUEUE=32;///<\internal Size of tx software queue -static char tx_dma_buffer[SOFTWARE_TX_QUEUE];///<\internal Tx dma buffer -static Queue<char,1> tx_queue;///<\internal Tx queue. Size is 1 because of dma /** * \internal @@ -142,14 +165,15 @@ void serial_dma_impl() //Wake eventual waiting thread, and do context switch if priority is higher char useless; bool hppw=false; - tx_queue.IRQget(useless,hppw); + SerialData::instance().tx_queue.IRQget(useless,hppw); if(hppw) Scheduler::IRQfindNextThread(); } void IRQserialInit() { - tx_queue.IRQreset(); - rxQueue.IRQreset(); + SerialData& s=SerialData::instance(); + s.tx_queue.IRQreset(); + s.rxQueue.IRQreset(); //Enable clock to GPIOA, AFIO and USART1 RCC->APB2ENR |= RCC_APB2ENR_IOPAEN | RCC_APB2ENR_AFIOEN | RCC_APB2ENR_USART1EN; @@ -192,20 +216,21 @@ void IRQserialDisable() serialEnabled=false; while(!IRQserialTxFifoEmpty()) ; //wait USART1->CR1=0; - tx_queue.IRQreset(); //Wake eventual thread waiting + SerialData::instance().tx_queue.IRQreset(); //Wake eventual thread waiting } void serialWrite(const char *str, unsigned int len) { if(!serialEnabled) return; - Lock<Mutex> l(txMutex); + SerialData& s=SerialData::instance(); + Lock<Mutex> l(s.txMutex); for(;len>0;) { // This will block if the buffer is currently being handled by the dma. // The advantage of using a queue is that if the dma tranfer ends while // a thread with lower priority than the one that is waiting, a context // switch will happen. - tx_queue.put(0); + s.tx_queue.put(0); { FastInterruptDisableLock lock; @@ -213,11 +238,11 @@ void serialWrite(const char *str, unsigned int len) if(!serialEnabled) return; // If we get here, the dma buffer is ready - unsigned int transferSize=std::min(len,SOFTWARE_TX_QUEUE); - memcpy(tx_dma_buffer,str,transferSize); + unsigned int transferSize=std::min(len,SerialData::SOFTWARE_TX_QUEUE); + memcpy(s.tx_dma_buffer,str,transferSize); // Setup DMA xfer DMA1_Channel4->CPAR=reinterpret_cast<unsigned int>(&USART1->DR); - DMA1_Channel4->CMAR=reinterpret_cast<unsigned int>(tx_dma_buffer); + DMA1_Channel4->CMAR=reinterpret_cast<unsigned int>(s.tx_dma_buffer); DMA1_Channel4->CNDTR=transferSize; DMA1_Channel4->CCR=DMA_CCR4_MINC | DMA_CCR4_DIR | DMA_CCR4_TEIE | DMA_CCR4_TCIE | DMA_CCR4_EN; @@ -262,7 +287,7 @@ void IRQserialWriteString(const char *str) void IRQserialInit() { - rxQueue.IRQreset(); + SerialData::instance().rxQueue.IRQreset(); //Enable clock to GPIOA, AFIO and USART1 RCC->APB2ENR |= RCC_APB2ENR_IOPAEN | RCC_APB2ENR_AFIOEN | RCC_APB2ENR_USART1EN; @@ -306,7 +331,7 @@ void serialWrite(const char *str, unsigned int len) { if(!serialEnabled) return; { - Lock<Mutex> l(txMutex); + Lock<Mutex> l(SerialData::instance().txMutex); for(unsigned int i=0;i<len;i++) { while((USART1->SR & USART_SR_TXE)==0) @@ -345,18 +370,20 @@ bool serialTxComplete() char serialReadChar() { - Lock<Mutex> l(rxMutex); + SerialData& s=SerialData::instance(); + Lock<Mutex> l(s.rxMutex); char result; - rxQueue.get(result); + s.rxQueue.get(result); return result; } bool serialReadCharNonblocking(char& c) { - Lock<Mutex> l(rxMutex); - if(rxQueue.isEmpty()==false) + SerialData& s=SerialData::instance(); + Lock<Mutex> l(s.rxMutex); + if(s.rxQueue.isEmpty()==false) { - rxQueue.get(c); + s.rxQueue.get(c); return true; } return false; @@ -371,7 +398,7 @@ bool serialRxLost() void serialRxFlush() { - rxQueue.reset(); + SerialData::instance().rxQueue.reset(); } bool IRQserialTxFifoEmpty() diff --git a/miosix/arch/cortexM3_stm32/stm32f100rb_stm32vldiscovery/board_settings.h b/miosix/arch/cortexM3_stm32/stm32f100rb_stm32vldiscovery/board_settings.h index 24b0175b..0239dfbc 100644 --- a/miosix/arch/cortexM3_stm32/stm32f100rb_stm32vldiscovery/board_settings.h +++ b/miosix/arch/cortexM3_stm32/stm32f100rb_stm32vldiscovery/board_settings.h @@ -58,7 +58,7 @@ const unsigned int AUX_TIMER_MAX=0xffff; ///<\internal Aux timer is 16 bits ///If defined, stdout is redirected to the debug communication channel, and ///will be printed if OpenOCD is connected. If not defined, stdout will be ///redirected throug USART1, as usual. -#define STDOUT_REDIRECTED_TO_DCC +//#define STDOUT_REDIRECTED_TO_DCC /** * \} diff --git a/miosix/arch/cortexM3_stm32/stm32f100rb_stm32vldiscovery/core/stage_1_boot.cpp b/miosix/arch/cortexM3_stm32/stm32f100rb_stm32vldiscovery/core/stage_1_boot.cpp index 7aed737c..ec923e72 100644 --- a/miosix/arch/cortexM3_stm32/stm32f100rb_stm32vldiscovery/core/stage_1_boot.cpp +++ b/miosix/arch/cortexM3_stm32/stm32f100rb_stm32vldiscovery/core/stage_1_boot.cpp @@ -7,8 +7,7 @@ * startup.cpp * STM32 C++ startup. * NOTE: for stm32 medium density value line devices ONLY (64 and 128KB devices). - * - supports interrupt handlers in C++ without extern "C" - * - global constructors are correctly called before main() + * Supports interrupt handlers in C++ without extern "C" * Developed by Terraneo Federico, based on ST startup code. * Additionally modified to boot Miosix. */ @@ -17,23 +16,6 @@ //stage_2_boot.cpp extern "C" void _init(); -/** - * Calls C++ global constructors - * \param start first function pointer to call - * \param end one past the last function pointer to call - * Declared "noinline" to optimize code size - */ -static void call_constructors(unsigned long *start, unsigned long *end) __attribute__((noinline)); -static void call_constructors(unsigned long *start, unsigned long *end) -{ - for(unsigned long *i=start; i<end; i++) - { - void (*funcptr)(); - funcptr=reinterpret_cast<void (*)()>(*i); - funcptr(); - } -} - /** * Called by Reset_Handler, performs initialization and calls main. * Never returns. @@ -62,12 +44,6 @@ void program_startup() extern unsigned char _edata asm("_edata"); extern unsigned char _bss_start asm("_bss_start"); extern unsigned char _bss_end asm("_bss_end"); - extern unsigned long __preinit_array_start asm("__preinit_array_start"); - extern unsigned long __preinit_array_end asm("__preinit_array_end"); - extern unsigned long __init_array_start asm("__init_array_start"); - extern unsigned long __init_array_end asm("__init_array_end"); - extern unsigned long _ctor_start asm("_ctor_start"); - extern unsigned long _ctor_end asm("_ctor_end"); //Initialize .data section, clear .bss section unsigned char *etext=&_etext; @@ -78,11 +54,6 @@ void program_startup() memcpy(data, etext, edata-data); memset(bss_start, 0, bss_end-bss_start); - //Initialize C++ global constructors - call_constructors(&__preinit_array_start, &__preinit_array_end); - call_constructors(&__init_array_start, &__init_array_end); - call_constructors(&_ctor_start, &_ctor_end); - //Move on to stage 2 _init(); diff --git a/miosix/arch/cortexM3_stm32/stm32f103ve_mp3v2/core/stage_1_boot.cpp b/miosix/arch/cortexM3_stm32/stm32f103ve_mp3v2/core/stage_1_boot.cpp index 6d860a64..2c841de6 100644 --- a/miosix/arch/cortexM3_stm32/stm32f103ve_mp3v2/core/stage_1_boot.cpp +++ b/miosix/arch/cortexM3_stm32/stm32f103ve_mp3v2/core/stage_1_boot.cpp @@ -6,8 +6,7 @@ /* * startup.cpp * STM32 C++ startup. - * - supports interrupt handlers in C++ without extern "C" - * - global constructors are correctly called before main() + * Supports interrupt handlers in C++ without extern "C" * Developed by Terraneo Federico, based on ST startup code. * Additionally modified to boot Miosix. */ @@ -16,23 +15,6 @@ //stage_2_boot.cpp extern "C" void _init(); -/** - * Calls C++ global constructors - * \param start first function pointer to call - * \param end one past the last function pointer to call - * Declared "noinline" to optimize code size - */ -static void call_constructors(unsigned long *start, unsigned long *end) __attribute__((noinline)); -static void call_constructors(unsigned long *start, unsigned long *end) -{ - for(unsigned long *i=start; i<end; i++) - { - void (*funcptr)(); - funcptr=reinterpret_cast<void (*)()>(*i); - funcptr(); - } -} - /** * Called by Reset_Handler, performs initialization and calls main. * Never returns. @@ -53,12 +35,6 @@ void program_startup() extern unsigned char _edata asm("_edata"); extern unsigned char _bss_start asm("_bss_start"); extern unsigned char _bss_end asm("_bss_end"); - extern unsigned long __preinit_array_start asm("__preinit_array_start"); - extern unsigned long __preinit_array_end asm("__preinit_array_end"); - extern unsigned long __init_array_start asm("__init_array_start"); - extern unsigned long __init_array_end asm("__init_array_end"); - extern unsigned long _ctor_start asm("_ctor_start"); - extern unsigned long _ctor_end asm("_ctor_end"); //Initialize .data section, clear .bss section unsigned char *etext=&_etext; @@ -69,11 +45,6 @@ void program_startup() memcpy(data, etext, edata-data); memset(bss_start, 0, bss_end-bss_start); - //Initialize C++ global constructors - call_constructors(&__preinit_array_start, &__preinit_array_end); - call_constructors(&__init_array_start, &__init_array_end); - call_constructors(&_ctor_start, &_ctor_end); - //Move on to stage 2 _init(); diff --git a/miosix/arch/cortexM3_stm32/stm32f103ve_mp3v2/interfaces-impl/hwmapping.h b/miosix/arch/cortexM3_stm32/stm32f103ve_mp3v2/interfaces-impl/hwmapping.h index 8c366402..fef4cd8f 100644 --- a/miosix/arch/cortexM3_stm32/stm32f103ve_mp3v2/interfaces-impl/hwmapping.h +++ b/miosix/arch/cortexM3_stm32/stm32f103ve_mp3v2/interfaces-impl/hwmapping.h @@ -186,6 +186,6 @@ typedef Gpio<GPIOB_BASE,8> pb8; //used to be Charger::en #ifdef _MIOSIX } //namespace miosix -#else //_MIOSIX +#endif //_MIOSIX #endif //HWMAPPING_H diff --git a/miosix/arch/cortexM3_stm32/stm32f103ve_strive_mini/core/stage_1_boot.cpp b/miosix/arch/cortexM3_stm32/stm32f103ve_strive_mini/core/stage_1_boot.cpp index 5f4cc399..4e4bb0b3 100644 --- a/miosix/arch/cortexM3_stm32/stm32f103ve_strive_mini/core/stage_1_boot.cpp +++ b/miosix/arch/cortexM3_stm32/stm32f103ve_strive_mini/core/stage_1_boot.cpp @@ -6,8 +6,7 @@ /* * startup.cpp * STM32 C++ startup. - * - supports interrupt handlers in C++ without extern "C" - * - global constructors are correctly called before main() + * Supports interrupt handlers in C++ without extern "C" * Developed by Terraneo Federico, based on ST startup code. * Additionally modified to boot Miosix. */ @@ -16,23 +15,6 @@ //stage_2_boot.cpp extern "C" void _init(); -/** - * Calls C++ global constructors - * \param start first function pointer to call - * \param end one past the last function pointer to call - * Declared "noinline" to optimize code size - */ -static void call_constructors(unsigned long *start, unsigned long *end) __attribute__((noinline)); -static void call_constructors(unsigned long *start, unsigned long *end) -{ - for(unsigned long *i=start; i<end; i++) - { - void (*funcptr)(); - funcptr=reinterpret_cast<void (*)()>(*i); - funcptr(); - } -} - /** * Called by Reset_Handler, performs initialization and calls main. * Never returns. @@ -61,12 +43,6 @@ void program_startup() extern unsigned char _edata asm("_edata"); extern unsigned char _bss_start asm("_bss_start"); extern unsigned char _bss_end asm("_bss_end"); - extern unsigned long __preinit_array_start asm("__preinit_array_start"); - extern unsigned long __preinit_array_end asm("__preinit_array_end"); - extern unsigned long __init_array_start asm("__init_array_start"); - extern unsigned long __init_array_end asm("__init_array_end"); - extern unsigned long _ctor_start asm("_ctor_start"); - extern unsigned long _ctor_end asm("_ctor_end"); //Initialize .data section, clear .bss section unsigned char *etext=&_etext; @@ -77,11 +53,6 @@ void program_startup() memcpy(data, etext, edata-data); memset(bss_start, 0, bss_end-bss_start); - //Initialize C++ global constructors - call_constructors(&__preinit_array_start, &__preinit_array_end); - call_constructors(&__init_array_start, &__init_array_end); - call_constructors(&_ctor_start, &_ctor_end); - //Move on to stage 2 _init(); diff --git a/miosix/arch/cortexM3_stm32/stm32f103ve_strive_mini/interfaces-impl/hwmapping.h b/miosix/arch/cortexM3_stm32/stm32f103ve_strive_mini/interfaces-impl/hwmapping.h index 016c9c81..5d4babe9 100644 --- a/miosix/arch/cortexM3_stm32/stm32f103ve_strive_mini/interfaces-impl/hwmapping.h +++ b/miosix/arch/cortexM3_stm32/stm32f103ve_strive_mini/interfaces-impl/hwmapping.h @@ -29,6 +29,7 @@ #define HWMAPPING_H #include "interfaces/gpio.h" +namespace miosix { // // All GPIOs are mapped here @@ -103,4 +104,7 @@ typedef Gpio<GPIOA_BASE,10> rx; //Handled by hardware (USART1) namespace buttons { typedef Gpio<GPIOB_BASE,15> button1; } + +} //namespace miosix + #endif //HWMAPPING_H diff --git a/miosix/arch/cortexM3_stm32/stm32f103ze_redbull_v2/core/stage_1_boot.cpp b/miosix/arch/cortexM3_stm32/stm32f103ze_redbull_v2/core/stage_1_boot.cpp index dbd9d18b..946bb0e5 100644 --- a/miosix/arch/cortexM3_stm32/stm32f103ze_redbull_v2/core/stage_1_boot.cpp +++ b/miosix/arch/cortexM3_stm32/stm32f103ze_redbull_v2/core/stage_1_boot.cpp @@ -6,8 +6,7 @@ /* * startup.cpp * STM32 C++ startup. - * - supports interrupt handlers in C++ without extern "C" - * - global constructors are correctly called before main() + * Supports interrupt handlers in C++ without extern "C" * Developed by Terraneo Federico, based on ST startup code. * Additionally modified to boot Miosix. */ @@ -16,23 +15,6 @@ //stage_2_boot.cpp extern "C" void _init(); -/** - * Calls C++ global constructors - * \param start first function pointer to call - * \param end one past the last function pointer to call - * Declared "noinline" to optimize code size - */ -static void call_constructors(unsigned long *start, unsigned long *end) __attribute__((noinline)); -static void call_constructors(unsigned long *start, unsigned long *end) -{ - for(unsigned long *i=start; i<end; i++) - { - void (*funcptr)(); - funcptr=reinterpret_cast<void (*)()>(*i); - funcptr(); - } -} - /** * Called by Reset_Handler, performs initialization and calls main. * Never returns. @@ -61,12 +43,6 @@ void program_startup() extern unsigned char _edata asm("_edata"); extern unsigned char _bss_start asm("_bss_start"); extern unsigned char _bss_end asm("_bss_end"); - extern unsigned long __preinit_array_start asm("__preinit_array_start"); - extern unsigned long __preinit_array_end asm("__preinit_array_end"); - extern unsigned long __init_array_start asm("__init_array_start"); - extern unsigned long __init_array_end asm("__init_array_end"); - extern unsigned long _ctor_start asm("_ctor_start"); - extern unsigned long _ctor_end asm("_ctor_end"); //Initialize .data section, clear .bss section unsigned char *etext=&_etext; @@ -83,11 +59,6 @@ void program_startup() #endif //__CODE_IN_XRAM memset(bss_start, 0, bss_end-bss_start); - //Initialize C++ global constructors - call_constructors(&__preinit_array_start, &__preinit_array_end); - call_constructors(&__init_array_start, &__init_array_end); - call_constructors(&_ctor_start, &_ctor_end); - //Move on to stage 2 _init(); diff --git a/miosix/arch/cortexM3_stm32/stm32f103ze_redbull_v2/interfaces-impl/hwmapping.h b/miosix/arch/cortexM3_stm32/stm32f103ze_redbull_v2/interfaces-impl/hwmapping.h index 8501789a..69cb8a01 100644 --- a/miosix/arch/cortexM3_stm32/stm32f103ze_redbull_v2/interfaces-impl/hwmapping.h +++ b/miosix/arch/cortexM3_stm32/stm32f103ze_redbull_v2/interfaces-impl/hwmapping.h @@ -30,6 +30,8 @@ #include "interfaces/gpio.h" +namespace miosix { + // // All GPIOs are mapped here // @@ -135,4 +137,6 @@ namespace buttons { typedef Gpio<GPIOD_BASE,3> user2; } +} //namespace miosix + #endif //HWMAPPING_H diff --git a/miosix/arch/cortexM3_stm32/stm32f103ze_stm3210e-eval/core/stage_1_boot.cpp b/miosix/arch/cortexM3_stm32/stm32f103ze_stm3210e-eval/core/stage_1_boot.cpp index d9c12a0b..a33ff9b6 100644 --- a/miosix/arch/cortexM3_stm32/stm32f103ze_stm3210e-eval/core/stage_1_boot.cpp +++ b/miosix/arch/cortexM3_stm32/stm32f103ze_stm3210e-eval/core/stage_1_boot.cpp @@ -6,8 +6,7 @@ /* * startup.cpp * STM32 C++ startup. - * - supports interrupt handlers in C++ without extern "C" - * - global constructors are correctly called before main() + * Supports interrupt handlers in C++ without extern "C" * Developed by Terraneo Federico, based on ST startup code. * Additionally modified to boot Miosix. */ @@ -16,23 +15,6 @@ //stage_2_boot.cpp extern "C" void _init(); -/** - * Calls C++ global constructors - * \param start first function pointer to call - * \param end one past the last function pointer to call - * Declared "noinline" to optimize code size - */ -static void call_constructors(unsigned long *start, unsigned long *end) __attribute__((noinline)); -static void call_constructors(unsigned long *start, unsigned long *end) -{ - for(unsigned long *i=start; i<end; i++) - { - void (*funcptr)(); - funcptr=reinterpret_cast<void (*)()>(*i); - funcptr(); - } -} - /** * Called by Reset_Handler, performs initialization and calls main. * Never returns. @@ -49,13 +31,7 @@ void program_startup() extern unsigned char _edata asm("_edata"); extern unsigned char _bss_start asm("_bss_start"); extern unsigned char _bss_end asm("_bss_end"); - extern unsigned long __preinit_array_start asm("__preinit_array_start"); - extern unsigned long __preinit_array_end asm("__preinit_array_end"); - extern unsigned long __init_array_start asm("__init_array_start"); - extern unsigned long __init_array_end asm("__init_array_end"); - extern unsigned long _ctor_start asm("_ctor_start"); - extern unsigned long _ctor_end asm("_ctor_end"); - + //Initialize .data section, clear .bss section unsigned char *etext=&_etext; unsigned char *data=&_data; @@ -71,11 +47,6 @@ void program_startup() #endif //__CODE_IN_XRAM memset(bss_start, 0, bss_end-bss_start); - //Initialize C++ global constructors - call_constructors(&__preinit_array_start, &__preinit_array_end); - call_constructors(&__init_array_start, &__init_array_end); - call_constructors(&_ctor_start, &_ctor_end); - //Move on to stage 2 _init(); diff --git a/miosix/arch/cortexM3_stm32f2/stm32f207ig_stm3220g-eval/core/stage_1_boot.cpp b/miosix/arch/cortexM3_stm32f2/stm32f207ig_stm3220g-eval/core/stage_1_boot.cpp index 18663fb1..cd799411 100644 --- a/miosix/arch/cortexM3_stm32f2/stm32f207ig_stm3220g-eval/core/stage_1_boot.cpp +++ b/miosix/arch/cortexM3_stm32f2/stm32f207ig_stm3220g-eval/core/stage_1_boot.cpp @@ -7,8 +7,7 @@ * startup.cpp * STM32 C++ startup. * NOTE: for stm32f2 devices ONLY. - * - supports interrupt handlers in C++ without extern "C" - * - global constructors are correctly called before main() + * Supports interrupt handlers in C++ without extern "C" * Developed by Terraneo Federico, based on ST startup code. * Additionally modified to boot Miosix. */ @@ -17,23 +16,6 @@ //stage_2_boot.cpp extern "C" void _init(); -/** - * Calls C++ global constructors - * \param start first function pointer to call - * \param end one past the last function pointer to call - * Declared "noinline" to optimize code size - */ -static void call_constructors(unsigned long *start, unsigned long *end) __attribute__((noinline)); -static void call_constructors(unsigned long *start, unsigned long *end) -{ - for(unsigned long *i=start; i<end; i++) - { - void (*funcptr)(); - funcptr=reinterpret_cast<void (*)()>(*i); - funcptr(); - } -} - /** * Called by Reset_Handler, performs initialization and calls main. * Never returns. @@ -50,12 +32,6 @@ void program_startup() extern unsigned char _edata asm("_edata"); extern unsigned char _bss_start asm("_bss_start"); extern unsigned char _bss_end asm("_bss_end"); - extern unsigned long __preinit_array_start asm("__preinit_array_start"); - extern unsigned long __preinit_array_end asm("__preinit_array_end"); - extern unsigned long __init_array_start asm("__init_array_start"); - extern unsigned long __init_array_end asm("__init_array_end"); - extern unsigned long _ctor_start asm("_ctor_start"); - extern unsigned long _ctor_end asm("_ctor_end"); //Initialize .data section, clear .bss section unsigned char *etext=&_etext; @@ -72,11 +48,6 @@ void program_startup() #endif //__CODE_IN_XRAM memset(bss_start, 0, bss_end-bss_start); - //Initialize C++ global constructors - call_constructors(&__preinit_array_start, &__preinit_array_end); - call_constructors(&__init_array_start, &__init_array_end); - call_constructors(&_ctor_start, &_ctor_end); - //Move on to stage 2 _init(); diff --git a/miosix/arch/cortexM3_stm32f2/stm32f207ig_stm3220g-eval/interfaces-impl/console.cpp b/miosix/arch/cortexM3_stm32f2/stm32f207ig_stm3220g-eval/interfaces-impl/console.cpp index 56d69a98..72a957df 100644 --- a/miosix/arch/cortexM3_stm32f2/stm32f207ig_stm3220g-eval/interfaces-impl/console.cpp +++ b/miosix/arch/cortexM3_stm32f2/stm32f207ig_stm3220g-eval/interfaces-impl/console.cpp @@ -64,10 +64,25 @@ void USART3_IRQHandler() namespace miosix { -static Mutex rxMutex;///<\internal Mutex used to guard the rx queue -static Mutex txMutex;///<\internal Mutex used to guard the tx queue -const unsigned int SOFTWARE_RX_QUEUE=32;///<\internal Size of rx software queue -static Queue<char,SOFTWARE_RX_QUEUE> rxQueue;///<\internal Rx software queue +class SerialData +{ +public: + static SerialData& instance() + { + static SerialData s; + return s; + } + + Mutex rxMutex;///<\internal Mutex used to guard the rx queue + Mutex txMutex;///<\internal Mutex used to guard the tx queue + static const unsigned int SOFTWARE_RX_QUEUE=32;///<\internal Size of rx queue + Queue<char,SOFTWARE_RX_QUEUE> rxQueue;///<\internal Rx software queue + +private: + SerialData() {} + SerialData(const SerialData&); + SerialData& operator= (const SerialData&); +}; /** * \internal @@ -79,19 +94,20 @@ static Queue<char,SOFTWARE_RX_QUEUE> rxQueue;///<\internal Rx software queue void serialIrqImpl() __attribute__((noinline)); void serialIrqImpl() { + SerialData& s=SerialData::instance(); bool hppw=false; unsigned int status=USART3->SR; if(status & USART_SR_ORE) //Receiver overrun { char c=USART3->DR; //Always read data, since this clears interrupt flags if((status & USART_SR_RXNE) && ((status & 0x7)==0)) - rxQueue.IRQput(c,hppw); + s.rxQueue.IRQput(c,hppw); } else if(status & USART_SR_RXNE) //Receiver data available { char c=USART3->DR; //Always read data, since this clears interrupt flags if((status & 0x7)==0) //If no noise nor framing nor parity error { - rxQueue.IRQput(c,hppw); + s.rxQueue.IRQput(c,hppw); } } if(hppw) Scheduler::IRQfindNextThread(); @@ -99,7 +115,7 @@ void serialIrqImpl() void IRQstm32f2serialPortInit() { - rxQueue.IRQreset(); + SerialData::instance().rxQueue.IRQreset(); //Enable clock to GPIOC and USART3 RCC->AHB1ENR |= RCC_AHB1ENR_GPIOCEN; RCC->APB1ENR |= RCC_APB1ENR_USART3EN; @@ -130,7 +146,7 @@ void IRQstm32f2serialPortInit() static void serialWriteImpl(const char *str, unsigned int len) { { - Lock<Mutex> l(txMutex); + Lock<Mutex> l(SerialData::instance().txMutex); for(unsigned int i=0;i<len;i++) { while((USART3->SR & USART_SR_TXE)==0) ; @@ -171,18 +187,20 @@ bool Console::IRQtxComplete() char Console::readChar() { - Lock<Mutex> l(rxMutex); + SerialData& s=SerialData::instance(); + Lock<Mutex> l(s.rxMutex); char result; - rxQueue.get(result); + s.rxQueue.get(result); return result; } bool Console::readCharNonBlocking(char& c) { - Lock<Mutex> l(rxMutex); - if(rxQueue.isEmpty()==false) + SerialData& s=SerialData::instance(); + Lock<Mutex> l(s.rxMutex); + if(s.rxQueue.isEmpty()==false) { - rxQueue.get(c); + s.rxQueue.get(c); return true; } return false; diff --git a/miosix/arch/cortexM3_stm32f2/stm32f207ze_als_camboard/core/stage_1_boot.cpp b/miosix/arch/cortexM3_stm32f2/stm32f207ze_als_camboard/core/stage_1_boot.cpp index 16c8c7af..386b8b61 100644 --- a/miosix/arch/cortexM3_stm32f2/stm32f207ze_als_camboard/core/stage_1_boot.cpp +++ b/miosix/arch/cortexM3_stm32f2/stm32f207ze_als_camboard/core/stage_1_boot.cpp @@ -7,8 +7,7 @@ * startup.cpp * STM32 C++ startup. * NOTE: for stm32f2 devices ONLY. - * - supports interrupt handlers in C++ without extern "C" - * - global constructors are correctly called before main() + * Supports interrupt handlers in C++ without extern "C" * Developed by Terraneo Federico, based on ST startup code. * Additionally modified to boot Miosix. */ @@ -17,23 +16,6 @@ //stage_2_boot.cpp extern "C" void _init(); -/** - * Calls C++ global constructors - * \param start first function pointer to call - * \param end one past the last function pointer to call - * Declared "noinline" to optimize code size - */ -static void call_constructors(unsigned long *start, unsigned long *end) __attribute__((noinline)); -static void call_constructors(unsigned long *start, unsigned long *end) -{ - for(unsigned long *i=start; i<end; i++) - { - void (*funcptr)(); - funcptr=reinterpret_cast<void (*)()>(*i); - funcptr(); - } -} - /** * Called by Reset_Handler, performs initialization and calls main. * Never returns. @@ -50,12 +32,6 @@ void program_startup() extern unsigned char _edata asm("_edata"); extern unsigned char _bss_start asm("_bss_start"); extern unsigned char _bss_end asm("_bss_end"); - extern unsigned long __preinit_array_start asm("__preinit_array_start"); - extern unsigned long __preinit_array_end asm("__preinit_array_end"); - extern unsigned long __init_array_start asm("__init_array_start"); - extern unsigned long __init_array_end asm("__init_array_end"); - extern unsigned long _ctor_start asm("_ctor_start"); - extern unsigned long _ctor_end asm("_ctor_end"); //Initialize .data section, clear .bss section unsigned char *etext=&_etext; @@ -70,11 +46,6 @@ void program_startup() memcpy(data, etext, edata-data); memset(bss_start, 0, bss_end-bss_start); - //Initialize C++ global constructors - call_constructors(&__preinit_array_start, &__preinit_array_end); - call_constructors(&__init_array_start, &__init_array_end); - call_constructors(&_ctor_start, &_ctor_end); - //Move on to stage 2 _init(); diff --git a/miosix/arch/cortexM3_stm32f2/stm32f207ze_als_camboard/interfaces-impl/console.cpp b/miosix/arch/cortexM3_stm32f2/stm32f207ze_als_camboard/interfaces-impl/console.cpp index 04ef0d7f..e75ca2b0 100644 --- a/miosix/arch/cortexM3_stm32f2/stm32f207ze_als_camboard/interfaces-impl/console.cpp +++ b/miosix/arch/cortexM3_stm32f2/stm32f207ze_als_camboard/interfaces-impl/console.cpp @@ -57,10 +57,25 @@ void USART1_IRQHandler() namespace miosix { -static Mutex rxMutex;///<\internal Mutex used to guard the rx queue -static Mutex txMutex;///<\internal Mutex used to guard the tx queue -const unsigned int SOFTWARE_RX_QUEUE=32;///<\internal Size of rx software queue -static Queue<char,SOFTWARE_RX_QUEUE> rxQueue;///<\internal Rx software queue +class SerialData +{ +public: + static SerialData& instance() + { + static SerialData s; + return s; + } + + Mutex rxMutex;///<\internal Mutex used to guard the rx queue + Mutex txMutex;///<\internal Mutex used to guard the tx queue + static const unsigned int SOFTWARE_RX_QUEUE=32;///<\internal Size of rx queue + Queue<char,SOFTWARE_RX_QUEUE> rxQueue;///<\internal Rx software queue + +private: + SerialData() {} + SerialData(const SerialData&); + SerialData& operator= (const SerialData&); +}; /** * \internal @@ -72,19 +87,20 @@ static Queue<char,SOFTWARE_RX_QUEUE> rxQueue;///<\internal Rx software queue void serialIrqImpl() __attribute__((noinline)); void serialIrqImpl() { + SerialData& s=SerialData::instance(); bool hppw=false; unsigned int status=USART1->SR; if(status & USART_SR_ORE) //Receiver overrun { char c=USART1->DR; //Always read data, since this clears interrupt flags if((status & USART_SR_RXNE) && ((status & 0x7)==0)) - rxQueue.IRQput(c,hppw); + s.rxQueue.IRQput(c,hppw); } else if(status & USART_SR_RXNE) //Receiver data available { char c=USART1->DR; //Always read data, since this clears interrupt flags if((status & 0x7)==0) //If no noise nor framing nor parity error { - rxQueue.IRQput(c,hppw); + s.rxQueue.IRQput(c,hppw); } } if(hppw) Scheduler::IRQfindNextThread(); @@ -92,7 +108,7 @@ void serialIrqImpl() void IRQstm32f2serialPortInit() { - rxQueue.IRQreset(); + SerialData::instance().rxQueue.IRQreset(); //Enable clock to GPIOA and USART1 RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN; RCC->APB2ENR |= RCC_APB2ENR_USART1EN; @@ -123,7 +139,7 @@ void IRQstm32f2serialPortInit() static void serialWriteImpl(const char *str, unsigned int len) { { - Lock<Mutex> l(txMutex); + Lock<Mutex> l(SerialData::instance().txMutex); for(unsigned int i=0;i<len;i++) { while((USART1->SR & USART_SR_TXE)==0) ; @@ -164,18 +180,20 @@ bool Console::IRQtxComplete() char Console::readChar() { - Lock<Mutex> l(rxMutex); + SerialData& s=SerialData::instance(); + Lock<Mutex> l(s.rxMutex); char result; - rxQueue.get(result); + s.rxQueue.get(result); return result; } bool Console::readCharNonBlocking(char& c) { - Lock<Mutex> l(rxMutex); - if(rxQueue.isEmpty()==false) + SerialData& s=SerialData::instance(); + Lock<Mutex> l(s.rxMutex); + if(s.rxQueue.isEmpty()==false) { - rxQueue.get(c); + s.rxQueue.get(c); return true; } return false; diff --git a/miosix/arch/cortexM3_stm32f2/stm32f207zg_EthBoardV2/core/stage_1_boot.cpp b/miosix/arch/cortexM3_stm32f2/stm32f207zg_EthBoardV2/core/stage_1_boot.cpp index 16c8c7af..386b8b61 100644 --- a/miosix/arch/cortexM3_stm32f2/stm32f207zg_EthBoardV2/core/stage_1_boot.cpp +++ b/miosix/arch/cortexM3_stm32f2/stm32f207zg_EthBoardV2/core/stage_1_boot.cpp @@ -7,8 +7,7 @@ * startup.cpp * STM32 C++ startup. * NOTE: for stm32f2 devices ONLY. - * - supports interrupt handlers in C++ without extern "C" - * - global constructors are correctly called before main() + * Supports interrupt handlers in C++ without extern "C" * Developed by Terraneo Federico, based on ST startup code. * Additionally modified to boot Miosix. */ @@ -17,23 +16,6 @@ //stage_2_boot.cpp extern "C" void _init(); -/** - * Calls C++ global constructors - * \param start first function pointer to call - * \param end one past the last function pointer to call - * Declared "noinline" to optimize code size - */ -static void call_constructors(unsigned long *start, unsigned long *end) __attribute__((noinline)); -static void call_constructors(unsigned long *start, unsigned long *end) -{ - for(unsigned long *i=start; i<end; i++) - { - void (*funcptr)(); - funcptr=reinterpret_cast<void (*)()>(*i); - funcptr(); - } -} - /** * Called by Reset_Handler, performs initialization and calls main. * Never returns. @@ -50,12 +32,6 @@ void program_startup() extern unsigned char _edata asm("_edata"); extern unsigned char _bss_start asm("_bss_start"); extern unsigned char _bss_end asm("_bss_end"); - extern unsigned long __preinit_array_start asm("__preinit_array_start"); - extern unsigned long __preinit_array_end asm("__preinit_array_end"); - extern unsigned long __init_array_start asm("__init_array_start"); - extern unsigned long __init_array_end asm("__init_array_end"); - extern unsigned long _ctor_start asm("_ctor_start"); - extern unsigned long _ctor_end asm("_ctor_end"); //Initialize .data section, clear .bss section unsigned char *etext=&_etext; @@ -70,11 +46,6 @@ void program_startup() memcpy(data, etext, edata-data); memset(bss_start, 0, bss_end-bss_start); - //Initialize C++ global constructors - call_constructors(&__preinit_array_start, &__preinit_array_end); - call_constructors(&__init_array_start, &__init_array_end); - call_constructors(&_ctor_start, &_ctor_end); - //Move on to stage 2 _init(); diff --git a/miosix/arch/cortexM3_stm32f2/stm32f207zg_EthBoardV2/interfaces-impl/console.cpp b/miosix/arch/cortexM3_stm32f2/stm32f207zg_EthBoardV2/interfaces-impl/console.cpp index 04ef0d7f..e75ca2b0 100644 --- a/miosix/arch/cortexM3_stm32f2/stm32f207zg_EthBoardV2/interfaces-impl/console.cpp +++ b/miosix/arch/cortexM3_stm32f2/stm32f207zg_EthBoardV2/interfaces-impl/console.cpp @@ -57,10 +57,25 @@ void USART1_IRQHandler() namespace miosix { -static Mutex rxMutex;///<\internal Mutex used to guard the rx queue -static Mutex txMutex;///<\internal Mutex used to guard the tx queue -const unsigned int SOFTWARE_RX_QUEUE=32;///<\internal Size of rx software queue -static Queue<char,SOFTWARE_RX_QUEUE> rxQueue;///<\internal Rx software queue +class SerialData +{ +public: + static SerialData& instance() + { + static SerialData s; + return s; + } + + Mutex rxMutex;///<\internal Mutex used to guard the rx queue + Mutex txMutex;///<\internal Mutex used to guard the tx queue + static const unsigned int SOFTWARE_RX_QUEUE=32;///<\internal Size of rx queue + Queue<char,SOFTWARE_RX_QUEUE> rxQueue;///<\internal Rx software queue + +private: + SerialData() {} + SerialData(const SerialData&); + SerialData& operator= (const SerialData&); +}; /** * \internal @@ -72,19 +87,20 @@ static Queue<char,SOFTWARE_RX_QUEUE> rxQueue;///<\internal Rx software queue void serialIrqImpl() __attribute__((noinline)); void serialIrqImpl() { + SerialData& s=SerialData::instance(); bool hppw=false; unsigned int status=USART1->SR; if(status & USART_SR_ORE) //Receiver overrun { char c=USART1->DR; //Always read data, since this clears interrupt flags if((status & USART_SR_RXNE) && ((status & 0x7)==0)) - rxQueue.IRQput(c,hppw); + s.rxQueue.IRQput(c,hppw); } else if(status & USART_SR_RXNE) //Receiver data available { char c=USART1->DR; //Always read data, since this clears interrupt flags if((status & 0x7)==0) //If no noise nor framing nor parity error { - rxQueue.IRQput(c,hppw); + s.rxQueue.IRQput(c,hppw); } } if(hppw) Scheduler::IRQfindNextThread(); @@ -92,7 +108,7 @@ void serialIrqImpl() void IRQstm32f2serialPortInit() { - rxQueue.IRQreset(); + SerialData::instance().rxQueue.IRQreset(); //Enable clock to GPIOA and USART1 RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN; RCC->APB2ENR |= RCC_APB2ENR_USART1EN; @@ -123,7 +139,7 @@ void IRQstm32f2serialPortInit() static void serialWriteImpl(const char *str, unsigned int len) { { - Lock<Mutex> l(txMutex); + Lock<Mutex> l(SerialData::instance().txMutex); for(unsigned int i=0;i<len;i++) { while((USART1->SR & USART_SR_TXE)==0) ; @@ -164,18 +180,20 @@ bool Console::IRQtxComplete() char Console::readChar() { - Lock<Mutex> l(rxMutex); + SerialData& s=SerialData::instance(); + Lock<Mutex> l(s.rxMutex); char result; - rxQueue.get(result); + s.rxQueue.get(result); return result; } bool Console::readCharNonBlocking(char& c) { - Lock<Mutex> l(rxMutex); - if(rxQueue.isEmpty()==false) + SerialData& s=SerialData::instance(); + Lock<Mutex> l(s.rxMutex); + if(s.rxQueue.isEmpty()==false) { - rxQueue.get(c); + s.rxQueue.get(c); return true; } return false; diff --git a/miosix/arch/cortexM3_stm32l1/stm32l151c8_als_mainboard/core/stage_1_boot.cpp b/miosix/arch/cortexM3_stm32l1/stm32l151c8_als_mainboard/core/stage_1_boot.cpp index cc404ea5..7c986c1f 100644 --- a/miosix/arch/cortexM3_stm32l1/stm32l151c8_als_mainboard/core/stage_1_boot.cpp +++ b/miosix/arch/cortexM3_stm32l1/stm32l151c8_als_mainboard/core/stage_1_boot.cpp @@ -7,8 +7,7 @@ * startup.cpp * STM32 C++ startup. * NOTE: for stm32l medium density devices ONLY. - * - supports interrupt handlers in C++ without extern "C" - * - global constructors are correctly called before main() + * Supports interrupt handlers in C++ without extern "C" * Developed by Terraneo Federico, based on ST startup code. * Additionally modified to boot Miosix. */ @@ -17,23 +16,6 @@ //stage_2_boot.cpp extern "C" void _init(); -/** - * Calls C++ global constructors - * \param start first function pointer to call - * \param end one past the last function pointer to call - * Declared "noinline" to optimize code size - */ -static void call_constructors(unsigned long *start, unsigned long *end) __attribute__((noinline)); -static void call_constructors(unsigned long *start, unsigned long *end) -{ - for(unsigned long *i=start; i<end; i++) - { - void (*funcptr)(); - funcptr=reinterpret_cast<void (*)()>(*i); - funcptr(); - } -} - /** * Called by Reset_Handler, performs initialization and calls main. * Never returns. @@ -50,12 +32,6 @@ void program_startup() extern unsigned char _edata asm("_edata"); extern unsigned char _bss_start asm("_bss_start"); extern unsigned char _bss_end asm("_bss_end"); - extern unsigned long __preinit_array_start asm("__preinit_array_start"); - extern unsigned long __preinit_array_end asm("__preinit_array_end"); - extern unsigned long __init_array_start asm("__init_array_start"); - extern unsigned long __init_array_end asm("__init_array_end"); - extern unsigned long _ctor_start asm("_ctor_start"); - extern unsigned long _ctor_end asm("_ctor_end"); //Initialize .data section, clear .bss section unsigned char *etext=&_etext; @@ -70,11 +46,6 @@ void program_startup() memcpy(data, etext, edata-data); memset(bss_start, 0, bss_end-bss_start); - //Initialize C++ global constructors - call_constructors(&__preinit_array_start, &__preinit_array_end); - call_constructors(&__init_array_start, &__init_array_end); - call_constructors(&_ctor_start, &_ctor_end); - //Move on to stage 2 _init(); diff --git a/miosix/arch/cortexM3_stm32l1/stm32l151c8_als_mainboard/interfaces-impl/console.cpp b/miosix/arch/cortexM3_stm32l1/stm32l151c8_als_mainboard/interfaces-impl/console.cpp index 75b059e9..deb89fc8 100644 --- a/miosix/arch/cortexM3_stm32l1/stm32l151c8_als_mainboard/interfaces-impl/console.cpp +++ b/miosix/arch/cortexM3_stm32l1/stm32l151c8_als_mainboard/interfaces-impl/console.cpp @@ -57,10 +57,26 @@ void USART1_IRQHandler() namespace miosix { -static Mutex rxMutex;///<\internal Mutex used to guard the rx queue -static Mutex txMutex;///<\internal Mutex used to guard the tx queue -const unsigned int SOFTWARE_RX_QUEUE=32;///<\internal Size of rx software queue -static Queue<char,SOFTWARE_RX_QUEUE> rxQueue;///<\internal Rx software queue + +class SerialData +{ +public: + static SerialData& instance() + { + static SerialData s; + return s; + } + + Mutex rxMutex;///<\internal Mutex used to guard the rx queue + Mutex txMutex;///<\internal Mutex used to guard the tx queue + static const unsigned int SOFTWARE_RX_QUEUE=32;///<\internal Size of rx queue + Queue<char,SOFTWARE_RX_QUEUE> rxQueue;///<\internal Rx software queue + +private: + SerialData() {} + SerialData(const SerialData&); + SerialData& operator= (const SerialData&); +}; /** * \internal @@ -72,19 +88,20 @@ static Queue<char,SOFTWARE_RX_QUEUE> rxQueue;///<\internal Rx software queue void serialIrqImpl() __attribute__((noinline)); void serialIrqImpl() { + SerialData& s=SerialData::instance(); bool hppw=false; unsigned int status=USART1->SR; if(status & USART_SR_ORE) //Receiver overrun { char c=USART1->DR; //Always read data, since this clears interrupt flags if((status & USART_SR_RXNE) && ((status & 0x7)==0)) - rxQueue.IRQput(c,hppw); + s.rxQueue.IRQput(c,hppw); } else if(status & USART_SR_RXNE) //Receiver data available { char c=USART1->DR; //Always read data, since this clears interrupt flags if((status & 0x7)==0) //If no noise nor framing nor parity error { - rxQueue.IRQput(c,hppw); + s.rxQueue.IRQput(c,hppw); } } if(hppw) Scheduler::IRQfindNextThread(); @@ -92,7 +109,7 @@ void serialIrqImpl() void IRQstm32f2serialPortInit() { - rxQueue.IRQreset(); + SerialData::instance().rxQueue.IRQreset(); //Enable clock to USART1 RCC->APB2ENR |= RCC_APB2ENR_USART1EN; //Enabled, 8 data bit, no parity, interrupt on character rx @@ -118,7 +135,7 @@ void IRQstm32f2serialPortInit() static void serialWriteImpl(const char *str, unsigned int len) { { - Lock<Mutex> l(txMutex); + Lock<Mutex> l(SerialData::instance().txMutex); for(unsigned int i=0;i<len;i++) { while((USART1->SR & USART_SR_TXE)==0) ; @@ -159,18 +176,20 @@ bool Console::IRQtxComplete() char Console::readChar() { - Lock<Mutex> l(rxMutex); + SerialData& s=SerialData::instance(); + Lock<Mutex> l(s.rxMutex); char result; - rxQueue.get(result); + s.rxQueue.get(result); return result; } bool Console::readCharNonBlocking(char& c) { - Lock<Mutex> l(rxMutex); - if(rxQueue.isEmpty()==false) + SerialData& s=SerialData::instance(); + Lock<Mutex> l(s.rxMutex); + if(s.rxQueue.isEmpty()==false) { - rxQueue.get(c); + s.rxQueue.get(c); return true; } return false; diff --git a/miosix/arch/cortexM4_stm32f4/stm32f407vg_bitsboard/core/stage_1_boot.cpp b/miosix/arch/cortexM4_stm32f4/stm32f407vg_bitsboard/core/stage_1_boot.cpp index 18bbad62..febde445 100644 --- a/miosix/arch/cortexM4_stm32f4/stm32f407vg_bitsboard/core/stage_1_boot.cpp +++ b/miosix/arch/cortexM4_stm32f4/stm32f407vg_bitsboard/core/stage_1_boot.cpp @@ -7,8 +7,7 @@ * startup.cpp * STM32 C++ startup. * NOTE: for stm32f4 devices ONLY. - * - supports interrupt handlers in C++ without extern "C" - * - global constructors are correctly called before main() + * Supports interrupt handlers in C++ without extern "C" * Developed by Terraneo Federico, based on ST startup code. * Additionally modified to boot Miosix. */ @@ -17,23 +16,6 @@ //stage_2_boot.cpp extern "C" void _init(); -/** - * Calls C++ global constructors - * \param start first function pointer to call - * \param end one past the last function pointer to call - * Declared "noinline" to optimize code size - */ -static void call_constructors(unsigned long *start, unsigned long *end) __attribute__((noinline)); -static void call_constructors(unsigned long *start, unsigned long *end) -{ - for(unsigned long *i=start; i<end; i++) - { - void (*funcptr)(); - funcptr=reinterpret_cast<void (*)()>(*i); - funcptr(); - } -} - /** * Called by Reset_Handler, performs initialization and calls main. * Never returns. @@ -62,12 +44,6 @@ void program_startup() extern unsigned char _edata asm("_edata"); extern unsigned char _bss_start asm("_bss_start"); extern unsigned char _bss_end asm("_bss_end"); - extern unsigned long __preinit_array_start asm("__preinit_array_start"); - extern unsigned long __preinit_array_end asm("__preinit_array_end"); - extern unsigned long __init_array_start asm("__init_array_start"); - extern unsigned long __init_array_end asm("__init_array_end"); - extern unsigned long _ctor_start asm("_ctor_start"); - extern unsigned long _ctor_end asm("_ctor_end"); //Initialize .data section, clear .bss section unsigned char *etext=&_etext; @@ -78,11 +54,6 @@ void program_startup() memcpy(data, etext, edata-data); memset(bss_start, 0, bss_end-bss_start); - //Initialize C++ global constructors - call_constructors(&__preinit_array_start, &__preinit_array_end); - call_constructors(&__init_array_start, &__init_array_end); - call_constructors(&_ctor_start, &_ctor_end); - //Move on to stage 2 _init(); diff --git a/miosix/arch/cortexM4_stm32f4/stm32f407vg_bitsboard/interfaces-impl/console.cpp b/miosix/arch/cortexM4_stm32f4/stm32f407vg_bitsboard/interfaces-impl/console.cpp index 050175fe..1ab9ea51 100644 --- a/miosix/arch/cortexM4_stm32f4/stm32f407vg_bitsboard/interfaces-impl/console.cpp +++ b/miosix/arch/cortexM4_stm32f4/stm32f407vg_bitsboard/interfaces-impl/console.cpp @@ -64,10 +64,25 @@ void USART3_IRQHandler() namespace miosix { -static Mutex rxMutex;///<\internal Mutex used to guard the rx queue -static Mutex txMutex;///<\internal Mutex used to guard the tx queue -const unsigned int SOFTWARE_RX_QUEUE=32;///<\internal Size of rx software queue -static Queue<char,SOFTWARE_RX_QUEUE> rxQueue;///<\internal Rx software queue +class SerialData +{ +public: + static SerialData& instance() + { + static SerialData s; + return s; + } + + Mutex rxMutex;///<\internal Mutex used to guard the rx queue + Mutex txMutex;///<\internal Mutex used to guard the tx queue + static const unsigned int SOFTWARE_RX_QUEUE=32;///<\internal Size of rx queue + Queue<char,SOFTWARE_RX_QUEUE> rxQueue;///<\internal Rx software queue + +private: + SerialData() {} + SerialData(const SerialData&); + SerialData& operator= (const SerialData&); +}; /** * \internal @@ -79,19 +94,20 @@ static Queue<char,SOFTWARE_RX_QUEUE> rxQueue;///<\internal Rx software queue void serialIrqImpl() __attribute__((noinline)); void serialIrqImpl() { + SerialData& s=SerialData::instance(); bool hppw=false; unsigned int status=USART3->SR; if(status & USART_SR_ORE) //Receiver overrun { char c=USART3->DR; //Always read data, since this clears interrupt flags if((status & USART_SR_RXNE) && ((status & 0x7)==0)) - rxQueue.IRQput(c,hppw); + s.rxQueue.IRQput(c,hppw); } else if(status & USART_SR_RXNE) //Receiver data available { char c=USART3->DR; //Always read data, since this clears interrupt flags if((status & 0x7)==0) //If no noise nor framing nor parity error { - rxQueue.IRQput(c,hppw); + s.rxQueue.IRQput(c,hppw); } } if(hppw) Scheduler::IRQfindNextThread(); @@ -99,7 +115,7 @@ void serialIrqImpl() void IRQBitsBoardSerialPortInit() { - rxQueue.IRQreset(); + SerialData::instance().rxQueue.IRQreset(); //Enable clock to USART3 RCC->APB1ENR |= RCC_APB1ENR_USART3EN; //Enabled, 8 data bit, no parity, interrupt on character rx @@ -129,7 +145,7 @@ void IRQBitsBoardSerialPortInit() static void serialWriteImpl(const char *str, unsigned int len) { { - Lock<Mutex> l(txMutex); + Lock<Mutex> l(SerialData::instance().txMutex); for(unsigned int i=0;i<len;i++) { while((USART3->SR & USART_SR_TXE)==0) ; @@ -170,18 +186,20 @@ bool Console::IRQtxComplete() char Console::readChar() { - Lock<Mutex> l(rxMutex); + SerialData& s=SerialData::instance(); + Lock<Mutex> l(s.rxMutex); char result; - rxQueue.get(result); + s.rxQueue.get(result); return result; } bool Console::readCharNonBlocking(char& c) { - Lock<Mutex> l(rxMutex); - if(rxQueue.isEmpty()==false) + SerialData& s=SerialData::instance(); + Lock<Mutex> l(s.rxMutex); + if(s.rxQueue.isEmpty()==false) { - rxQueue.get(c); + s.rxQueue.get(c); return true; } return false; diff --git a/miosix/arch/cortexM4_stm32f4/stm32f407vg_stm32f4discovery/core/stage_1_boot.cpp b/miosix/arch/cortexM4_stm32f4/stm32f407vg_stm32f4discovery/core/stage_1_boot.cpp index 18bbad62..febde445 100644 --- a/miosix/arch/cortexM4_stm32f4/stm32f407vg_stm32f4discovery/core/stage_1_boot.cpp +++ b/miosix/arch/cortexM4_stm32f4/stm32f407vg_stm32f4discovery/core/stage_1_boot.cpp @@ -7,8 +7,7 @@ * startup.cpp * STM32 C++ startup. * NOTE: for stm32f4 devices ONLY. - * - supports interrupt handlers in C++ without extern "C" - * - global constructors are correctly called before main() + * Supports interrupt handlers in C++ without extern "C" * Developed by Terraneo Federico, based on ST startup code. * Additionally modified to boot Miosix. */ @@ -17,23 +16,6 @@ //stage_2_boot.cpp extern "C" void _init(); -/** - * Calls C++ global constructors - * \param start first function pointer to call - * \param end one past the last function pointer to call - * Declared "noinline" to optimize code size - */ -static void call_constructors(unsigned long *start, unsigned long *end) __attribute__((noinline)); -static void call_constructors(unsigned long *start, unsigned long *end) -{ - for(unsigned long *i=start; i<end; i++) - { - void (*funcptr)(); - funcptr=reinterpret_cast<void (*)()>(*i); - funcptr(); - } -} - /** * Called by Reset_Handler, performs initialization and calls main. * Never returns. @@ -62,12 +44,6 @@ void program_startup() extern unsigned char _edata asm("_edata"); extern unsigned char _bss_start asm("_bss_start"); extern unsigned char _bss_end asm("_bss_end"); - extern unsigned long __preinit_array_start asm("__preinit_array_start"); - extern unsigned long __preinit_array_end asm("__preinit_array_end"); - extern unsigned long __init_array_start asm("__init_array_start"); - extern unsigned long __init_array_end asm("__init_array_end"); - extern unsigned long _ctor_start asm("_ctor_start"); - extern unsigned long _ctor_end asm("_ctor_end"); //Initialize .data section, clear .bss section unsigned char *etext=&_etext; @@ -78,11 +54,6 @@ void program_startup() memcpy(data, etext, edata-data); memset(bss_start, 0, bss_end-bss_start); - //Initialize C++ global constructors - call_constructors(&__preinit_array_start, &__preinit_array_end); - call_constructors(&__init_array_start, &__init_array_end); - call_constructors(&_ctor_start, &_ctor_end); - //Move on to stage 2 _init(); diff --git a/miosix/arch/cortexM4_stm32f4/stm32f407vg_stm32f4discovery/interfaces-impl/console.cpp b/miosix/arch/cortexM4_stm32f4/stm32f407vg_stm32f4discovery/interfaces-impl/console.cpp index 4874d317..3147ad92 100644 --- a/miosix/arch/cortexM4_stm32f4/stm32f407vg_stm32f4discovery/interfaces-impl/console.cpp +++ b/miosix/arch/cortexM4_stm32f4/stm32f407vg_stm32f4discovery/interfaces-impl/console.cpp @@ -64,10 +64,25 @@ void USART2_IRQHandler() namespace miosix { -static Mutex rxMutex;///<\internal Mutex used to guard the rx queue -static Mutex txMutex;///<\internal Mutex used to guard the tx queue -const unsigned int SOFTWARE_RX_QUEUE=32;///<\internal Size of rx software queue -static Queue<char,SOFTWARE_RX_QUEUE> rxQueue;///<\internal Rx software queue +class SerialData +{ +public: + static SerialData& instance() + { + static SerialData s; + return s; + } + + Mutex rxMutex;///<\internal Mutex used to guard the rx queue + Mutex txMutex;///<\internal Mutex used to guard the tx queue + static const unsigned int SOFTWARE_RX_QUEUE=32;///<\internal Size of rx queue + Queue<char,SOFTWARE_RX_QUEUE> rxQueue;///<\internal Rx software queue + +private: + SerialData() {} + SerialData(const SerialData&); + SerialData& operator= (const SerialData&); +}; /** * \internal @@ -79,19 +94,20 @@ static Queue<char,SOFTWARE_RX_QUEUE> rxQueue;///<\internal Rx software queue void serialIrqImpl() __attribute__((noinline)); void serialIrqImpl() { + SerialData& s=SerialData::instance(); bool hppw=false; unsigned int status=USART2->SR; if(status & USART_SR_ORE) //Receiver overrun { char c=USART2->DR; //Always read data, since this clears interrupt flags if((status & USART_SR_RXNE) && ((status & 0x7)==0)) - rxQueue.IRQput(c,hppw); + s.rxQueue.IRQput(c,hppw); } else if(status & USART_SR_RXNE) //Receiver data available { char c=USART2->DR; //Always read data, since this clears interrupt flags if((status & 0x7)==0) //If no noise nor framing nor parity error { - rxQueue.IRQput(c,hppw); + s.rxQueue.IRQput(c,hppw); } } if(hppw) Scheduler::IRQfindNextThread(); @@ -99,7 +115,7 @@ void serialIrqImpl() void IRQstm32f4serialPortInit() { - rxQueue.IRQreset(); + SerialData::instance().rxQueue.IRQreset(); //Enable clock to GPIOA and USART2 RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN; RCC->APB1ENR |= RCC_APB1ENR_USART2EN; @@ -133,7 +149,7 @@ void IRQstm32f4serialPortInit() static void serialWriteImpl(const char *str, unsigned int len) { { - Lock<Mutex> l(txMutex); + Lock<Mutex> l(SerialData::instance().txMutex); for(unsigned int i=0;i<len;i++) { while((USART2->SR & USART_SR_TXE)==0) ; @@ -174,18 +190,20 @@ bool Console::IRQtxComplete() char Console::readChar() { - Lock<Mutex> l(rxMutex); + SerialData& s=SerialData::instance(); + Lock<Mutex> l(SerialData::instance().rxMutex); char result; - rxQueue.get(result); + SerialData::instance().rxQueue.get(result); return result; } bool Console::readCharNonBlocking(char& c) { - Lock<Mutex> l(rxMutex); - if(rxQueue.isEmpty()==false) + SerialData& s=SerialData::instance(); + Lock<Mutex> l(s.rxMutex); + if(s.rxQueue.isEmpty()==false) { - rxQueue.get(c); + s.rxQueue.get(c); return true; } return false; diff --git a/miosix/check_global_objects.pl b/miosix/check_global_objects.pl new file mode 100644 index 00000000..82c86539 --- /dev/null +++ b/miosix/check_global_objects.pl @@ -0,0 +1,70 @@ +#!/usr/bin/perl + +# +# This program checks that there are no global objects in the kernel code. +# usage: perl check_global_objects.pl <list of .o files to check> +# returns 0 on success, 1 on failure. In this case the list of files with +# global objects will be printed. +# +# This program is useful to prevent the use of global constructors. +# This is because the use of global constructors in a kernel creates the +# problem of when to call those constructors. +# +# In Miosix up to 1.61 constructors were called as soon as possible, right +# after copying .data in RAM and clearing .bss, therefore before the kernel +# was started. This allowed to make use of global objects within the kernel, +# as their constructors were called before the objects were used. However, +# this created a problem with user code: also the global constructors of user +# code were called before the kernel was started, and this meant that an +# attempt to printf(), open files, create threads, or other operations possible +# only after the kernel is started would cause a crash of the kernel. +# +# To fix this in Miosix 2.0, global constructors are called as late as +# possible, right before calling main(), when the kernel is already started. +# However by doing so it is important that global constructors are never used +# inside the kernel itself, as this creates the possibility of accessing an +# object before its constructor is called. To be sure that this does not happen +# a way is needed to automatically check that no global constructors are used +# in the kernel code. Fortunately, this is possible, and this program does +# just that. +# + +use warnings; +use strict; + +my @broken_files; +foreach my $filename (@ARGV) +{ + # First, check that the argument is really an object file + die "$filename is not a file name." unless -f $filename; + die "$filename is not an object file." unless $filename=~/\.o$/; + + # Then use readelf to dump all sections of the file + my $output=`arm-miosix-eabi-readelf -SW \"$filename\"`; + my @lines=split("\n",$output); + + my $sections=0; + foreach my $line (@lines) + { + # Lines containing section information have the following format + # " [ 2] .text PROGBITS 00000000 000044 000088 00 AX 0 0 4" + next unless($line=~/^ \[ ?\d+\] (\S+) /); + $sections++; + + # Look for .preinit_array* .init_array* .fini_array* .ctors* .dtors* + # sections. These are the sign that the file has global constructors. + if($1=~/^\.preinit_array|^\.init_array|^\.ctors|^\.fini_array|^\.dtors/) + { + push(@broken_files,$filename); + } + } + + # Sanity check, if a file has no sections probably something is wrong + die "$filename has no sections. Something is wrong." unless $sections>0; +} + +if(@broken_files!=0) +{ + print("check_global_objects.pl: Error: @broken_files contain global constructors\n"); + exit(1); +} diff --git a/miosix/compiler/Readme.txt b/miosix/compiler/Readme.txt index 70ae37e6..9f949c86 100644 --- a/miosix/compiler/Readme.txt +++ b/miosix/compiler/Readme.txt @@ -19,10 +19,10 @@ Install the following dependencies: gcc, g++, make, ncurses, byacc, flex, texinfo, patch, gmp, mpfr, mpc, tar, unzip, libelf For example, for Ubuntu/Kubuntu open a shell and type: -sudo apt-get install gcc g++ make libncurses5-dev byacc flex texinfo patch libgmp3-dev libmpfr-dev libmpc-dev tar unzip libelf-dev +sudo apt-get install gcc g++ make libncurses5-dev byacc flex texinfo patch libgmp3-dev libmpfr-dev libmpc-dev tar unzip libelf-dev perl While on Fedora: -sudo yum intall gcc gcc-c++ make ncurses-devel byacc flex texinfo patch gmp-devel mpfr-devel libmpc-devel tar unzip elfutils-libelf-devel +sudo yum intall gcc gcc-c++ make ncurses-devel byacc flex texinfo patch gmp-devel mpfr-devel libmpc-devel tar unzip elfutils-libelf-devel perl Note: these scripts require "sudo". If you use a distro like Fedora where sudo is not enabled by default, use "visudo" to enable sudo for your account. You diff --git a/miosix/config/Makefile.inc b/miosix/config/Makefile.inc index 7dddd530..56ee2d60 100644 --- a/miosix/config/Makefile.inc +++ b/miosix/config/Makefile.inc @@ -259,8 +259,8 @@ endif ## Then, initialize C/C++ flags with -D_MIOSIX so that application code can ## know if the OS is MIOSIX ## -CFLAGS_BASE := -D_MIOSIX_BOARDNAME=\"$(OPT_BOARD)\" -CXXFLAGS_BASE := -D_MIOSIX_BOARDNAME=\"$(OPT_BOARD)\" +CFLAGS_BASE := -D_MIOSIX_BOARDNAME=\"$(OPT_BOARD)\" -Wno-unused-but-set-variable +CXXFLAGS_BASE := -D_MIOSIX_BOARDNAME=\"$(OPT_BOARD)\" -Wno-unused-but-set-variable ## ## Now two big switch-like constructs nested. The first lists all possible diff --git a/miosix/doc/textdoc/Changelog.txt b/miosix/doc/textdoc/Changelog.txt index 9b10e870..50539f50 100644 --- a/miosix/doc/textdoc/Changelog.txt +++ b/miosix/doc/textdoc/Changelog.txt @@ -1,5 +1,21 @@ Changelog for Miosix np embedded OS +- Changed version number from v1.61 to v20.alpha1 in version.cpp. +- Added -Wno-unused-but-set-variable to Makefile. +- Added testsuite check for global objects support outside of the kernel. +- Removed the use of global objects in the serial port drivers. +- Breaking change regarding constructors of global objects. Up to Miosix v1.61 + they were called during stage_1_boot, therefore before the kernel was + started. They are now called in stage_2_boot, right before calling main. + This results in a more intuitive behaviour, as it is now possible to + write on stdout, access the filesystem, create threads, etc. within + constructors of global objects. On the downside it is no longer possible to + instantiate global objects withing the kernel itself, as this would cause + the risk of accessing objects before their constructor has run. The lack of + global objects is actively check by check_global_objects.pl at compile time + to prevent errors. +- Changed stm32vldiscovery default stdio redirection from the DCC to the + serial port. - Added stm32f4 sdio driver, tested on stm32f4discovery. - Improved the SDIO drivers for both stm32f1 and stm32f2. It now uses DMA transfers whenever possible. In the stm32f2 it is always possible, diff --git a/miosix/kernel/filesystem/filesystem.cpp b/miosix/kernel/filesystem/filesystem.cpp index 3133163e..66785d8d 100644 --- a/miosix/kernel/filesystem/filesystem.cpp +++ b/miosix/kernel/filesystem/filesystem.cpp @@ -36,7 +36,16 @@ namespace miosix { -static Mutex fsMutex;///\internal This Mutex is used to guard access to the fs. +/** + * \internal + * \return the Mutex that is used to guard access to the fs. + */ +Mutex& getFsMutex() +{ + static Mutex fsMutex; + return fsMutex; +} + // // class Filesystem @@ -54,7 +63,7 @@ char Filesystem::mount() if(mounted==true) return 3; //If filesystem already mounted, return error char result=0; { - Lock<Mutex> l(fsMutex); + Lock<Mutex> l(getFsMutex()); //Mount filesystem if(f_mount(0,&filesystem)!=FR_OK) result=1; //Fatfs will delay actual filesystem mount until the first request is @@ -68,7 +77,7 @@ char Filesystem::mount() void Filesystem::umount() { - Lock<Mutex> l(fsMutex); + Lock<Mutex> l(getFsMutex()); if(mounted==false) return; mounted=false; @@ -92,7 +101,7 @@ int Filesystem::openFile(const char *name, int flags, int mode) if(isMounted()==false) return -1; { - Lock<Mutex> l(fsMutex); + Lock<Mutex> l(getFsMutex()); int index=findAndFillEmptySlot();//Also fills in the file descriptor if(index==-1) return -1; @@ -160,7 +169,7 @@ int Filesystem::readFile(int fd, void *buffer, int bufSize) if(isMounted()==false) return -1; { - Lock<Mutex> l(fsMutex); + Lock<Mutex> l(getFsMutex()); //Find file from descriptor int index=findSlot(fd); @@ -179,7 +188,7 @@ int Filesystem::writeFile(int fd, const void *buffer, int bufSize) if(isMounted()==false) return -1; { - Lock<Mutex> l(fsMutex); + Lock<Mutex> l(getFsMutex()); //Find file from descriptor int index=findSlot(fd); @@ -203,7 +212,7 @@ int Filesystem::lseekFile(int fd, int pos, int whence) if(isMounted()==false) return -1; { - Lock<Mutex> l(fsMutex); + Lock<Mutex> l(getFsMutex()); //Find file from descriptor int index=findSlot(fd); @@ -236,7 +245,7 @@ int Filesystem::fstatFile(int fd, struct stat *pstat) if(isMounted()==false) return -1; { - Lock<Mutex> l(fsMutex); + Lock<Mutex> l(getFsMutex()); //Find file from descriptor int index=findSlot(fd); @@ -256,7 +265,7 @@ int Filesystem::statFile(const char *file, struct stat *pstat) if(isMounted()==false) return -1; FILINFO info; { - Lock<Mutex> l(fsMutex); + Lock<Mutex> l(getFsMutex()); if(f_stat(file,&info)!=FR_OK) return -1; } memset(pstat,0,sizeof(struct stat)); @@ -272,7 +281,7 @@ int Filesystem::closeFile(int fd) if(isMounted()==false) return -1; { - Lock<Mutex> l(fsMutex); + Lock<Mutex> l(getFsMutex()); //Find file from descriptor int index=findSlot(fd); @@ -297,7 +306,7 @@ int Filesystem::mkdir(const char *path, int mode) if(isMounted()==false) return -1; { - Lock<Mutex> l(fsMutex); + Lock<Mutex> l(getFsMutex()); switch(f_mkdir(path)) { case FR_OK: @@ -315,7 +324,7 @@ int Filesystem::unlink(const char *path) if(isMounted()==false) return -1; { - Lock<Mutex> l(fsMutex); + Lock<Mutex> l(getFsMutex()); if(f_unlink(path)!=FR_OK) return -1; return 0; } @@ -416,7 +425,7 @@ char Directory::open(const char *name) if(Filesystem::instance().isMounted()==false) return 3; { - Lock<Mutex> l(fsMutex); + Lock<Mutex> l(getFsMutex()); if(f_opendir(&d,name)!=FR_OK) return 1; return 0; } @@ -426,7 +435,7 @@ bool Directory::next(char *name, unsigned int& size, unsigned char& attrib) { FILINFO fi; { - Lock<Mutex> l(fsMutex); + Lock<Mutex> l(getFsMutex()); if(f_readdir(&d,&fi)!=FR_OK) return false; } diff --git a/miosix/kernel/stage_2_boot.cpp b/miosix/kernel/stage_2_boot.cpp index c38d434a..afa2a5b2 100644 --- a/miosix/kernel/stage_2_boot.cpp +++ b/miosix/kernel/stage_2_boot.cpp @@ -53,6 +53,21 @@ extern int main(int argc, char *argv[]); namespace miosix { +/** + * Calls C++ global constructors + * \param start first function pointer to call + * \param end one past the last function pointer to call + */ +static void call_constructors(unsigned long *start, unsigned long *end) +{ + for(unsigned long *i=start; i<end; i++) + { + void (*funcptr)(); + funcptr=reinterpret_cast<void (*)()>(*i); + funcptr(); + } +} + /** * \internal * Performs the part of initialization that must be done after the kernel is @@ -96,6 +111,17 @@ static void mainLoader(void *argv) MemoryProfiling::getHeapSize()); #endif + //Initialize C++ global constructors + extern unsigned long __preinit_array_start asm("__preinit_array_start"); + extern unsigned long __preinit_array_end asm("__preinit_array_end"); + extern unsigned long __init_array_start asm("__init_array_start"); + extern unsigned long __init_array_end asm("__init_array_end"); + extern unsigned long _ctor_start asm("_ctor_start"); + extern unsigned long _ctor_end asm("_ctor_end"); + call_constructors(&__preinit_array_start, &__preinit_array_end); + call_constructors(&__init_array_start, &__init_array_end); + call_constructors(&_ctor_start, &_ctor_end); + //Run application code #ifdef __NO_EXCEPTIONS main(0,NULL); diff --git a/miosix/testsuite/testsuite.cpp b/miosix/testsuite/testsuite.cpp index 6950a9cc..80ecfa70 100644 --- a/miosix/testsuite/testsuite.cpp +++ b/miosix/testsuite/testsuite.cpp @@ -2233,6 +2233,8 @@ tests: C++ static constructors */ +static unsigned char t17_v1=0; + class TestStaticConstructor { public: @@ -2252,6 +2254,14 @@ static TestStaticConstructor& instance() return singleton; } +class TestOneCallToStaticConstructor +{ +public: + TestOneCallToStaticConstructor() { t17_v1++; } +}; + +TestOneCallToStaticConstructor t17_v2; + static void test_17() { test_name("static constructors"); @@ -2260,6 +2270,8 @@ static void test_17() iprintf("a=0x%x, b=0x%x\n",instance().a, instance().b); fail("constructor fail"); } + // Fails both if never called or if called multiple times + if(t17_v1!=1) fail("Constructor error"); pass(); } diff --git a/miosix/util/version.cpp b/miosix/util/version.cpp index 25a5d730..0f29366d 100644 --- a/miosix/util/version.cpp +++ b/miosix/util/version.cpp @@ -37,7 +37,7 @@ namespace miosix { #define AU #endif -const char AU ver[]="Miosix v1.61 (" _MIOSIX_BOARDNAME ", " __DATE__ " " __TIME__ CV ")"; +const char AU ver[]="Miosix v2.0alpha1 (" _MIOSIX_BOARDNAME ", " __DATE__ " " __TIME__ CV ")"; const char *getMiosixVersion() { diff --git a/miosix_np_2/nbproject/private/private.xml b/miosix_np_2/nbproject/private/private.xml index e67bac43..2bcf1ef4 100644 --- a/miosix_np_2/nbproject/private/private.xml +++ b/miosix_np_2/nbproject/private/private.xml @@ -5,7 +5,7 @@ </code-assistance-data> <data xmlns="http://www.netbeans.org/ns/make-project-private/1"> <activeConfTypeElem>0</activeConfTypeElem> - <activeConfIndexElem>9</activeConfIndexElem> + <activeConfIndexElem>2</activeConfIndexElem> </data> <editor-bookmarks xmlns="http://www.netbeans.org/ns/editor-bookmarks/1"/> </project-private> -- GitLab