AnsweredAssumed Answered

Flash X Not Working... I have proof!

Question asked by Michael Schwager on Jan 20, 2015
Latest reply on Jan 29, 2015 by Michael Schwager

I've finally managed to capture a failing FlashX driver.

This is using the TWR-K60D100M with MK60DN512VMD10-4N22D and associated 4.1 BSP from the cloning wizard.

 

The issue appears to be related to memory allocation.

The test code allocates an increasing number of memory segments, each 15 bytes, then tries to write 512 bytes to flashx:swap1.

The contents of the flash write have nothing to do with the memory allocated.  They are separate buffers.

 

After a number of cycles, the write fails.

Specifically when it hits 57 segments (@ 15 bytes each this is 855 bytes).

 

If I start the loop at 57 segments, the write doesn't fail here.  It counts up to some larger number of segments to fail.

So it seems deallocating memory doesn't put the system back in the same state.

 

Anyway, here is the main.c file.  Also attached.

 

 

 

 

// MQX headers #include <mqx.h> #include <bsp.h> #include <fio.h>   #ifdef _DEBUG   // Allows you to do an action after the handler, such as return, print something, block, etc. #define ASSERT(cond,action,...) \ do { \   if(!(cond)) {\   assert_handler("[ASSERT]", #cond, __FILE__, __LINE__, ##__VA_ARGS__);\   do {\   action;\   } while(0);\   }\ } while(0)   // Stops MQX #define ASSERT_FAIL(cond,...) ((!(cond) && \                                assert_handler("[FATAL]", #cond, __FILE__, __LINE__, ##__VA_ARGS__) &&\                                (_mqx_fatal_error(-1),1)))   #define ASSERT_WARN(cond,...) ((!(cond) && \                                assert_handler("[WARNING]", #cond, __FILE__, __LINE__, ##__VA_ARGS__)))   #define ASSERT_MSG(cond,...) ((!(cond) && \                               assert_handler("[MESSAGE]", #cond, __FILE__, __LINE__, ##__VA_ARGS__)))   #else #define ASSERT(cond,action,...)  do {(void)sizeof(cond);} while(0) #define ASSERT_FAIL(cond,...) #define ASSERT_WARN(cond,...) #define ASSERT_MSG(cond,...) #endif   /* Task IDs */ enum {MAIN_TASK = 1};   // Local function declarations void main_task(uint32_t);   const TASK_TEMPLATE_STRUCT  MQX_template_list[] = {   /* Task Index,         Function,            Stack,  Priority,  Name,                 Attributes,          Param, Time Slice */   { MAIN_TASK,           main_task,           4096,        10,   "main",               MQX_AUTO_START_TASK, 0,     0 },   { 0 } };    static bool assert_handler(char *category, char *arg, char *file, int line, ...) {     printf("%s: (%s) at line %d in %s\n", category, arg, line, file);       va_list args;     va_start(args, line);     vprintf(va_arg(args, char *), args);     va_end(args);       printf("\n");   fflush(stdout);     return true; }   static uint32_t min(uint32_t a, uint32_t b) {   return a<b?a:b; }   int32_t flash_write_bytes(const char *name, const uint32_t addr, const uint8_t *vals, const uint32_t num_bytes) {   MQX_FILE_PTR flash = fopen(name, 0);   ASSERT_FAIL(flash != NULL, "Can't open flash file");   //ioctl(flash, FLASH_IOCTL_ENABLE_SECTOR_CACHE, 0);   //ioctl(flash, FLASH_IOCTL_ENABLE_BUFFERING, 0);   fseek(flash, addr, IO_SEEK_SET);   uint32_t result = write(flash, (uint8_t  *)vals, num_bytes);   if (result != num_bytes) {   fclose(flash);   return 0;   } else { // Yes we were able to write everything   fclose(flash);   return result;   } }   static uint8_t static_buff[2048]; uint32_t test_flash(const char *name, uint32_t addr, uint8_t *vals, uint32_t num_bytes) {   // Test flash for any region, any address.   // This is destructive to content of vals, and obviously   // destructive to contents of flash   static uint8_t val = 1;   memset(static_buff, val++, 2048);     // Use local buffer and 2048 if buffer arg and sz are null and zero, respectively   uint8_t *buff =      vals == NULL ? static_buff : vals;   uint32_t   sz = num_bytes ==    0 ?        2048 : num_bytes;   uint32_t result;   result = flash_write_bytes(name, addr, buff, sz);   printf("Test flash result is: %d\n", result);   fflush(stdout);   return result; }   static void main_task(uint32_t initial_data) {   uint32_t num_segments = 1;   uint32_t seg_size = 15;   uint32_t *sizes;   uint32_t **ptrs;   uint32_t totalsz = 0;     while(1) {   //printf("\nAt least %d bytes available at start\n", find_max_memory());   uint32_t allocsz = num_segments * sizeof(uint32_t *);   printf("\nAllocating %d bytes to hold %d sizes\n", allocsz, num_segments);   sizes = _lwmem_alloc_zero(allocsz);   ASSERT(sizes, "Could not allocate %d bytes", allocsz);   fflush(stdout);     printf("Allocating %d bytes to hold %d ptrs\n", allocsz, num_segments);   ptrs = _lwmem_alloc_zero(allocsz);   ASSERT(ptrs, "Could not allocate %d bytes", allocsz);   fflush(stdout);     printf("Allocating %d times\n", num_segments);   for(uint32_t i = 0; i < num_segments; i++) {   uint32_t sz = seg_size;   //printf("\t%d\t Allocating %d bytes\n", i, sz);   //fflush(stdout);   ptrs[i] = _lwmem_alloc_zero(sz);   ASSERT_FAIL(ptrs[i], "Could not allocate %d bytes", sz);   sizes[i] = sz;   totalsz += sz;   }     printf("Total allocation: %d bytes\n", totalsz);   bool test_result = test_flash("flashx:swap1", 0x00000000, NULL, 512);   ASSERT_FAIL(test_result, "Failed flash test");   printf("Flash test passed\n");   fflush(stdout);     // Release before starting over   printf("Releasing everything\n");   for(uint32_t i = 0; i < num_segments; i++) {   sizes[i] = 0;   ptrs[i] = NULL;   _lwmem_free(ptrs[i]);   }   _lwmem_free(ptrs);   _lwmem_free(sizes);   totalsz = 0;     num_segments += 1;   } }   

Original Attachment has been moved to: main.c.txt.zip

Outcomes