int ICACHE_FLASH_ATTR dhsender_queue_add(REQUEST_TYPE type, REQUEST_NOTIFICATION_TYPE notification_type, REQUEST_DATA_TYPE data_type, unsigned int id, va_list ap) { ETS_INTR_LOCK(); if(mQueueAddPos == mQueueTakePos) { ETS_INTR_UNLOCK(); dhdebug("ERROR: no space for request"); return 0; } mQueue[mQueueAddPos].id = id; mQueue[mQueueAddPos].type = type; mQueue[mQueueAddPos].data_type = data_type; mQueue[mQueueAddPos].notification_type = notification_type; dhsender_data_parse_va(ap, &data_type, &mQueue[mQueueAddPos].data, &mQueue[mQueueAddPos].data_len, &mQueue[mQueueAddPos].pin); if(mQueueTakePos < 0) mQueueTakePos = mQueueAddPos; if(mQueueAddPos >= mQueueMaxSize - 1) mQueueAddPos = 0; else mQueueAddPos++; mQueueSize++; if(mQueueSize > RESERVE_FOR_RESPONCE) dhmem_block(); ETS_INTR_UNLOCK(); return 1; }
UP_STATUS ICACHE_FLASH_ATTR uploadable_page_put(const char *data, unsigned int data_len) { if(mBuffer == NULL) return UP_STATUS_WRONG_CALL; if(mFlashingSector > UPLOADABLE_PAGE_END_SECTOR) return UP_STATUS_OVERFLOW; reset_timer(); ETS_INTR_LOCK(); while(data_len) { uint32_t tocopy = (data_len > (SPI_FLASH_SEC_SIZE - mBufferPos)) ? (SPI_FLASH_SEC_SIZE - mBufferPos): data_len; os_memcpy(&mBuffer[mBufferPos], data, tocopy); mBufferPos += tocopy; data_len -= tocopy; data += tocopy; if(mBufferPos == SPI_FLASH_SEC_SIZE) { SpiFlashOpResult res = flash_data(); mBufferPos = 0; if(res != SPI_FLASH_RESULT_OK) { ETS_INTR_UNLOCK(); dhdebug("Error while writing page at 0x%X", mFlashingSector * SPI_FLASH_SEC_SIZE); return UP_STATUS_INTERNAL_ERROR; } } } ETS_INTR_UNLOCK(); return UP_STATUS_OK; }
UP_STATUS ICACHE_FLASH_ATTR uploadable_page_finish() { if(mBuffer == NULL) return UP_STATUS_WRONG_CALL; os_timer_disarm(&mFlashingTimer); ETS_INTR_LOCK(); // Mark data with null terminated char. If data takes whole available space, // there is no need in null terminated char. // At this point buffer should have at lest 1 free byte, since buffer // reaches maximum size before, it had to be written to flash. // If nothing was written, just report ok. SpiFlashOpResult res = SPI_FLASH_RESULT_OK; if(mBufferPos) { mBuffer[mBufferPos] = 0; mBufferPos++; res = flash_data(); } else if(mFlashingSector > UPLOADABLE_PAGE_START_SECTOR && mFlashingSector <= UPLOADABLE_PAGE_END_SECTOR) { res = write_zero_byte(mFlashingSector); } mBufferPos = 0; os_free(mBuffer); mBuffer = NULL; // force to recalc page size mPageLength = 0; ETS_INTR_UNLOCK(); if(res != SPI_FLASH_RESULT_OK) { dhdebug("Error while finishing flash page"); return UP_STATUS_INTERNAL_ERROR; } dhdebug("Flashing page has finished successfully"); return UP_STATUS_OK; }
void vPortFree(void *pv, const char * file, unsigned line) #endif { uint8_t *puc = ( uint8_t * ) pv; BlockLink_t *pxLink; if( pv != NULL ) { /* The memory being freed will have an BlockLink_t structure immediately before it. */ puc -= uxHeapStructSize; /* This casting is to keep the compiler from issuing warnings. */ pxLink = ( void * ) puc; /* Check the block is actually allocated. */ configASSERT( ( pxLink->xBlockSize & xBlockAllocatedBit ) != 0 ); configASSERT( pxLink->pxNextFreeBlock == NULL ); if( ( pxLink->xBlockSize & xBlockAllocatedBit ) != 0 ) { #ifndef MEMLEAK_DEBUG if( pxLink->pxNextFreeBlock == NULL ) #endif { /* The block is being returned to the heap - it is no longer allocated. */ pxLink->xBlockSize &= ~xBlockAllocatedBit; //vTaskSuspendAll(); ETS_INTR_LOCK(); #ifdef MEMLEAK_DEBUG if(prvRemoveBlockFromUsedList(pxLink) < 0){ ets_printf("%x already freed\n", pv); } else #endif { /* Add this block to the list of free blocks. */ xFreeBytesRemaining += pxLink->xBlockSize; traceFREE( pv, pxLink->xBlockSize ); prvInsertBlockIntoFreeList( ( ( BlockLink_t * ) pxLink ) ); } // ( void ) xTaskResumeAll(); ETS_INTR_UNLOCK(); } #ifndef MEMLEAK_DEBUG else { mtCOVERAGE_TEST_MARKER(); } #endif } else { mtCOVERAGE_TEST_MARKER(); } } }
int ICACHE_FLASH_ATTR dhsender_queue_take(HTTP_REQUEST *out, unsigned int *is_notification) { if(mQueueTakePos < 0) return 0; ETS_INTR_LOCK(); DHSENDER_QUEUE item; os_memcpy(&item, &mQueue[mQueueTakePos], sizeof(DHSENDER_QUEUE)); if(mQueueTakePos >= mQueueMaxSize - 1) mQueueTakePos = 0; else mQueueTakePos++; if(mQueueAddPos == mQueueTakePos) mQueueTakePos = -1; mQueueSize--; ETS_INTR_UNLOCK(); if(mQueueSize < MEM_RECOVER_THRESHOLD && dhmem_isblock()) dhmem_unblock(); char buf[HTTP_REQUEST_MIN_ALLOWED_PAYLOAD]; if(dhsender_data_to_json(buf, sizeof(buf), item.notification_type == RNT_NOTIFICATION_GPIO, item.data_type, &item.data, item.data_len, item.pin) < 0) { snprintf(buf, sizeof(buf), "Failed to convert data to json"); item.type = RT_RESPONCE_ERROR; } *is_notification = 0; switch(item.type) { case RT_RESPONCE_OK: case RT_RESPONCE_ERROR: dhrequest_create_update(out, item.id, (item.type == RT_RESPONCE_OK) ? STATUS_OK : STATUS_ERROR, buf); break; case RT_NOTIFICATION: *is_notification = 1; switch(item.notification_type) { case RNT_NOTIFICATION_GPIO: dhrequest_create_notification(out, "gpio/int", buf); break; case RNT_NOTIFICATION_ADC: dhrequest_create_notification(out, "adc/int", buf); break; case RNT_NOTIFICATION_UART: dhrequest_create_notification(out, "uart/int", buf); break; case RNT_NOTIFICATION_ONEWIRE: dhrequest_create_notification(out, "onewire/master/int", buf); break; default: dhdebug("ERROR: Unknown notification type of request %d", item.notification_type); return 0; } break; default: dhdebug("ERROR: Unknown type of request %d", item.type); return 0; } return 1; }
void Hardware_Timer::setCallback(InterruptCallback interrupt) { ETS_INTR_LOCK(); callback = interrupt; ETS_INTR_UNLOCK(); if (!interrupt) stop(); }
void Timer::setCallback(InterruptCallback interrupt/* = NULL*/) { ETS_INTR_LOCK(); callback = interrupt; delegate_func = nullptr; ETS_INTR_UNLOCK(); if (!interrupt) stop(); }
void Timer::setCallback(Delegate<void()> delegateFunction) { ETS_INTR_LOCK(); callback = nullptr; delegate_func = delegateFunction; ETS_INTR_UNLOCK(); if (!delegateFunction) stop(); }
void pvShowMalloc() { BlockLink_t *pxIterator; //ets_printf("sh0:%d,%d,",uxHeapStructSize,sizeof( BlockLink_t )); if(uxHeapStructSize < sizeof( BlockLink_t )) return; ETS_INTR_LOCK(); Wait_SPI_Idle(&flashchip); Cache_Read_Enable_New(); //ets_printf("sh1,"); os_printf("--------Show Malloc--------\n"); for( pxIterator = &yStart; pxIterator->pxNextFreeBlock != NULL;pxIterator = pxIterator->pxNextFreeBlock) { char file_name[33]; const char *file_name_printf; //ets_printf("sh2,"); file_name_printf = vGetFileName(file_name, pxIterator->pxNextFreeBlock->file); os_printf("F:%s\tL:%u\tmalloc %d\t@ %x\n", file_name_printf, pxIterator->pxNextFreeBlock->line, pxIterator->pxNextFreeBlock->xBlockSize - 0x80000000, ( void * ) ( ( ( unsigned char * ) pxIterator->pxNextFreeBlock ) + uxHeapStructSize)); //ets_printf("sh3,"); // ets_delay_us(2000); system_soft_wdt_feed(); } os_printf("--------Free %d--------\n\n", xFreeBytesRemaining); #if 0 uint32 last_link = (uint32)yStart.pxNextFreeBlock; uint32 index = 0; os_printf("'*':used, '-'free, each %d bytes\n", portBYTE_ALIGNMENT_v); os_printf("%x:", last_link); for( pxIterator = &yStart; pxIterator->pxNextFreeBlock != NULL;pxIterator = pxIterator->pxNextFreeBlock) { uint16 i; for (i = 0; i < ((uint32)pxIterator->pxNextFreeBlock - last_link) / portBYTE_ALIGNMENT_v; i++) { index++; os_printf("-"); if (index % 64 == 0) { os_printf("\n%x:", (uint32)yStart.pxNextFreeBlock + index * portBYTE_ALIGNMENT_v); } } for (i = 0; i < pxIterator->pxNextFreeBlock->xBlockSize / portBYTE_ALIGNMENT_v; i++) { index++; os_printf("*"); if (index % 64 == 0) { os_printf("\n%x:", (uint32)yStart.pxNextFreeBlock + index * portBYTE_ALIGNMENT_v); } } last_link = ((uint32)pxIterator->pxNextFreeBlock + pxIterator->pxNextFreeBlock->xBlockSize); system_soft_wdt_feed(); } os_printf("\n\n"); #endif //ets_printf("sh4\n"); ETS_INTR_UNLOCK(); }
bool spiffs_format_internal(spiffs_config *cfg) { if (cfg->phys_addr == 0) { SYSTEM_ERROR("Can't format file system, wrong address"); return false; } u32_t sect_first, sect_last; sect_first = cfg->phys_addr; sect_first = flashmem_get_sector_of_address(sect_first); sect_last = cfg->phys_addr + cfg->phys_size; sect_last = flashmem_get_sector_of_address(sect_last); debugf("sect_first: %x, sect_last: %x\n", sect_first, sect_last); ETS_INTR_LOCK(); int total = sect_last - sect_first; int cur = 0; int last = -1; while( sect_first <= sect_last ) { if(flashmem_erase_sector( sect_first++ )) { int percent = cur++ * 100 / total; if (percent > last) debugf("%d%%", percent); last = percent; } else { ETS_INTR_UNLOCK(); return false; } } debugf("formated"); ETS_INTR_UNLOCK(); }
bool Servo::removeChannel(ServoChannel* channel) { if (channels.removeElement(channel)) { ETS_INTR_LOCK(); getPins(); calcTiming(); ETS_INTR_UNLOCK(); if (channels.size() == 0) { started = false; hardwareTimer.stop(); } return true; } return false; }
UP_STATUS ICACHE_FLASH_ATTR uploadable_page_begin() { ETS_INTR_LOCK(); if(mBuffer == NULL) { mBuffer = (char *)os_malloc(SPI_FLASH_SEC_SIZE); } mBufferPos = 0; mFlashingSector = UPLOADABLE_PAGE_START_SECTOR; ETS_INTR_UNLOCK(); if(mBuffer == NULL) { dhdebug("No memory to initialize page flashing"); return UP_STATUS_INTERNAL_ERROR; } reset_timer(); dhdebug("Page flashing is initialized"); return UP_STATUS_OK; }
bool uart_getc(char *c){ RcvMsgBuff *pRxBuff = &(UartDev.rcv_buff); if(pRxBuff->pWritePos == pRxBuff->pReadPos){ // empty return false; } // ETS_UART_INTR_DISABLE(); ETS_INTR_LOCK(); *c = (char)*(pRxBuff->pReadPos); if (pRxBuff->pReadPos == (pRxBuff->pRcvMsgBuff + RX_BUFF_SIZE)) { pRxBuff->pReadPos = pRxBuff->pRcvMsgBuff ; } else { pRxBuff->pReadPos++; } // ETS_UART_INTR_ENABLE(); ETS_INTR_UNLOCK(); return true; }
bool Servo::addChannel(ServoChannel* channel) { uint8 channel_count = channels.size(); if (channel_count > SERVO_CHANNEL_NUM_MAX) return false; channels.add(channel); ETS_INTR_LOCK(); getPins(); calcTiming(); ETS_INTR_UNLOCK(); if (!started) { started = true; hardwareTimer.initializeUs(100000,ServoTimerInt); hardwareTimer.startOnce(); } return true; }
void vPortFree( void *pv ) { unsigned char *puc = ( unsigned char * ) pv; xBlockLink *pxLink; // printf("%s\n", __func__); if( pv != NULL ) { /* The memory being freed will have an xBlockLink structure immediately before it. */ puc -= heapSTRUCT_SIZE; /* This casting is to keep the compiler from issuing warnings. */ pxLink = ( void * ) puc; /* Check the block is actually allocated. */ configASSERT( ( pxLink->xBlockSize & xBlockAllocatedBit ) != 0 ); configASSERT( pxLink->pxNextFreeBlock == NULL ); if( ( pxLink->xBlockSize & xBlockAllocatedBit ) != 0 ) { if( pxLink->pxNextFreeBlock == NULL ) { /* The block is being returned to the heap - it is no longer allocated. */ pxLink->xBlockSize &= ~xBlockAllocatedBit; // vTaskSuspendAll(); ETS_INTR_LOCK(); { /* Add this block to the list of free blocks. */ xFreeBytesRemaining += pxLink->xBlockSize; prvInsertBlockIntoFreeList( ( ( xBlockLink * ) pxLink ) ); } // xTaskResumeAll(); ETS_INTR_UNLOCK(); } } } // printf("%s %x %d\n", __func__, pv, xFreeBytesRemaining); }
LOCAL void ICACHE_FLASH_ATTR recover_led(void *arg) { ETS_INTR_LOCK(); PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0TXD_U, FUNC_GPIO1); gpio_output_set(0, 0x2, 0x2, 0); ETS_INTR_UNLOCK(); }
void *pvPortMalloc( size_t xWantedSize ) { xBlockLink *pxBlock, *pxPreviousBlock, *pxNewBlockLink; void *pvReturn = NULL; // printf("%s %d %d\n", __func__, xWantedSize, xFreeBytesRemaining); // vTaskSuspendAll(); ETS_INTR_LOCK(); { /* If this is the first call to malloc then the heap will require initialisation to setup the list of free blocks. */ if( pxEnd == NULL ) { prvHeapInit(); } /* Check the requested block size is not so large that the top bit is set. The top bit of the block size member of the xBlockLink structure is used to determine who owns the block - the application or the kernel, so it must be free. */ if( ( xWantedSize & xBlockAllocatedBit ) == 0 ) { /* The wanted size is increased so it can contain a xBlockLink structure in addition to the requested amount of bytes. */ if( xWantedSize > 0 ) { xWantedSize += heapSTRUCT_SIZE; /* Ensure that blocks are always aligned to the required number of bytes. */ if( ( xWantedSize & portBYTE_ALIGNMENT_MASK ) != 0x00 ) { /* Byte alignment required. */ xWantedSize += ( portBYTE_ALIGNMENT - ( xWantedSize & portBYTE_ALIGNMENT_MASK ) ); } } if( ( xWantedSize > 0 ) && ( xWantedSize <= xFreeBytesRemaining ) ) { /* Traverse the list from the start (lowest address) block until one of adequate size is found. */ pxPreviousBlock = &xStart; pxBlock = xStart.pxNextFreeBlock; while( ( pxBlock->xBlockSize < xWantedSize ) && ( pxBlock->pxNextFreeBlock != NULL ) ) { pxPreviousBlock = pxBlock; pxBlock = pxBlock->pxNextFreeBlock; } /* If the end marker was reached then a block of adequate size was not found. */ if( pxBlock != pxEnd ) { /* Return the memory space pointed to - jumping over the xBlockLink structure at its start. */ pvReturn = ( void * ) ( ( ( unsigned char * ) pxPreviousBlock->pxNextFreeBlock ) + heapSTRUCT_SIZE ); /* This block is being returned for use so must be taken out of the list of free blocks. */ pxPreviousBlock->pxNextFreeBlock = pxBlock->pxNextFreeBlock; /* If the block is larger than required it can be split into two. */ if( ( pxBlock->xBlockSize - xWantedSize ) > heapMINIMUM_BLOCK_SIZE ) { /* This block is to be split into two. Create a new block following the number of bytes requested. The void cast is used to prevent byte alignment warnings from the compiler. */ pxNewBlockLink = ( void * ) ( ( ( unsigned char * ) pxBlock ) + xWantedSize ); /* Calculate the sizes of two blocks split from the single block. */ pxNewBlockLink->xBlockSize = pxBlock->xBlockSize - xWantedSize; pxBlock->xBlockSize = xWantedSize; /* Insert the new block into the list of free blocks. */ prvInsertBlockIntoFreeList( ( pxNewBlockLink ) ); } xFreeBytesRemaining -= pxBlock->xBlockSize; /* The block is being returned - it is allocated and owned by the application and has no "next" block. */ pxBlock->xBlockSize |= xBlockAllocatedBit; pxBlock->pxNextFreeBlock = NULL; } } } } // xTaskResumeAll(); ETS_INTR_UNLOCK(); #if( configUSE_MALLOC_FAILED_HOOK == 1 ) { if( pvReturn == NULL ) { extern void vApplicationMallocFailedHook( void ); vApplicationMallocFailedHook(); } } #endif // printf("%s %x %x\n", __func__, pvReturn, pxBlock); return pvReturn; }
void *pvPortMalloc( size_t xWantedSize, const char * file, unsigned line, bool use_iram) #endif { BlockLink_t *pxBlock, *pxPreviousBlock, *pxNewBlockLink; void *pvReturn = NULL; static bool is_inited = false; if (!is_inited) { void vPortDefineHeapRegions( const HeapRegion_t * const pxHeapRegions ); xHeapRegions[0].pucStartAddress = ( uint8_t * )&_heap_start; xHeapRegions[0].xSizeInBytes = (( size_t)( 0x40000000 - (uint32)&_heap_start)); xHeapRegions[1].pucStartAddress = ( uint8_t * )&_lit4_end; xHeapRegions[1].xSizeInBytes = (( size_t)( 0x4010C000 - (uint32)&_lit4_end)); is_inited = true; vPortDefineHeapRegions(xHeapRegions); } /* The heap must be initialised before the first call to prvPortMalloc(). */ configASSERT( pxEnd ); // vTaskSuspendAll(); ETS_INTR_LOCK(); { /* Check the requested block size is not so large that the top bit is set. The top bit of the block size member of the BlockLink_t structure is used to determine who owns the block - the application or the kernel, so it must be free. */ if( ( xWantedSize & xBlockAllocatedBit ) == 0 ) { /* The wanted size is increased so it can contain a BlockLink_t structure in addition to the requested amount of bytes. */ if( xWantedSize > 0 ) { xWantedSize += uxHeapStructSize; /* Ensure that blocks are always aligned to the required number of bytes. */ if( ( xWantedSize & portBYTE_ALIGNMENT_MASK ) != 0x00 ) { /* Byte alignment required. */ xWantedSize += ( portBYTE_ALIGNMENT - ( xWantedSize & portBYTE_ALIGNMENT_MASK ) ); } else { mtCOVERAGE_TEST_MARKER(); } } else { mtCOVERAGE_TEST_MARKER(); } if( ( xWantedSize > 0 ) && ( xWantedSize <= xFreeBytesRemaining ) ) { /* Traverse the list from the start (lowest address) block until one of adequate size is found. */ pxPreviousBlock = &xStart; pxBlock = xStart.pxNextFreeBlock; BlockLink_t *pxIterator; /* Iterate through the list until a block is found that has a higher address than the block being inserted. */ for( pxIterator = &xStart; pxIterator->pxNextFreeBlock != 0; pxIterator = pxIterator->pxNextFreeBlock ) { if ((line == 0 || use_iram == true) && (uint32)pxIterator->pxNextFreeBlock > 0x40000000 && pxIterator->pxNextFreeBlock->xBlockSize > xWantedSize) { pxPreviousBlock = pxIterator; pxBlock = pxIterator->pxNextFreeBlock; break; } } while( ( pxBlock->xBlockSize < xWantedSize ) && ( pxBlock->pxNextFreeBlock != NULL ) ) { pxPreviousBlock = pxBlock; pxBlock = pxBlock->pxNextFreeBlock; } /* If the end marker was reached then a block of adequate size was not found. */ if( pxBlock != pxEnd ) { /* Return the memory space pointed to - jumping over the BlockLink_t structure at its start. */ pvReturn = ( void * ) ( ( ( uint8_t * ) pxPreviousBlock->pxNextFreeBlock ) + uxHeapStructSize ); /* This block is being returned for use so must be taken out of the list of free blocks. */ pxPreviousBlock->pxNextFreeBlock = pxBlock->pxNextFreeBlock; /* If the block is larger than required it can be split into two. */ if( ( pxBlock->xBlockSize - xWantedSize ) > heapMINIMUM_BLOCK_SIZE ) { /* This block is to be split into two. Create a new block following the number of bytes requested. The void cast is used to prevent byte alignment warnings from the compiler. */ pxNewBlockLink = ( void * ) ( ( ( uint8_t * ) pxBlock ) + xWantedSize ); /* Calculate the sizes of two blocks split from the single block. */ pxNewBlockLink->xBlockSize = pxBlock->xBlockSize - xWantedSize; pxBlock->xBlockSize = xWantedSize; /* Insert the new block into the list of free blocks. */ prvInsertBlockIntoFreeList( ( pxNewBlockLink ) ); } else { mtCOVERAGE_TEST_MARKER(); } xFreeBytesRemaining -= pxBlock->xBlockSize; if( xFreeBytesRemaining < xMinimumEverFreeBytesRemaining ) { xMinimumEverFreeBytesRemaining = xFreeBytesRemaining; } else { mtCOVERAGE_TEST_MARKER(); } /* The block is being returned - it is allocated and owned by the application and has no "next" block. */ pxBlock->xBlockSize |= xBlockAllocatedBit; pxBlock->pxNextFreeBlock = NULL; #ifdef MEMLEAK_DEBUG if(uxHeapStructSize >= sizeof( BlockLink_t )){ pxBlock->file = file; pxBlock->line = line; } //link the use block prvInsertBlockIntoUsedList(pxBlock); #endif } else { mtCOVERAGE_TEST_MARKER(); } } else { mtCOVERAGE_TEST_MARKER(); } } else { mtCOVERAGE_TEST_MARKER(); } traceMALLOC( pvReturn, xWantedSize ); } // ( void ) xTaskResumeAll(); ETS_INTR_UNLOCK(); #if( configUSE_MALLOC_FAILED_HOOK == 1 ) { if( pvReturn == NULL ) { extern void vApplicationMallocFailedHook( void ); vApplicationMallocFailedHook(); } else { mtCOVERAGE_TEST_MARKER(); } } #endif return pvReturn; }