├── .gitignore ├── Documentation ├── CC13xx26xx.jpg ├── JesFs.pdf ├── Nrf52840_DK.jpg ├── PerformanceTests.pdf ├── jesfs_logo.jpg ├── ltrax_module.jpg ├── ltx_jesfs.jpg ├── nrf52832.jpg ├── nrf52840.jpg └── rc1310Fk.jpg ├── JesFs_main.c ├── LICENSE ├── README.md ├── jesfs.h ├── jesfs_hl.c ├── jesfs_int.h ├── jesfs_ml.c ├── platform_CC13XX_CC26XX ├── JesFs_ll_tirtos.c ├── ReadMe.txt └── tb_tools_cc.c ├── platform_SAMD20 ├── Configure_JesFs_for_SAMD20.pdf ├── JesFs_II_atmelstart.c └── tb_tools_atmelstart.c ├── platform_WIN ├── JesFsDemo_cpp_studio.cbproj ├── JesFsDemo_cpp_studio.cbproj.local ├── JesFsDemo_cpp_studio.res ├── JesFs_ll_pc.c ├── ReadMe.txt ├── Win32 │ └── Debug │ │ └── JesFsDemo_cpp_studio.exe └── tb_tools_win.c ├── platform_nRF52 ├── JesFs_ll_pca100xx.c ├── ReadMe.txt ├── nrf52832 │ ├── config │ │ └── sdk_config.h │ └── ses │ │ └── flash_placement.xml ├── nrf52840 │ ├── config │ │ └── sdk_config.h │ └── ses │ │ └── flash_placement.xml ├── tb_pins_nrf52.h └── tb_tools_nrf52.c ├── tb_tools.h └── usecase_BlackBox ├── BlackBox_Eval.pdf ├── blackbox_helpers.c ├── blackbox_helpers.h ├── blackbox_main.c ├── platform_CC13XX_CC26XX └── ReadMe.txt ├── platform_WIN ├── BlackBox_cpp_stdio.cbproj ├── BlackBox_cpp_stdio.cbproj.local ├── BlackBox_cpp_stdio.res ├── BlackBox_cpp_stdio.stat └── Win32 │ └── Debug │ └── BlackBox_cpp_stdio.exe ├── platform_nRF52_nrf52840 ├── ReadMe.txt ├── config │ └── sdk_config.h └── ses │ └── flash_placement.xml └── readme.md /.gitignore: -------------------------------------------------------------------------------- 1 | Output/ 2 | *.emSession 3 | *.emProject 4 | *.jlink 5 | _firmware.sec 6 | _firmware.bin 7 | privat* 8 | 9 | .local/* -------------------------------------------------------------------------------- /Documentation/CC13xx26xx.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joembedded/JesFs/ebabac8866c69107afa3e4e1fef24a9b6ef647d7/Documentation/CC13xx26xx.jpg -------------------------------------------------------------------------------- /Documentation/JesFs.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joembedded/JesFs/ebabac8866c69107afa3e4e1fef24a9b6ef647d7/Documentation/JesFs.pdf -------------------------------------------------------------------------------- /Documentation/Nrf52840_DK.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joembedded/JesFs/ebabac8866c69107afa3e4e1fef24a9b6ef647d7/Documentation/Nrf52840_DK.jpg -------------------------------------------------------------------------------- /Documentation/PerformanceTests.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joembedded/JesFs/ebabac8866c69107afa3e4e1fef24a9b6ef647d7/Documentation/PerformanceTests.pdf -------------------------------------------------------------------------------- /Documentation/jesfs_logo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joembedded/JesFs/ebabac8866c69107afa3e4e1fef24a9b6ef647d7/Documentation/jesfs_logo.jpg -------------------------------------------------------------------------------- /Documentation/ltrax_module.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joembedded/JesFs/ebabac8866c69107afa3e4e1fef24a9b6ef647d7/Documentation/ltrax_module.jpg -------------------------------------------------------------------------------- /Documentation/ltx_jesfs.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joembedded/JesFs/ebabac8866c69107afa3e4e1fef24a9b6ef647d7/Documentation/ltx_jesfs.jpg -------------------------------------------------------------------------------- /Documentation/nrf52832.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joembedded/JesFs/ebabac8866c69107afa3e4e1fef24a9b6ef647d7/Documentation/nrf52832.jpg -------------------------------------------------------------------------------- /Documentation/nrf52840.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joembedded/JesFs/ebabac8866c69107afa3e4e1fef24a9b6ef647d7/Documentation/nrf52840.jpg -------------------------------------------------------------------------------- /Documentation/rc1310Fk.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joembedded/JesFs/ebabac8866c69107afa3e4e1fef24a9b6ef647d7/Documentation/rc1310Fk.jpg -------------------------------------------------------------------------------- /JesFs_main.c: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * JesFs_main.C: JesFs Demo/Test 3 | * 4 | * JesFs - Jo's Embedded Serial File System 5 | * 6 | * Demo how to use JesFs on 7 | * - TI CC13xx/CC26xx Launchpad 8 | * - Nordic nRF52840 DK_PCA10056 (nRF52) 9 | * - Nordic nRF52832 DK_PCA10040 (nRF52) 10 | * - Windows (Compilers: "Embarcadero(R) C++ Builder Community Edition" (for PC) 11 | * and "Microsoft Visual Studio Community 2019") 12 | * 13 | * Can be used as standalone project or in combination with secure JesFsBoot Bootloader 14 | * 15 | * Docu in 'JesFs.pdf' 16 | * 17 | * (C) joembedded@gmail.com - www.joembedded.de 18 | * Version: 19 | * 1.5: 25.11.2019 20 | * 1.51: 07.12.2019 (nRF52) added deep sleep functions in Toolbox (nrF52840<3uA) (see cmd 's') 21 | * 1.6: 22.12.2019 added fs_check_disk() for detailed checks 22 | * 1.61: 05.01.2020 source cosmetics and (nRF52) SPIM 16MHz as default 23 | * 1.62: 19.01.2020 Changed WD behavior in tb_tools 24 | * 1.7: 25.02.2020 (nRF52) Added Defines for u-Blox NINA-B3 25 | * 1.8: 20.03.2020 Added Time set with '!' and UART-RX-Error 26 | * 2.0: 06.09.2020 (nRF52) Changed UART Driver to APP_UART for Multi-Use in tb_tools 27 | * 2.01: 08.09.2020 (nRF52) Fixed Error in SDK17 (see tb_tools_nrf52.c-> 'SDK17') 28 | * 2.02: 23.09.2020 (nRF52) Adapted to SDK17.0.2 (still Problem in 'nrf_drv_clock.c' -> see 'SDK17') 29 | * 2.03: 22.11.2020 Corrected small error in JesFs_main.c 'r' command. 30 | * 2.04: 11.02.2021 Corrected small error in JesFs_main.c 'X' command. 31 | * 2.05: 12.03.2021 Added print of Flash ID for analysis 32 | * 2.06: 21.03.2021 Added hint about 'Bulk Erase'/Soft format (see case 'F')) 33 | * 2.54: 06.10.2021 added 'tb_get_runtime()' for NRF52 34 | * 2.55: 06.10.2021 INFO: SDK17.1.0: There is still an Error on nrf_drv_clk.c ( -> search in this file 'SDK17') 35 | * 2.56: 02.04.2022 improved fs_checkdisk() (nRF52840 J-TAG corrupted FlashDisk via QSPI) 36 | * 2.70: 17.03.2023 added _feature supply_voltage_check(); 37 | * 2.71: 14.09.2023 all global fs_-functions check _supply_voltage_check() on entry 38 | *******************************************************************************/ 39 | 40 | #define VERSION "2.57 / 17.03.2023" 41 | 42 | #ifdef WIN32 // Visual Studio Code defines WIN32 43 | #define _CRT_SECURE_NO_WARNINGS // VS somtimes complains traditional C 44 | #endif 45 | 46 | #include 47 | #include 48 | #include 49 | #include 50 | #include 51 | #include 52 | 53 | 54 | //======== Platform headers ========== 55 | #ifdef PLATFORM_NRF52 // Define this Macro in ProjectOptions - PredefinedSymbols 56 | #include "boards.h" // Settings div. 57 | 58 | #define GID 1 // Guard-ID 59 | 60 | #endif 61 | 62 | #ifdef CC13XX_CC26XX // Define this Macro in ProjectOptions - PredefinedSymbols 63 | #define main mainThread // main_start is a Task 64 | #endif 65 | 66 | #ifdef WIN32 // Visual Studio Code defines WIN32 67 | #define __WIN32__ // Embarcadero defines __WIN32__ 68 | #endif 69 | #ifdef __WIN32__ 70 | extern int16_t ll_read_vdisk(char* fname); // Helpers to write/read virtual Disk to fFile on PC 71 | extern int16_t ll_setid_vdisk(uint32_t id); 72 | extern int16_t ll_get_info_vdisk(uint32_t * pid_used, uint8_t * *pmem, uint32_t * psize); 73 | #endif 74 | 75 | //======= Toolbox ======= 76 | #include "tb_tools.h" 77 | 78 | //===== JesFs ===== 79 | #include "jesfs.h" 80 | 81 | //====================== Globals =============== 82 | #define MAX_INPUT 80 83 | char input[MAX_INPUT+1]; // 0 at end 84 | 85 | #define SBUF_SIZE 10000 // Big buffer for BULK write test (Remark for CCxxy0: only 20k available) 86 | uint8_t sbuffer[SBUF_SIZE]; // Test buffer 87 | 88 | //==== JesFs globals ===== 89 | // two global descriptors and helpers (global to save RAM memory and allow reuse) 90 | // (JesFs was originally desigend for very small CPUs) 91 | FS_DESC fs_desc, fs_desc_b; // _b: A second descriptor for rename etc.. 92 | FS_STAT fs_stat; 93 | FS_DATE fs_date; // Structe holding date-time 94 | 95 | 96 | //=========== Helper Functions =============== 97 | //=== Platform specific === 98 | uint32_t _time_get(void) { 99 | return tb_time_get(); 100 | } 101 | 102 | // Mostly all modern CPUs have internal high-speed A/D. Ideal for checking power. 103 | // Since V2.70 power is checked on fs_start() and all global write-functions on entry. 104 | // Normally only a few msec for writing/modifying the is required. 105 | int16_t _supply_voltage_check(void){ 106 | return 0; // 0: Assume Power OK (Failure if <>0) 107 | } 108 | 109 | 110 | //=== common helpers === 111 | // Helper Function for readable timestamps 112 | void conv_secs_to_date_sbuffer(uint32_t secs) { 113 | fs_sec1970_to_date(secs,&fs_date); 114 | sprintf((char*)sbuffer,"%02u.%02u.%04u %02u:%02u:%02u",fs_date.d,fs_date.m,fs_date.a,fs_date.h,fs_date.min,fs_date.sec); 115 | } 116 | // Convert a String "day.month.year4 hr:min[.sec]" to unix-seconds // Return 0 on error 117 | uint32_t conv_tstr_to_secs(char* pc){ 118 | memset(&fs_date,0,sizeof(fs_date)); 119 | fs_date.d=(uint8_t)strtoul(pc,&pc,0); 120 | if(*pc++!='.') return 0; 121 | fs_date.m=(uint8_t)strtoul(pc,&pc,0); 122 | if(*pc++!='.') return 0; 123 | fs_date.a=(uint16_t)strtoul(pc,&pc,0); 124 | if(*pc++!=' ') return 0; 125 | fs_date.h=(uint8_t)strtoul(pc,&pc,0); 126 | if(*pc++!=':') return 0; 127 | fs_date.min=(uint8_t)strtoul(pc,&pc,0); 128 | if(*pc++==':') fs_date.sec=(uint8_t)strtoul(pc,0,0); // Seconds optional 129 | return fs_date2sec1970(&fs_date); 130 | } 131 | 132 | //========= MAIN ==================== 133 | int main(void) { // renamed to mainThread() on CCxxyy 134 | char *pc; 135 | uint32_t uval; 136 | int32_t res; 137 | int32_t i,h; 138 | int32_t anz; 139 | uint32_t t0; 140 | uint32_t asecs; 141 | uint8_t open_flag; 142 | 143 | #ifdef PLATFORM_NRF52 // Find out why restared 144 | uval = (NRF_POWER->RESETREAS); 145 | (NRF_POWER->RESETREAS)=0xFFFFFFFF; // Clear with '1' 146 | #endif 147 | 148 | tb_init(); // Init the Toolbox (without Watchdog) 149 | tb_watchdog_init(); // Watchdog separate init 150 | 151 | tb_printf("\n*** JesFs *Demo* " VERSION " (C)JoEmbedded.de\n\n"); 152 | 153 | #ifdef PLATFORM_NRF52 // Find out why restared 154 | tb_printf("Reset-Reason: 0x%X ",uval); 155 | if(uval&1) tb_printf("(Pin-Reset)"); // The low Nibble Reasons 156 | if(uval&2) tb_printf("(Watchdog)"); 157 | if(uval&4) tb_printf("(Soft-Reset)"); 158 | if(uval&8) tb_printf("(CPU Lockup)"); 159 | tb_printf(" Bootcode: 0x%x\n",tb_get_bootcode(true)); 160 | GUARD(GID); // GUARD: Save THIS line as last visited line in Module GID 161 | #endif 162 | 163 | res=fs_start(FS_START_NORMAL); 164 | tb_printf("Filesystem Init:%d\n",res); 165 | tb_printf("Disk size: %d Bytes\n", sflash_info.total_flash_size); 166 | tb_printf("Flash ID: %x\n",sflash_info.identification); // For Analysis, see 'jesfs.h' for definitions 167 | 168 | for(;;) { 169 | tb_board_led_on(0); 170 | 171 | tb_time_get(); // Dummy call to update Unix-Timer 172 | tb_printf("> "); // Show prompt 173 | res=tb_gets(input,MAX_INPUT, 60000, 1); // 60 seconds time with echo 174 | tb_putc('\n'); 175 | tb_watchdog_feed(1); // Now 250 secs time 176 | tb_board_led_off(0); 177 | 178 | #ifdef PLATFORM_NRF52 // Save Software Position 179 | GUARD(GID); 180 | #endif 181 | if(res<0){ 182 | tb_printf("ERROR: UART-RX\n"); // Show prompt 183 | tb_uninit(); 184 | tb_delay_ms(1000); 185 | tb_init(); 186 | }else if(res>0) { // ignore empty lines 187 | pc=&input[1]; // point to 1.st argument 188 | while(*pc==' ') pc++; // Remove Whitspaces from Input 189 | uval=strtoul(pc,NULL,0); // Or 0 190 | 191 | t0=tb_get_ticks(); 192 | switch(input[0]) { 193 | 194 | case 's': // V1.51: With deep sleep, on nRF52840: <3uA 195 | tb_printf("'s' Flash DeepSleep and CPU sleep %d secs...\n",uval); 196 | res=fs_start(FS_START_RESTART); // Restart Flash to be sure it is awake, else it can not be sent to sleep.. 197 | if(res) tb_printf("(FS_start(FS_RESTART) return ERROR: Res:%d)\n",res); 198 | fs_deepsleep(); // ...because if Flash is already sleeping, this will wake it up!, now SPI closed, Flash in Deep-Sleep 199 | tb_delay_ms(10); // Wait for Text Out 200 | tb_uninit(); // Disable toolbox-HighPower peripherals (e.g. UART) 201 | tb_delay_ms(uval*1000); 202 | tb_init(); // Re-Enable again 203 | // no 'break', wake Filesystem fall-through 204 | 205 | case 'i': 206 | res=fs_start(FS_START_FAST); // Wake (an enable Flash) 207 | tb_printf("'i' Filesystem Init Fast: Res:%d\n",res); 208 | if(!res) break; // All OK 209 | 210 | case 'I': 211 | res=fs_start(FS_START_NORMAL); 212 | tb_printf("'I' Filesystem Init Normal: Res: %d\n",res); 213 | break; 214 | 215 | case 'S': 216 | tb_printf("'S' Only and CPU sleep %d secs (Wake Sflash with 'i'/'I')...\n",uval); 217 | tb_delay_ms(uval*1000); 218 | break; 219 | 220 | case 'F': 221 | // Warning: F1 ('Bulk Erase') might need VERY long on some (larger) Chips (> 240 secs, 222 | // which is Default Timeout). Better to use F2 (which erases only non-empty 4k sectors). 223 | // F1: Hardware Chip Erase ('Bulk Erase') F2: Soft Erase :2 (faster if not full) 224 | i=atoi(pc); 225 | pc="???"; 226 | if(i==1) pc="Chip Erase"; 227 | else if(i==2) pc="Soft Erase"; 228 | tb_printf("'F' Format Serial Flash (Mode:%d(%s)) (may take up to 240 secs!)...\n",i,pc); 229 | tb_printf("FS format: Res:%d\n",fs_format(i)); 230 | break; 231 | 232 | case 'o': 233 | // Open an existing file and set file position to first byte or create it, if not existing. 234 | // This file can not be closed, but appended if file position points behind the last existing byte 235 | // of the file 236 | tb_printf("'o' Open File for Reading or Raw '%s' (incl. Writing)\n",pc); 237 | open_flag=SF_OPEN_READ |SF_OPEN_RAW|SF_OPEN_CRC; // flags: Read only (Raw required for Delete) with CRC 238 | if(*pc=='~'){ open_flag &= ~SF_OPEN_CRC; pc++; tb_printf("CRC disabled\n");} // ~FILENAME = no CRC 239 | res=fs_open(&fs_desc,pc, open_flag ); 240 | tb_printf("Res:%d, Len:%d\n",res,fs_desc.file_len); // (Len: if already exists) 241 | break; 242 | 243 | case 'O': 244 | // Open the file for writing and create it, if not existing. If existing: truncate 245 | tb_printf("'O' Open File for Writing '%s'\n",pc); 246 | open_flag=SF_OPEN_CREATE|SF_OPEN_WRITE |SF_OPEN_CRC; // flags: Create if not there, in any case: open for writing with CRC 247 | if(*pc=='~'){ open_flag &= ~SF_OPEN_CRC; pc++; tb_printf("CRC disabled\n");} // ~FILENAME = no CRC 248 | res=fs_open(&fs_desc,pc,open_flag); 249 | tb_printf("Res:%d\n",res); 250 | break; 251 | 252 | case 'c': 253 | // Write CRC/Len if file was opened for writing, RAW files can not be closed 254 | // In any case: invalidate the descriptor 255 | tb_printf("'c' Close File, Res:%d\n",fs_close(&fs_desc)); 256 | break; 257 | 258 | case 'd': 259 | tb_printf("'d' Delete (RAW opened) File, Res:%d\n",fs_delete(&fs_desc)); 260 | break; 261 | 262 | 263 | case 'v': // Listing on virtual Disk - Only basic infos. No checks, Version with **File Health-Check** for all files with CRC in JesFs_cmd.c 264 | tb_printf("'v' Directory:\n"); 265 | tb_printf("Disk size: %d Bytes\n", sflash_info.total_flash_size); 266 | if(sflash_info.creation_date==0xFFFFFFFF) { // Severe Error 267 | tb_printf("Error: Invalid/Unformated Disk!\n"); 268 | break; 269 | } 270 | tb_printf("Disk available: %d Bytes / %d Sectors\n",sflash_info.available_disk_size,sflash_info.available_disk_size/SF_SECTOR_PH); 271 | conv_secs_to_date_sbuffer(sflash_info.creation_date); 272 | tb_printf("Disk formated [%s]\n",sbuffer); 273 | for(i=0; i0) { 320 | uval=anz; 321 | if(uval>SBUF_SIZE) uval=SBUF_SIZE; 322 | res=fs_write(&fs_desc,sbuffer,uval); 323 | tb_printf("Write %u/%u Bytes - Res:%d\n",uval,anz,res); 324 | if(res<0) break; 325 | anz-=uval; 326 | } 327 | break; 328 | 329 | case 'w': // Write Text Data 330 | tb_printf("'w' Write '%s' to file\n",pc); 331 | res=fs_write(&fs_desc,(uint8_t*)pc,strlen(pc)); 332 | tb_printf("Res:%d\n",res); 333 | break; 334 | 335 | case 'r': 336 | tb_printf("'r' Read (max.) %d Bytes from File:\n",uval); 337 | anz = uval; 338 | // Read the complete sbuffer, but show only max. first 60 bytes 339 | if(anz<(int)sizeof(sbuffer)) { 340 | res=fs_read(&fs_desc, sbuffer , anz); 341 | // Show max. the first 60 Bytes... 342 | if(res>0) { 343 | for(i=0; i60) { 346 | tb_printf("..."); 347 | break; // Don't show all 348 | } 349 | } 350 | tb_printf("\n"); 351 | } 352 | } else { 353 | // This is e.g. tp place the file position to find the end of the file 354 | // Silent read is VERY fast, my measures show ca. 120-180 MB/sec (nRF52) 355 | // Warning: silent read will not update computed CRC32 356 | tb_printf("Read %d silent...\n",anz); 357 | res=fs_read(&fs_desc, NULL , anz); 358 | } 359 | tb_printf("Read %d Bytes: Res:%d\n",anz,res); 360 | break; 361 | 362 | case 'R': 363 | // Read BULK data 364 | // Reading Files with computed CRC32 is about 550-600 kB/sec (nRF52) and 365 | // without computed CRC ca. 3.75MB/sec what is very close to the 366 | // theoretical absolute maximum limit of 4MB/sec 367 | tb_printf("'R' BULK Read %d Bytes from file in Junks of %d\n",uval,SBUF_SIZE); 368 | h=0; 369 | anz=uval; 370 | while(anz>0) { 371 | uval=anz; 372 | if(uval>SBUF_SIZE) uval=SBUF_SIZE; 373 | res=fs_read(&fs_desc,sbuffer,uval); 374 | if(res<=0) break; // 0: Nothing more 375 | anz-=uval; 376 | h+=res; 377 | } 378 | tb_printf("Read %u Bytes - Res:%d\n",h,res); 379 | 380 | break; 381 | 382 | case 'e': 383 | // Rewind file position 384 | res=fs_rewind(&fs_desc); 385 | tb_printf("'e' Rewind File - Res:%d\n",res); 386 | break; 387 | 388 | case 't': 389 | // Show file position an disk len (not for unlcosed files) and the computed CRC32 390 | tb_printf("'t' Test/Info: file_pos:%d file_len:%d CRC32:%x\n",fs_desc.file_pos,fs_desc.file_len, fs_desc.file_crc32); 391 | break; 392 | 393 | case 'z': 394 | // Display the CRC of a file (shows 0xFFFFFFFF for unclosed files or if not enabled) 395 | // and the computed CRC32 (which is only updated for physical reads, not for silent reads) 396 | tb_printf("'z' CRC32: Disk:%x, Run:%x\n",fs_get_crc32(&fs_desc),fs_desc.file_crc32); 397 | break; 398 | 399 | case 'n': // Rename (Open) File to 400 | tb_printf("'n' Rename File to '%s'\n",pc); // rename also allows changing Flags (eg. Hidden or Sync) 401 | i=SF_OPEN_CREATE|SF_OPEN_WRITE; // ensures new File is avail. and empty 402 | if(fs_desc.open_flags&SF_OPEN_CRC) i|= SF_OPEN_CRC; // Optionally Take CRC to new File 403 | res=fs_open(&fs_desc_b,pc,i); // Must be a new name (not the same) 404 | if(!res) res=fs_rename(&fs_desc,&fs_desc_b); 405 | tb_printf("Rename - Res:%d\n",res); 406 | break; 407 | 408 | 409 | case 'q': // Quit: Exit / System Reset. 410 | tb_printf("'q' Exit in 1 sec...\n"); 411 | tb_delay_ms(1000); 412 | tb_printf("Bye!\n"); 413 | 414 | // Winddows exit() 415 | // TI-RTOS Up to (TI-RTOS+Debugger) what happens: Reset, Stall, Nirvana, .. See TI docu. 416 | // nRF52: Reset 417 | tb_system_reset(); 418 | 419 | case 'X': // Watchdog Test 420 | tb_printf("Counting %d secs, Watchdog Test...\n",uval); 421 | #ifdef PLATFORM_NRF52 // Save Software Position 422 | GUARD(GID); 423 | #endif 424 | for(i=0;i127) res='.'; 459 | tb_printf("%c",res); 460 | } 461 | tb_printf("\n"); 462 | } 463 | } 464 | break; 465 | 466 | #ifdef __WIN32__ 467 | // On Windows the virtual Disk/Flash (in RAM) can be saved and reloaded 468 | case '+': 469 | tb_printf("'+': Write VirtualDisk to File: '%s'\n",pc); 470 | res=ll_write_vdisk(pc); 471 | tb_printf("Res: %d\n",res); 472 | break; 473 | 474 | case '#': 475 | tb_printf("'#': Read VirtualDisk from File: '%s'\n",pc); 476 | res=ll_read_vdisk(pc); 477 | tb_printf("Res: %d\n",res); 478 | tb_printf("FS Init Normal:%d\n",fs_start(FS_START_NORMAL)); 479 | break; 480 | 481 | case '$': 482 | // Manually select size of virtual Flash 483 | anz=strtoul(pc,NULL,0); 484 | tb_printf("'$': Set vdisk ID: $%x/%d\n",anz,anz); 485 | ll_setid_vdisk(anz); 486 | break; 487 | #endif 488 | 489 | default: 490 | tb_printf("???\n"); 491 | break; 492 | } 493 | 494 | // Measure runtime 495 | tb_printf("(Run: %u msec)\n",tb_deltaticks_to_ms(t0,tb_get_ticks())); 496 | } 497 | } 498 | } 499 | 500 | // ** 501 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Jo 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # JesFs - Jo's Embedded Serial File System # 2 | **for Standard (Serial) NOR-Flash** 3 | 4 | Just think of very simple things like language data: on a “very small” 5 | Embedded Device (not something “big” like an Embedded Linux, but something 6 | that can run with small batteries for years): it is commonly integrated 7 | “somewhere in the code”. 8 | Difficult to change! But if the language data is in files, 9 | changes are easy. Same for graphics, setups, everything… 10 | It even allows to change the firmware on the Embedded Device from many different sources! 11 | 12 | Think of Embedded Devices, that even can get their latest firmware by themselves! E.g. over 13 | WiFi, Mobile Internet, Bluetooth, UART, Radio-Link, … 14 | Suddenly all options are open! And if you have concerns about 15 | the security: don’t worry: problem already solved, as you’ll see later.. 16 | 17 | The main problem for “very small devices” – until now – was the “File System”: 18 | everybody knows “FAT”, “NTFS”, … but have you ever thought of a file system on a small chip? 19 | Or even inside of a CPU? No problem, with the right Software. This is why I wrote 20 | 21 | **“JesFs – Jo’s Embedded Serial File System“** 22 | 23 | ![JesFs on LTraX](https://github.com/joembedded/JesFs/blob/master/Documentation/ltx_jesfs.jpg) 24 | 25 | [Image: 4MB JesFs on 2x3 mm] 26 | 27 | 28 | My daily work ist the IoT. Because I did not find any really practical solution, 29 | I decided to create my own one. “Robustness”, “Security” and “Small Footprint” 30 | were my design constraints. 31 | 32 | JesFs was designed for use in the “Real World” and for use with standard Serial NOR-Flash memories, 33 | like the M25R-Series, used on nRF52840-DK, nRF52832 and the CC13xx/CC26xx Launchpads, which is available up to 16 MB, or even more… 34 | 35 | Some Basics about JesFs: 36 | 37 | - Ultra-Small RAM and code footprint: can be used on the smallest MCUs with only 8kByte program memory or less (like the famous MSP430-series, almost all kind of 32-Bit ARM cores (M0, M3, M4, ….)). Only 200 Bytes of RAM are sufficient! 38 | - Completely Open Source, free and written in Standard C. 39 | - Works with Serial NOR-Flash from **8kByte to 16MByte** (opt. up to 2GByte), but could also be used with CPU-internal NOR-Flash. 40 | - Works hand-in-hand with the Ultra-Small JesFsBoot Secure bootloader (requires less than 8kB on standard ARM cores, including an AES-128 encryption engine for reliable Over-the-Air-Updates (“OTA”)). 41 | - Includes optimised Wear Leveling (for maximum life of the memory). 42 | - Very Fast Data transfer (e.g. **reading files: 3.7MB/sec** on nRF52840). 43 | - A special mode was added to allow millions of write cycles, especially for data collection, event reports and journaling aplications. 44 | - JesFs is persistent: no data loss on Power Loss or Reset. 45 | - Designed for (almost) all situations, where NOR memories could be used (the ones where only blocks can be deleted (0->1) and only 0 written. 46 | - Tested with: Macronix MX25Rxx, GigaDevices GD25WDxx and GD25WQxx, ... 47 | - Strictly taylored to Ultra-Low-Power Embedded Systems 48 | - Designed to use the advantage of an underlying RTOS, but can also be used standalone. 49 | - Sample applications for the nRF52840/nRF52832-DK, Launchpads CC13xx/26xx, Atmel SAMD20, Windows-PC and others (Documentation PDF: [JesFs.pdf](https://github.com/joembedded/JesFs/blob/master/Documentation/JesFs.pdf)) 50 | - Easy to use with an intuitive API: 51 | 52 | ``` 53 | int16_t fs_open(FS_DESC *pdesc, char* pname, uint8_t flags); 54 | int32_t fs_read(FS_DESC *pdesc, uint8_t *pdest, uint32_t anz); 55 | int16_t fs_write(FS_DESC *pdesc, uint8_t *pdata, uint32_t len); 56 | int16_t fs_close(FS_DESC *pdesc); 57 | int16_t fs_delete(FS_DESC *pdesc); 58 | int16_t fs_rewind(FS_DESC *pdesc); 59 | int16_t fs_rename(FS_DESC *pd_odesc, FS_DESC *pd_ndesc); 60 | uint32_t fs_get_crc32(FS_DESC *pdesc); 61 | int16_t fs_check_disk(void cb_printf(char *fmt, ...), uint8_t *pline, uint32_t line_size); 62 | 63 | int16_t fs_format(uint32_t f_id); 64 | int16_t fs_start(uint8_t mode); 65 | void fs_deepsleep(void); 66 | 67 | int16_t fs_info(FS_STAT *pstat, uint16_t fno); 68 | void fs_sec1970_to_date(uint32_t asecs, FS_DATE *pd); 69 | ``` 70 | --- 71 | 72 | ## Changelog (JesFs_main.c) ## 73 | - V1.0 CC13XX/CC26xx and Windows 74 | - V1.5 (nRf52) nRF52840 port 75 | - V1.51 (nRf52) nRF52840 support Deep Sleep/Wakeup (Deep Sleep with RTC active and Full RAM retention <3uA) 76 | - V1.6 Added 'fs_disk_check()': careful Disk Check 77 | - V1.61 (nRf52) source cosmetics and reduced default SPIM Clock to 16MHz on nRF52840 (32MHz recommended only without Softdevice) 78 | - V1.7 (nRf52) Added Defines for u-Blox NINA-B3 79 | - V1.8 Added Time set with '!' and UART-RX-Error 80 | - V2.0 (nRf52) Changed UART Driver to APP_UART for Multi-Use in tb_tools 81 | - V2.01 (nRf52) Changed to SDK17 (problem with nrf_clock() in SDK17, see docu) 82 | - V2.02 (nRf52) Changed to SDK17.0.2 and SES 5.10b (problem with nrf_clock() in SDK17.0.2 not fixed in SDK17.0.2, see docu) 83 | - V2.10 (nRF52) Added Support for nRF52832 84 | - V2.20 (nRF52) Added Sample for nRF52832 (I/O Configuration for u-Blox ANNA-B112-module) 85 | - V2.30 (nRF52) Added print of Flash ID for analysis in JesFs_main.c 86 | - V2.54 (nRF52) Added 'tb_get_runtime()' in tb_tools.c 87 | - V2.55 (nRF52) Changed to SDK17.1.0 and SES 5.42ab (problem with nrf_clock() in SDK17.0.2 not fixed in SDK17.0.2, see docu) 88 | - V2.60 (nRF52) Use global Macro $SDK_ROOT 89 | - V2.61 (SAMD20) Atmel SAMD20 contributed (*kudos*!) 90 | - V2.70 added _feature supply_voltage_check(); 91 | - V2.71 all global fs_-functions check _supply_voltage_check() on entry 92 | - V2.72 JesFs_hl.c (File V1.91) 93 | 94 | --- 95 | 96 | # Using JesFs – BlackBox-Demo # 97 | ## A Flight Recorder for Home Use ## 98 | 99 | Many technical devices work reliable for years and years and no one cares about them. But if they fail, there is always the question: WHAT WENT WRONG? 100 | 101 | This is, where the JesFs could become extremely useful. 102 | 103 | Read more: [BlackBox_Eval.pdf](https://github.com/joembedded/JesFs/blob/master/usecase_BlackBox/BlackBox_Eval.pdf) 104 | 105 | # Hardware # 106 | ## Some tested Serial-Flash Chips ### 107 | Wide Voltage Range (1.6v-3.6V) and Ultra-Low-Power Standby: 108 | - Macronix MX25R-Series (MX25Rxx) 109 | - GigaDevices GD25W-Series (GD25WD80C, GD25WQ64E, ...) 110 | 111 | ## Use with NRF52-CPUs: ## 112 | ![nRF52840](https://github.com/joembedded/JesFs/blob/master/Documentation/nrf52840.jpg) 113 | ![nRF52832](https://github.com/joembedded/JesFs/blob/master/Documentation/nrf52832.jpg) 114 | 115 | ## Use with CC13xx/26xx-CPUs: ## 116 | ![CC13xx/26xx](https://github.com/joembedded/JesFs/blob/master/Documentation/CC13xx26xx.jpg) 117 | 118 | # Installation (for NRF52 CPUs): 119 | - Built with SES (V6.22a (*)) and SDK 17.1.0 (*: Later Versions of SES require changed project settings!!!) 120 | 121 | - Set Macro $SDK_ROOT where to find the SDK in SES -> Tools -> Options -> Building: 122 | e.g.: "Global Macros": "SDK_ROOT=C:\nordic\nRF5_SDK_17.1.0_ddde560" 123 | 124 | - Set Platform Macro with I/O-Pins (see tb_tools.h) 125 | 126 | - Optionally fix Problem with nrf_clock() (see docu tb_tools_nrf52.c/.h) 127 | 128 | --- 129 | 130 | -------------------------------------------------------------------------------- /jesfs.h: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * JesFs.h: Header Files for JesFs 3 | * 4 | * JesFs - Jo's Embedded Serial File System 5 | * 6 | * Tested on 7 | * - Win 8 | * - TI-RTOS CC13xx/CC26xx Launchpad 9 | * - nRF52840 on PCA10056 DK Board 10 | * 11 | * (C) joembedded@gmail.com - www.joembedded.de 12 | * Version: 13 | * 1.5 / 25.11.2019 14 | * 1.6 / 22.12.2019 added fs_disk_check() 15 | * 1.7 / 12.03.2020 added fs_date2sec1970() 16 | * 1.8 / 25.09.2020 added fs_set_static_secs() to set a static time for JesFs 17 | * 1.9 / 22.02.2021 added/edited Devicelist, added new Flash Family GD25WD 18 | * 1.10 / 28.02.2021 added/edited Devicelist, added new Flash Family GD25WQ 19 | * 1.11 / 16.03.2023 added more checks (Errors -144 ff) 20 | * 21 | *******************************************************************************/ 22 | 23 | /* List of Errors 24 | -100: SPI Init (Hardware) 25 | -101: Flash Timeout WaitBusy 26 | -102: SPI Can not set WriteEnableBit (Flash locked?) 27 | -103: FlashID:Unknown/illegal, readable but unknown Flash Density (describes the size) 28 | -104: FlashID:Unknown Flash ID, readable but unknown (eg. 0xC228 for Macronix M25xx, see docu) 29 | -105: Illegal flash addr 30 | -106: Block crosses sector border 31 | -107: fs_start found problems in the filesystem structure (-> run recover) 32 | -108: Unknown MAGIC, this Flash is either unformated or contains other data 33 | -109: Flash-ID in the Flash Index does not match Hardware-ID (-> run recover) 34 | -110: Filename to long/short 35 | -111: Too many files, Index full! (ca. 1000 for 4k sectors) 36 | -112: Sector border violated (before write) 37 | -113: Flash full! No free sectors available or Flash not formatted 38 | -114: Index corrupted (-> run recover) (or FS in deepsleep (see internal flag STATE_DEEPSLEEP)) 39 | -115: Number out of range Index (fs_stat) 40 | -116: No active file at this entry (fs_stat) 41 | -117: Illegal descriptor or file not open 42 | -118: File not open for writing 43 | -119: Index out of range 44 | -120: Illegal sector address 45 | -121: Short circle in sector list (-> run recover) 46 | -122: sector list contains illegal file owner (-> run recover) 47 | -123: Illegal sector type (-> run recover) 48 | -124: File not found 49 | -125: Illegal file flags (e.g. trying to delete a file opened for write) 50 | -126: Illegal file system structure (-> run recover ((possible reason: PowerLoss, , Index defect points to HEAD 0xFFFFFFFF))) 51 | -127: Closed files can not be continued (for writing) 52 | -128: Sector defect ('Header with owner') (-> run recover) 53 | -129: File descriptor corrupted. 54 | -130: Try to write to (unclosed) file in RAW with unknown end position 55 | -131: Sector corrupted: Empty marked sector not empty 56 | -132: File is empty 57 | -133: Rename not possible with Files open as READ or RAW 58 | -134: Rename requires an empty File as new Filename 59 | -135: Both files must be open for Rename 60 | -136: Erase Sector failed 61 | -137: Write to Flash Failed 62 | -138: Verify Failed 63 | -139: Format parameter 64 | -140: Command Deepsleep: Filesystem already sleeping (only informative) 65 | -141: Other Commands: Filesystem sleeping! 66 | -142: Illegal file system structure (-> run recover, Index defect points to illegal HEAD) 67 | -143: Illegal file system structure (-> run recover, Index defect) 68 | -144: FlashID:ZeroSleep read as 0x000000 (Short Circuit on SPI or Flash still Sleepmode) 69 | -145: FlashID:UnConnected read as 0xFFFFFF (SPI unconnected or Flash corrupt) 70 | -146: Illegal MagicHeader: Invalid Value found (and not 0xFFFFFFFF) 71 | -147: Device Voltage too low 72 | -148: Flash not accesible: Deepsleep or PowerFail 73 | */ 74 | 75 | #ifdef __cplusplus 76 | extern "C"{ 77 | #endif 78 | 79 | //------------------- Area for User Settings START ----------------------------- 80 | /* SF_xx_TRANSFER_LIMIT: 81 | * If defined, SPI Read- and Write-Transfers are chunked to this maximum Limit 82 | * for normal operation set to maximum or undefine ;-) 83 | * Recommended for Read to CPU: use >=64, or better: undefine SF_RD_TRANSFER_LIMIT 84 | * for Write to SPI: Because standard SPI has 256-Byte pages, chunks are 85 | * already small. But feel free to set SF_TX_TRANSFER_LIMIT to somethig smaller 86 | * 87 | * On TI-RTOS and the X110-Emulator on a CC1310 the heap does not like 88 | * too big chunks. However, it makes transfers slower. 89 | */ 90 | //#define SF_RD_TRANSFER_LIMIT 64 91 | //#define SF_TX_TRANSFER_LIMIT 64 92 | 93 | // Define this macro for additional statistics 94 | #define JSTAT 95 | 96 | // Sample-Flash ID MACRONIX (Ultra-Low-Power), add others 97 | #define MACRONIX_MANU_TYP_RX 0xC228 // Macronix MX25R-Low-Power-Series first 2 ID-Bytes (without Density) 98 | //#define GIGADEV_MANU_TYP_RC 0xC840 // GigaDevices (used in RC1310F) first 2 ID-Bytes (without Density), WARNING: Will not work <3V!!! 99 | #define GIGADEV_MANU_TYP_WD 0xC864 // GigaDevices (same as MX25R, e.g. GD25WD80C) 100 | #define GIGADEV_MANU_TYP_WQ 0xC865 // GigaDevices (same as MX25R,e.g. GD25WQ64E) 101 | 102 | //------------------- Area for User Settings END ------------------------------- 103 | 104 | 105 | #define FNAMELEN 21 // maximum filename len (Byte 22 must be 0, as in regular strings)... 106 | 107 | // Startflags (fs_start()) 108 | #define FS_START_NORMAL 0 // ca. 20 msec per MB on an empty Flash 109 | #define FS_START_FAST 1 // ca. 10 msec per MB on an empty Flash, but less checks 110 | //#define FS_START_PEDANTIC 2 // Reserved for Version 2 111 | #define FS_START_RESTART 128 // ca. 50 usec if Flash data is already known. Else FS_START_NORMAL 112 | 113 | #define FS_FORMAT_FULL 1 // Erases ALL (Bulk Erase) (slow) 114 | #define FS_FORMAT_SOFT 2 // Erase only non-empty sectors (sometimes faster) 115 | 116 | // Flags for (fs_open) files 117 | #define SF_OPEN_READ 1 // open for read only 118 | #define SF_OPEN_CREATE 2 // create file in any case 119 | #define SF_OPEN_WRITE 4 // open for writing 120 | #define SF_OPEN_RAW 8 // just open 121 | #define SF_OPEN_CRC 16 // if set: calculate CRC32 for file while reading/writing 122 | #define SF_XOPEN_UNCLOSED 32 // File is/was not closed. Set (informative) by fs_stat() (disc_flags) or fs_open (open_flags) 123 | #define SF_OPEN_EXT_SYNC 64 // File should be synced to external filesystem, this Flag is not relevant for the Filesystem, but for external access 124 | #define _SF_OPEN_RES 128 // Reserved for nonvolatile files (for JesFs V2.x) 125 | 126 | // Flags for File-List 127 | #define FS_STAT_ACTIVE 1 128 | #define FS_STAT_INACTIVE 2 129 | #define FS_STAT_UNCLOSED 4 130 | #define FS_STAT_INDEX 128 // Requested Index would be outside of Index (used for Diagnostic) 131 | 132 | // Flags for state_flag 133 | #define STATE_DEEPSLEEP 1 // if set: JesFS in in deep sleep (Code -141) 134 | #define STATE_POWERFAIL 2 // if set: Not enabled due to Power Fail (Code -147) 135 | #define STATE_DEEPSLEEP_OR_POWERFAIL (STATE_DEEPSLEEP | STATE_POWERFAIL) // (Code -148) 136 | 137 | // Filedescriptor 138 | typedef struct{ 139 | uint32_t _head_sadr; // Hidden, head of file 140 | uint32_t _wrk_sadr; // Hidden, working 141 | uint32_t file_pos; // end pos is the current file len 142 | uint32_t file_len; // len after open (set by fs_open) FFFFFFFF if unknown 143 | uint32_t file_crc32; // running CRC32 according ISO 3309, FFFFFFFF if not used (only with SF_OPEN_CRC) 144 | uint32_t file_ctime; // Creation Time of the file UNIX-Time in seconds since 1.1.1970, 0:00:00 145 | 146 | uint16_t _sadr_rel; // Hidden, relative 147 | uint8_t open_flags; // current file flags (set by fs_open) OR file_flags on disk OR (opt) SF_XOPEN_UNCLOSED 148 | } FS_DESC; 149 | 150 | // Statistic descriptor 151 | typedef struct{ 152 | char fname[FNAMELEN+1]; // Max. filenam len V1.0 (21+0x00) 153 | uint32_t file_ctime; // Creation Time of the file UNIX-Time in seconds since 1.1.1970, 0:00:00 154 | uint32_t file_len; 155 | uint32_t file_crc32; // CRC32 in Flash for this file, according ISO 3309, FFFFFFFF if not used (only with SF_OPEN_CRC) 156 | uint32_t _head_sadr; // Hidden, head of file 157 | uint8_t disk_flags; // file flags on disk(written by fs_close) OR (opt) SF_XOPEN_UNCLOSED 158 | } FS_STAT; 159 | 160 | // Standard sizes for this implementation, see docu 161 | #define SF_SECTOR_PH 4096 // SFlash-Physical Sector in Bytes 162 | #define SF_BUFFER_SIZE_B 128 // 32 LONGS. 163 | 164 | // Working Buf Flash 165 | typedef union{ 166 | uint8_t u8[SF_BUFFER_SIZE_B]; 167 | uint16_t u16[SF_BUFFER_SIZE_B/2]; 168 | uint32_t u32[SF_BUFFER_SIZE_B/4]; 169 | } SF_BUFFER; 170 | 171 | 172 | // Structure, describing the Flash 173 | typedef struct{ 174 | // -- Filled Interpret_ID -- 175 | // e.g. 176 | // M25P40: 512kbB Manufacturer:20 Type:20 Density:13 ! ATTENTEION: No 4k-Ops, hence: not useabale for JesFs - > NotOK 177 | // MX25R8035: 1MByte Manufacturer:C2 Type:28 Density:14 -> Ok, tested 178 | // MX25R6435F: 8MByte Manufacturer:C2 Type:28 Density:17 -> Ok (should work) 179 | // MT25QL128ABA 16Byte Manufacturer:20 Type:BA Density:18 -> Ok (should work) 180 | // etc.. 181 | 182 | uint32_t identification; 183 | uint32_t total_flash_size; // Max. available space. Here up to 2GB possible 184 | uint32_t creation_date; // UNIX-Time in seconds since 1.1.1970, 0:00:00 (Time when formated) 0x0xFFFFFFFF not allowed! 185 | 186 | // -- jesfs Header, 187 | // Init-Infos 188 | uint32_t lusect_adr; 189 | uint32_t available_disk_size; // Available Disk space in Bytes (Marked 'todelete' or free) 190 | 191 | uint16_t files_used; // Used Header Sectors 192 | uint16_t files_active; // Active files (files_used - files_active = files_deleted) 193 | 194 | #ifdef JSTAT 195 | uint16_t sectors_todelete; // Counts in 1, not really required, just for statistics 196 | uint16_t sectors_clear; // Counts in 1, not really required, just for statistics 197 | uint16_t sectors_unknown; // Counts in 1, Should be zero... Bot really required, just for statistics 198 | #endif 199 | 200 | // Internal Buffer. Should be at least 64 Bytes. Default: 128 Bytes 201 | SF_BUFFER databuf; 202 | uint8_t state_flags; // Currently only STATE_DEEPSLEEP used, 8Bit (at end of struct) 203 | } SFLASH_INFO; 204 | 205 | extern SFLASH_INFO sflash_info; //Describes Flash 206 | 207 | // required by fs_sec1970_to_date() 208 | typedef struct{ // Structure for a full date (readable) 209 | uint8_t sec; 210 | uint8_t min; 211 | uint8_t h; 212 | uint8_t d; 213 | uint8_t m; 214 | uint16_t a; // 1970 - 2099 (2100 is no leap year) 215 | } FS_DATE; 216 | 217 | //-------------------- HighLevel Functions -------------------------- 218 | int16_t fs_start(uint8_t mode); 219 | int16_t fs_deepsleep(void); 220 | 221 | int16_t fs_format(uint8_t fmode); 222 | int32_t fs_read(FS_DESC *pdesc, uint8_t *pdest, uint32_t anz); 223 | int16_t fs_rewind(FS_DESC *pdesc); 224 | int16_t fs_open(FS_DESC *pdesc, char* pname, uint8_t flags); 225 | int16_t fs_notexists(char *pname); 226 | int16_t fs_write(FS_DESC *pdesc, uint8_t *pdata, uint32_t len); 227 | int16_t fs_close(FS_DESC *pdesc); 228 | int16_t fs_delete(FS_DESC *pdesc); 229 | int16_t fs_rename(FS_DESC *pd_odesc, FS_DESC *pd_ndesc); 230 | uint32_t fs_get_crc32(FS_DESC *pdesc); 231 | 232 | int16_t fs_info(FS_STAT *pstat, uint16_t fno); 233 | void fs_sec1970_to_date(uint32_t asecs, FS_DATE *pd); 234 | uint32_t fs_date2sec1970(FS_DATE *pd); 235 | void fs_set_static_secs(uint32_t newsecs); 236 | 237 | int16_t fs_check_disk(void cb_printf(char* fmt, ...), uint8_t *pline, uint32_t line_size); 238 | 239 | #ifdef __cplusplus 240 | } 241 | #endif 242 | //End 243 | -------------------------------------------------------------------------------- /jesfs_int.h: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * JesFs_int.h - internal headers 3 | * 4 | * JesFs - Jo's Embedded Serial File System 5 | * 6 | * The following parts are only relevant for 7 | * the (internal) medium/low level drivers 8 | * 9 | * (C) joembedded@gmail.com - www.joembedded.de 10 | * Version: see Header Files 11 | * 12 | *******************************************************************************/ 13 | 14 | #ifdef __cplusplus 15 | extern "C"{ 16 | #endif 17 | //------------------- Internal JesFS Defines ------------------------ 18 | 19 | // For Debugging/Stress tests: If defined, treat SPI as very small disk. Size must be Sectorsize^x and 20 | // at least 2 Sectors (=8kB) Maximum is 2GB, for 3-Byte SPI-Flash: Maximum 16MB 21 | // #define DEBUG_FORCE_MINIDISK_DENSITY 0x0F // (1<= 2 Sectors, here 0xF: 32kB = 8 Sectors 22 | 23 | #define MIN_DENSITY 0x0D // 0x13: 512k, smaller doesn not make sense, except for tests, 0x0D is the minimum 24 | #define MAX_DENSITY 0x18 // 0x18: 16 MB is the maximum for 3-byte addressed Flash. (But up to 2GB is possible) 25 | 26 | 27 | // Header of each sector 28 | #define HEADER_SIZE_L 3 // equals 12 Bytes 29 | #define HEADER_SIZE_B (HEADER_SIZE_L*4) 30 | // addition header at start of file 31 | #define FINFO_SIZE_B 36 32 | 33 | //------------------- Internal JesFS Functions ------------------------ 34 | 35 | #define HEADER_MAGIC 0x4673654A //'JesF' 36 | #define SECTOR_MAGIC_HEAD_ACTIVE 0xFFFF293A 37 | #define SECTOR_MAGIC_HEAD_DELETED 0xFFFF2130 38 | #define SECTOR_MAGIC_DATA 0xFFFF5D5B 39 | #define SECTOR_MAGIC_TODELETE 0xFFFF4040 40 | 41 | // Easy Access B W L 42 | typedef union{ 43 | uint8_t u8[4]; 44 | uint16_t u16[2]; 45 | uint32_t u32; 46 | } SF_LONGWORDBYTE; // Structure for byte/word/long access 47 | 48 | //------------------- LowLevel SPI Functions Depending on Hardware! ------- 49 | void sflash_wait_usec(uint32_t usec); 50 | 51 | int16_t sflash_spi_init(void); 52 | void sflash_spi_close(void); 53 | 54 | void sflash_select(void); 55 | void sflash_deselect(void); 56 | void sflash_spi_read(uint8_t *buf, uint16_t len); // len is 16Bit! 57 | void sflash_spi_write(const uint8_t *buf, uint16_t len); // len is 16Bit! 58 | 59 | //---------------- Little helpers for MediumLevel ------------------ 60 | uint32_t fs_strlen(char *s); 61 | void fs_strncpy(char *d, char *s, uint8_t maxchar); 62 | void fs_memset(uint8_t *p, uint8_t v, uint32_t n); 63 | int16_t fs_strcmp(char *s1, char *s2); 64 | uint32_t fs_track_crc32(uint8_t *pdata, uint32_t wlen, uint32_t crc_run); 65 | uint32_t fs_get_secs(void); // Unix-Secs 66 | 67 | //------------------- MediumLevel SPI Functions ------------------------ 68 | void sflash_bytecmd(uint8_t cmd, uint8_t more); 69 | uint32_t sflash_QuickScanIdentification(void); 70 | int16_t sflash_interpret_id(uint32_t id); 71 | void sflash_DeepPowerDown(void); 72 | void sflash_ReleaseFromDeepPowerDown(void); 73 | void sflash_read(uint32_t sadr, uint8_t* sbuf, uint16_t len); 74 | uint8_t sflash_ReadStatusReg(void); 75 | void sflash_WriteEnable(void); 76 | void sflash_PageWrite(uint32_t sadr, uint8_t* sbuf, uint16_t len); 77 | void sflash_BulkErase(void); 78 | void sflash_llSectorErase4k(uint32_t sadr); // LowLevel, bezogen auf 4K 79 | int16_t sflash_WaitBusy(uint32_t msec); 80 | int16_t sflash_WaitWriteEnabled(void); 81 | int16_t sflash_SectorWrite(uint32_t sflash_adr, uint8_t* sbuf, uint32_t len); 82 | int16_t sflash_SectorErase(uint32_t sadr); // High-Level 83 | #ifdef __cplusplus 84 | } 85 | #endif 86 | //--------------End of Internal JesFS Functions ------------------------ 87 | -------------------------------------------------------------------------------- /jesfs_ml.c: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * JesFs_ml.c: JesFs MediumLevel(Serial Flash Management) driver 3 | * 4 | * JesFs - Jo's Embedded Serial File System 5 | * 6 | * (C)joembedded@gmail.com - www.joembedded.de 7 | * Version: see Header Files 8 | * 9 | *******************************************************************************/ 10 | 11 | //#include 12 | 13 | /* Required Std. headers */ 14 | #include 15 | #include 16 | 17 | #include "jesfs.h" 18 | #include "jesfs_int.h" 19 | 20 | SFLASH_INFO sflash_info; // Describes the Flash 21 | 22 | //------------------- MediumLevel SPI Start ------------------------ 23 | //* Send SPUI Singlebyte-Command. More might follow 24 | void sflash_bytecmd(uint8_t cmd, uint8_t more) { 25 | sflash_select(); 26 | sflash_spi_write(&cmd, 1); 27 | if (!more) 28 | sflash_deselect(); 29 | } 30 | 31 | /* READ IDENTIFICATION (3 Bytes) 32 | * Flash must be woen up before, else ID is 0 for (most) flash*/ 33 | #define CMD_RDID 0x9F // Read Identification: Manuf.8 Type.8 Density.8 34 | uint32_t sflash_QuickScanIdentification(void) { 35 | uint32_t id; 36 | uint8_t buf[3]; 37 | sflash_bytecmd(CMD_RDID, 1); // More 38 | sflash_spi_read(buf, 3); 39 | sflash_deselect(); 40 | // Build 32Bit id safely, so it will work also on 16 Bit compilers (like MSP430) 41 | id = buf[0]; 42 | id <<= 8; // Manufacturer 43 | id |= buf[1]; 44 | id <<= 8; // Type 45 | id |= buf[2]; // Density 46 | return id; 47 | } 48 | 49 | /* Analyse ID (3 Bytes) of the flash */ 50 | int16_t sflash_interpret_id(uint32_t id) { 51 | uint8_t h; 52 | sflash_info.total_flash_size = 0; 53 | 54 | // Keep Flash-ID for optional Analysis 55 | sflash_info.identification = id; 56 | 57 | if (id == 0x000000) 58 | return -144; // ShortCircuit/Sleep in SPI? 59 | if (id == 0xFFFFFF) 60 | return -145; // Unconnected in SPI? 61 | 62 | switch (id >> 8) { // Check Without Density 63 | default: 64 | return -104; // Unknown ID/Type (!!: e.g. Micron has otherTypes th. Macronix, but identical Fkts (Quiescent Current for Macronix is the lowest..) 65 | 66 | // List of tested/knownAsGood Flash-Manufacturer/IDs (see Header File). Others may be added later 67 | case MACRONIX_MANU_TYP_RX: // Macronix - The 1MB-Version is on the TI CC1310 Launchpad, 2-16 MB on LTraX, .. 68 | case GIGADEV_MANU_TYP_WD: // GigaDevice up to 8Mbit 69 | case GIGADEV_MANU_TYP_WQ: // GigaDevice >= 2Mbit 70 | 71 | // ...add others... 72 | break; // OK! 73 | } 74 | 75 | #ifdef DEBUG_FORCE_MINIDISK_DENSITY 76 | h = DEBUG_FORCE_MINIDISK_DENSITY; // MiniDisc >= 2 Sectors Minimum 77 | #else 78 | h = id & 255; // Density 79 | if (h < MIN_DENSITY || h > MAX_DENSITY) 80 | return -103; // Unknown Density! 8*512kB-8*16MB ist OK 81 | #endif 82 | sflash_info.total_flash_size = 1 << (h); // All OK for JesFs: 8k-16MB OK fuer 3B-SPI Flash, opt. 2GB 83 | return 0; // OK 84 | } 85 | 86 | /* DEEP POWER DOWN 87 | * Flash Deep Sleep. Wake RELASE or (some) by READ IDENTIFIATION */ 88 | #define CMD_DEEPPOWERDOWN 0xB9 89 | void sflash_DeepPowerDown(void) { 90 | sflash_bytecmd(CMD_DEEPPOWERDOWN, 0); // NoMore 91 | } 92 | 93 | /* RELEASE from DEEP POWER DOWN 94 | * older Types of Flash give ID, newer; Omly WaleUp. After tPowerUp read ID 95 | * Very important: e.e. MX25R80535 requires ca. 35usec until ready! 96 | * Unbedingt beruecksichtigen (separat, User) */ 97 | #define CMD_RELEASEDPD 0xAB 98 | void sflash_ReleaseFromDeepPowerDown(void) { 99 | sflash_bytecmd(CMD_RELEASEDPD, 0); // NoMore 100 | // sflash_wait_usec(50); // Delay by caller 101 | } 102 | 103 | /* Read Len Bytes FlashAdr(sdr) to sbuf 104 | * For Adr>=16MB: use 4-Byte-CMD (0x13), extend Driver to 32 Bit!!! 105 | */ 106 | #define CMD_READDATA 0x03 107 | void sflash_read(uint32_t sadr, uint8_t *sbuf, uint16_t len) { 108 | uint8_t buf[4]; // 109 | buf[0] = CMD_READDATA; 110 | buf[1] = (uint8_t)(sadr >> 16); 111 | buf[2] = (uint8_t)(sadr >> 8); 112 | buf[3] = (uint8_t)(sadr); 113 | sflash_select(); 114 | sflash_spi_write(buf, 4); 115 | sflash_spi_read(sbuf, len); 116 | sflash_deselect(); 117 | } 118 | 119 | /* ReadStatusRegister Bit0: 1:WriteInprogress Bit1: WriteEnabled, Restbits ign. */ 120 | #define CMD_STATUSREG 0x05 121 | uint8_t sflash_ReadStatusReg(void) { 122 | uint8_t buf; 123 | sflash_bytecmd(CMD_STATUSREG, 1); // More 124 | sflash_spi_read(&buf, 1); 125 | sflash_deselect(); 126 | return buf; 127 | } 128 | /* Write Enable */ 129 | #define CMD_WRITEENABLE 0x06 130 | void sflash_WriteEnable(void) { 131 | sflash_bytecmd(CMD_WRITEENABLE, 0); // NoMore 132 | } 133 | 134 | /* Len Bytes write FlashAdr(sdr) to sbuf. 135 | * For Adr>=16MB: 4-Byte-CMD (0x12), separate! 136 | * Before: Enable set, autom. reset to 0 137 | * ca. 0.8-4 msec/pagewrite 138 | */ 139 | #define CMD_PAGEWRITE 0x02 140 | void sflash_PageWrite(uint32_t sadr, uint8_t *sbuf, uint16_t len) { 141 | uint8_t buf[4]; // 142 | buf[0] = CMD_PAGEWRITE; 143 | buf[1] = (uint8_t)(sadr >> 16); 144 | buf[2] = (uint8_t)(sadr >> 8); 145 | buf[3] = (uint8_t)(sadr); 146 | sflash_select(); 147 | sflash_spi_write(buf, 4); 148 | sflash_spi_write(sbuf, len); 149 | sflash_deselect(); 150 | } 151 | 152 | /* Start BULK Erase 153 | * (Write Enable before, takes long! Scan Status) 154 | */ 155 | #define CMD_BULKERASE 0xC7 156 | void sflash_BulkErase(void) { 157 | sflash_bytecmd(CMD_BULKERASE, 0); // NoMore 158 | } 159 | 160 | /* Sector Erase 4k 161 | * Attention: 4k not on all flash, bust almost all. 162 | * M25P40: - 163 | * MX25R8035: 100 typ / 300 max msec 164 | * MT25QL128 50 typ / 400 max msec 165 | */ 166 | #define CMD_SECTOR4K_ERASE 0x20 167 | void sflash_llSectorErase4k(uint32_t sadr) { 168 | uint8_t buf[4]; // 169 | buf[0] = CMD_SECTOR4K_ERASE; 170 | buf[1] = (uint8_t)(sadr >> 16); 171 | buf[2] = (uint8_t)(sadr >> 8); 172 | buf[3] = (uint8_t)(sadr); 173 | sflash_select(); 174 | sflash_spi_write(buf, 4); 175 | sflash_deselect(); 176 | } 177 | 178 | // x msec lang warten bis Flash fertig oder Fehler 179 | int16_t sflash_WaitBusy(uint32_t msec) { 180 | while (msec--) { 181 | sflash_wait_usec(1000); 182 | if (!(sflash_ReadStatusReg() & 1)) 183 | return 0; // OK 184 | } 185 | return -101; // Fehler! Timout 186 | } 187 | 188 | // WriteEnabled setzen und checken ob OK (lt. DB) oder Fehler(-1) 189 | int16_t sflash_WaitWriteEnabled(void) { 190 | // if(m_voltage()< MIN_VDD_SFLASH) return -1; // Voltage too low! Systemabhaengig 191 | sflash_WriteEnable(); 192 | if (sflash_ReadStatusReg() & 2) 193 | return 0; 194 | return -102; // Fehler! Flash locked? oder WP 195 | } 196 | 197 | /* Write Sector up to maximum. Write in Pages. Attention: Pageprog keeps the SFlash busy for a few mesec. Theoretically 198 | * the check yould be retarded for better performance, but thie makes the software more difficult. Maybe in a later version. 199 | */ 200 | int16_t sflash_SectorWrite(uint32_t sflash_adr, uint8_t *sbuf, uint32_t len) { 201 | uint32_t maxwrite; 202 | 203 | if (sflash_adr >= sflash_info.total_flash_size) 204 | return -105; // Flash Full! Illegal Address 205 | maxwrite = SF_SECTOR_PH - (sflash_adr & (SF_SECTOR_PH - 1)); 206 | if (len > maxwrite) 207 | return -106; // Sektorviolation 208 | 209 | while (len) { 210 | maxwrite = 256 - (uint8_t)sflash_adr; 211 | #ifdef SF_TX_TRANSFER_LIMIT 212 | if (maxwrite > SF_TX_TRANSFER_LIMIT) 213 | maxwrite = SF_TX_TRANSFER_LIMIT; 214 | #endif 215 | if (len < maxwrite) 216 | maxwrite = len; // Dann halt weniger in diesem Block schreiben 217 | if (sflash_WaitWriteEnabled()) 218 | return -102; // Wait unt. OK, Fehler 1:1 219 | sflash_PageWrite(sflash_adr, sbuf, maxwrite); 220 | if (sflash_WaitBusy(100)) 221 | return -101; // 100 msec unt. Page OK 222 | sbuf += maxwrite; 223 | sflash_adr += maxwrite; 224 | len -= maxwrite; 225 | } 226 | return 0; // Alles OK 227 | } 228 | 229 | // HighLevel SectorErase (inc. Error Check and 230 | int16_t sflash_SectorErase(uint32_t sadr) { 231 | if (sflash_WaitWriteEnabled()) 232 | return -102; 233 | sflash_llSectorErase4k(sadr); 234 | if (sflash_WaitBusy(400)) 235 | return -101; // 400 msec max page 236 | return 0; 237 | } 238 | //------------------- MediumLevel SPI OK ------------------------ -------------------------------------------------------------------------------- /platform_CC13XX_CC26XX/JesFs_ll_tirtos.c: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * JesFs_ll_tirtos.c: LowLevelDriver for TI-RTOS 3 | * 4 | * JesFs - Jo's Embedded Serial File System 5 | * 6 | * Tested on CC1310, CC1312 and CC2652 Launchpads 7 | * 8 | * Special notes for TI-RTOS: 9 | * - There is a blocking waiting function used (CPUdelay() in sflash_wait_usec()). 10 | * It may be replaced by a TI-RTOS waiting function (like Task_wait(), etc.. 11 | * - During SPI select active, the RED Led (Launchpad) is on. While waiting, it is toggeling, 12 | * so with a small Piezo you can 'hear' and 'see' the file system working ;-) 13 | * 14 | * (C) 2019 joembedded@gmail.com - www.joembedded.de 15 | * Version: 1.5 / 25.11.2019 16 | * 17 | *******************************************************************************/ 18 | 19 | // ---------------- required for JesFs ---------------------------- 20 | #include 21 | #include 22 | #include 23 | 24 | #include "jesfs.h" 25 | #include "jesfs_int.h" 26 | 27 | 28 | /* Driver Header files */ 29 | #include 30 | #include 31 | /* Board Header file */ 32 | #include "Board.h" 33 | 34 | // Different Boards have different Names for directly accessed Flash-CS-Pin 35 | #ifndef Board_GPIO_SPI_FLASH_CS 36 | #ifdef CC1310_LAUNCHXL 37 | #define Board_GPIO_SPI_FLASH_CS CC1310_LAUNCHXL_GPIO_SPI_FLASH_CS 38 | #endif 39 | #ifdef CC1312R1_LAUNCHXL 40 | #define Board_GPIO_SPI_FLASH_CS CC1312R1_LAUNCHXL_GPIO_SPI_FLASH_CS 41 | #endif 42 | #endif 43 | 44 | 45 | //------------------- LowLevel SPI START ------------------------ 46 | SPI_Handle flash_spi_handle; // NULL: Initialise, else active 47 | 48 | // INIT Hardware SPI 49 | int16_t sflash_spi_init(void){ 50 | SPI_Params spiParams; 51 | 52 | if(flash_spi_handle) return 0; // Already active! 53 | 54 | /* Configure the Flash CS pin (High) Attention: Nameconvention _GPIO_ via GPIO*/ 55 | GPIO_setConfig(Board_GPIO_SPI_FLASH_CS, GPIO_CFG_OUT_OD_PU | GPIO_CFG_OUT_STR_MED | GPIO_CFG_OUT_HIGH); 56 | 57 | SPI_Params_init(&spiParams); 58 | //spiParams.frameFormat=SPI_POL0_PHA0 (=Default) oder SPI_POL1_PHA1; beide OK 59 | //spiParams.bitRate=100000; // Mit 100k for Tests 60 | spiParams.bitRate=12000000; // Mit 12M fastest on CC1310, runs top on Launchpad 61 | // TI: 12 Mhz maximum if Master 62 | 63 | spiParams.transferMode = SPI_MODE_BLOCKING; 64 | spiParams.transferCallbackFxn = NULL; 65 | 66 | flash_spi_handle = SPI_open(Board_SPI0, &spiParams); // Close 67 | if (!flash_spi_handle ) return -100; // Watchdog will kill 68 | return 0; 69 | } 70 | 71 | void sflash_spi_close(void){ 72 | SPI_close(flash_spi_handle); 73 | flash_spi_handle=NULL; 74 | } 75 | 76 | // Connected a Piezo to GPIO_LED0 ;-) 77 | void sflash_wait_usec(uint32_t usec){ 78 | GPIO_toggle(Board_GPIO_RLED); // Connect a Piezo to GIPO and; Hear Me Working! 79 | CPUdelay(usec*12); // On CC1310@48MHz, Release&Debug: 12 cycles/usec 80 | } 81 | 82 | void sflash_select(void){ 83 | GPIO_write(Board_GPIO_RLED, 1); // Hear Me Working! Led ON 84 | GPIO_write(Board_GPIO_SPI_FLASH_CS, 0); 85 | } 86 | void sflash_deselect(void){ 87 | GPIO_write(Board_GPIO_RLED, 0); // Hear Me Working! Led OFF 88 | GPIO_write(Board_GPIO_SPI_FLASH_CS, 1); 89 | } 90 | 91 | /* !!! Attention: TI-RTOS may have problems with the heap, if len is too large 92 | * Seems to work well with DriverLib, but with TI-RTOS drivers only <=1k seems to work well */ 93 | void sflash_spi_read(uint8_t *buf, uint16_t len){ 94 | SPI_Transaction masterTransaction; 95 | 96 | masterTransaction.count = len; 97 | masterTransaction.txBuf = NULL; 98 | masterTransaction.arg = NULL; 99 | masterTransaction.rxBuf = buf; 100 | SPI_transfer(flash_spi_handle, &masterTransaction); 101 | } 102 | 103 | /* Because of SPI page-Size (def. 256 Bytes) len is no problem. */ 104 | void sflash_spi_write(const uint8_t *buf, uint16_t len){ 105 | SPI_Transaction masterTransaction; 106 | 107 | masterTransaction.count = len; 108 | masterTransaction.txBuf = (void*)buf; 109 | masterTransaction.arg = NULL; 110 | masterTransaction.rxBuf = NULL; 111 | 112 | SPI_transfer(flash_spi_handle, &masterTransaction); 113 | } 114 | //------------------- LowLevel SPI Fertig ------------------------ 115 | -------------------------------------------------------------------------------- /platform_CC13XX_CC26XX/ReadMe.txt: -------------------------------------------------------------------------------- 1 | # ReadMe.txt # 2 | 3 | Please read the JesFs.pdf how to build the JesFs Demo for CC13XX and CC26XX CPUs. 4 | -------------------------------------------------------------------------------- /platform_CC13XX_CC26XX/tb_tools_cc.c: -------------------------------------------------------------------------------- 1 | /********************************************************************* 2 | * tb_tools_cc.c - Toolbox for UART, Unix-Time, .. 3 | * 4 | * For platform CC13XX / CC26XX 5 | * 6 | * 2019 (C) joembedded.de 7 | * Version: 8 | * 1.0 / 25.11.2019 9 | * 1.01 / 07.12.2019 power optim. for tb_uninit() ToDo 10 | * 1.02 / 09.12.2019 return empty string on timeout 11 | *********************************************************************/ 12 | 13 | // TI-RTOS requires Bunch of Header Files 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | /* Driver Header files */ 26 | #include 27 | //#include 28 | #include 29 | #include 30 | #include 31 | #include 32 | // Driverlib 33 | #include 34 | #include DeviceFamily_constructPath(driverlib/sys_ctrl.h) 35 | #include DeviceFamily_constructPath(driverlib/aon_rtc.h) 36 | 37 | #include "Board.h" 38 | 39 | #include 40 | #include 41 | #include 42 | #include 43 | #include 44 | #include // for var_args 45 | #include // for sleep/usleep 46 | 47 | #include "tb_tools.h" 48 | 49 | #ifndef CC13XX_CC26XX // Define this Macro in ProjectOptions - PredefinedSymbols 50 | #error "Define the Platform (CC13XX_CC26XX)" 51 | #endif 52 | 53 | // ---- local defines -------------- 54 | 55 | // ---------- locals uart -------------------- 56 | #define TB_SIZE_LINE_OUT 80 // 1 terminal line working buffer 57 | static char tb_uart_line_out[TB_SIZE_LINE_OUT]; 58 | 59 | #define UART_RX_BUFSIZE 128 // Any size OK 60 | #define UART_TX_BUFSIZE 128 // 61 | #define UART_TX_TIMEOUT 10000 // Semaphoren-Timeout in Task-Ticks (100 msec enough for 256 Bytes(22 msec)) 62 | 63 | static UART_Handle uart_handle; // Handle 64 | 65 | // transfer buffers 66 | static uint8_t uart_tx_buf[UART_TX_BUFSIZE]; 67 | static Semaphore_Handle uart_tx_sema; 68 | 69 | static uint8_t uart_rx_buf[UART_RX_BUFSIZE]; 70 | static uint16_t uart_rxidx_in, uart_rxidx_out; 71 | static int16_t uart_rxfrei_anz; 72 | 73 | // ---- locals Watcdog ---- 74 | static bool tb_wdt_enabled=false; 75 | 76 | static bool tb_init_flag=false; 77 | 78 | //--------------- hardware drivers UART ---------------------- 79 | //---------uart_blockout--------- 80 | static int16_t uart_blkout(uint8_t* pu, uint16_t len){ 81 | if(len>UART_TX_BUFSIZE) return -1; 82 | 83 | // TX-Puffer 256 Bytes => wait max 22 msec 84 | Semaphore_pend(uart_tx_sema, UART_TX_TIMEOUT); // 85 | 86 | memcpy(uart_tx_buf,pu, len); // D S n 87 | UART_write(uart_handle,uart_tx_buf,len); 88 | return 0; 89 | } 90 | // ---- callback Thread simply frees ressource ------------- 91 | static void _uart_handle_write_cb(UART_Handle handle, void *tmp_txBuf, size_t size){ 92 | Semaphore_post(uart_tx_sema); // Ready! Seems to fail in rare cases? 93 | } 94 | 95 | // --- read Callback: Es wurden size_bytes gelesen, wieviel weiter 96 | static void _uart_handle_read_cb(UART_Handle handle, void *tmp_txBuf, size_t size){ 97 | uint16_t frei; 98 | int16_t mxf; 99 | uint32_t key=Hwi_disable(); 100 | mxf=uart_rxfrei_anz-size; // Soviel ist JETZT noch frei (int16) 101 | 102 | uart_rxidx_in+=size; 103 | if(uart_rxidx_in>=UART_RX_BUFSIZE) uart_rxidx_in=0; // Overflow 104 | if(uart_rxidx_in>=uart_rxidx_out) frei=UART_RX_BUFSIZE-uart_rxidx_in; 105 | else frei=uart_rxidx_out-uart_rxidx_in; 106 | // Bei FLOW-Ctrl. evtl. kleinere Bloecke als 1/4 lesen fuer feinere Granularitaet 107 | if(frei>(UART_RX_BUFSIZE/4)) frei=(UART_RX_BUFSIZE/4); 108 | 109 | uart_rxfrei_anz=mxf; // merken 110 | Hwi_restore(key); 111 | 112 | UART_read(uart_handle, uart_rx_buf+uart_rxidx_in , frei); // Empfangen was geht 113 | } 114 | // ----------- uart_open--------------------------- 115 | // Manual Flow! 116 | int16_t uart_open(void){ 117 | Semaphore_Params semp; 118 | 119 | // Zuerst die Semaphoren erzeugen! 120 | // Semaphore fuer TX erzeugen 121 | Semaphore_Params_init(&semp); 122 | semp.mode = Semaphore_Mode_BINARY; 123 | uart_tx_sema=Semaphore_create(1,&semp, NULL); // Geht auch ohne EB 124 | 125 | uart_rxidx_in=0; // In-Pointer 126 | uart_rxidx_out=0; // Out-Pointer 127 | uart_rxfrei_anz=UART_RX_BUFSIZE; // Wieviel verfuegbar insgesamt 128 | 129 | UART_Params uartParams; 130 | UART_Params_init(&uartParams); 131 | uartParams.writeDataMode = UART_DATA_BINARY; // TEXT nicht auf CC26xx 132 | uartParams.readDataMode = UART_DATA_BINARY; // TEXT nicht auf CC26xx 133 | uartParams.readReturnMode = UART_RETURN_FULL; 134 | uartParams.readEcho = UART_ECHO_OFF; // ECHO ON nicht auf CC26xx 135 | uartParams.baudRate = 115200; // <--- 115kBd 136 | 137 | uartParams.readMode = UART_MODE_CALLBACK; 138 | uartParams.readCallback = _uart_handle_read_cb; 139 | uartParams.writeMode = UART_MODE_CALLBACK; 140 | uartParams.writeCallback = _uart_handle_write_cb; 141 | 142 | // Alwasys UART No 0 143 | uart_handle = UART_open(0, &uartParams); // MUSS klappen! 144 | if(!uart_handle) return -1004; // Kann nicht oeffnen! 145 | 146 | UART_control(uart_handle, UARTCC26XX_CMD_RETURN_PARTIAL_ENABLE, NULL); // Nicht noetig bei Einzelzeichen 147 | UART_read(uart_handle, uart_rx_buf , (UART_RX_BUFSIZE/4)); // Maximal 1/4 Puffer lesen 148 | 149 | return 0; 150 | } 151 | 152 | // Kann bedenkenlos jederzeit aufgerufen werden 153 | void uart_close(void){ 154 | if(uart_handle) { 155 | UART_readCancel(uart_handle); 156 | // UART_control(uart_handle, UART_CMD_RXDISABLE, 0); // Suggested by TI because of I_q, but no results 157 | UART_writeCancel(uart_handle); 158 | UART_close(uart_handle); 159 | 160 | /** Dummy open/close with no callbacks, because of too high I_q */ 161 | UART_Params uartParams; 162 | UART_Params_init(&uartParams); 163 | // Alwasys UART No 0 164 | uart_handle = UART_open(0, &uartParams); 165 | UART_close(uart_handle); 166 | 167 | uart_handle=NULL; 168 | } 169 | Semaphore_delete(&uart_tx_sema); 170 | 171 | } 172 | // ----------- UART drivers end ------------- 173 | 174 | 175 | // -------- init Toolbox ----------------- 176 | // Init UART, SPI and optionally Watchdog - Power opt. missing 177 | void tb_init(void){ 178 | if(tb_init_flag==false){ 179 | /* Init what we need */ 180 | GPIO_init(); // LEDs (and JesFs too) 181 | /* Configure the LED pin */ 182 | GPIO_setConfig(Board_GPIO_RLED, GPIO_CFG_OUT_STD | GPIO_CFG_OUT_LOW); // RED 183 | 184 | UART_init(); // required for HW uart 185 | //I2C_init(); 186 | SPI_init(); // normally required required (several instances available) 187 | 188 | uart_open(); 189 | 190 | tb_init_flag=true; 191 | } 192 | } 193 | 194 | // ------ uninit all -------------------- 195 | void tb_uninit(void){ 196 | if(tb_init_flag){ 197 | // LowPower ToDo... 198 | // uart_close(); etc.. 199 | tb_init_flag=false; 200 | } 201 | } 202 | 203 | // ------ Only LED 0 (RED) available on CCxxyy ----- 204 | void tb_board_led_on(uint8_t idx){ 205 | GPIO_write(Board_GPIO_RLED, 1); 206 | } 207 | void tb_board_led_off(uint8_t idx){ 208 | GPIO_write(Board_GPIO_RLED, 0); 209 | } 210 | void tb_board_led_invert(uint8_t idx){ 211 | GPIO_toggle(Board_GPIO_RLED); 212 | } 213 | 214 | 215 | // ------- System Reset ------------- 216 | void tb_system_reset(void){ 217 | SysCtrlSystemReset(); // Up to (TI-RTOS+Debugger) what happens: Reset, Stall, Nirvana, .. See TI docu. 218 | } 219 | 220 | 221 | // ------Watchdog, triggered befor reset ----- 222 | // ---- enable the watchdog only once! ----------- 223 | // #define USE_WATCHDOG 224 | #define WDINTV 1500000 // 1 sec on cc13xx 225 | #define WD_INTERVAL 250 // 250 secs for large Flash 226 | static uint16_t wd_cnt=WD_INTERVAL; 227 | 228 | Watchdog_Handle watchdogHandle; 229 | void watchdogCallback(uintptr_t _unused){ 230 | Watchdog_clear(watchdogHandle); 231 | if(wd_cnt--==0) for(;;); // Die 232 | } 233 | 234 | void tb_watchdog_init(void){ 235 | #ifdef USE_WATCHDOG 236 | Watchdog_init(); 237 | /* Create and enable a Watchdog with resets disabled */ 238 | Watchdog_Params_init(¶ms); 239 | params.callbackFxn = (Watchdog_Callback)watchdogCallback; 240 | params.resetMode = Watchdog_RESET_ON; 241 | //params.debugStallMode = Watchdog_DEBUG_STALL_OFF; // (Default (OK for Debug) is STALL_ON) 242 | watchdogHandle = Watchdog_open(Board_WATCHDOG0, ¶ms); // Assert it works.. 243 | Watchdog_setReload(watchdogHandle, WDINTV); 244 | tb_wdt_enabled=true; 245 | #endif 246 | } 247 | 248 | // ---- Feed the watchdog, No function if WD not initialised ------------ 249 | // feed_ticks currently ignored, but >0 250 | void tb_watchdog_feed(uint32_t feed_ticks){ 251 | if(feed_ticks && tb_wdt_enabled) { 252 | wd_cnt=WD_INTERVAL; 253 | } 254 | } 255 | 256 | 257 | // --- A low Power delay --- 258 | void tb_delay_ms(uint32_t msec){ 259 | while(msec){ 260 | if(msec>=1000) { 261 | sleep(1); 262 | msec -=1000; 263 | }else{ 264 | usleep(msec*1000); // < 1e6 265 | break; 266 | } 267 | } 268 | } 269 | 270 | // ---- Unix-Timer. Must be called periodically to work, but at least twice per RTC-overflow (512..xx secs) --- 271 | uint32_t tb_time_get(void){ 272 | return Seconds_get(); // use BIOS here 273 | } 274 | 275 | // Set time, regarding the timer 276 | void tb_time_set(uint32_t new_secs){ 277 | return Seconds_set(new_secs); // use BIOS here 278 | } 279 | 280 | // ----- fine clocl ticks functions --------------------- 281 | // Use the difference of 2 timestamps to calclualte msec Time 282 | // CCxxyy: RTC runns with 65535 ticks/sec 283 | uint32_t tb_get_ticks(void){ 284 | return AONRTCCurrentCompareValueGet(); 285 | } 286 | 287 | // Warning: might overflow for very long ticks, maximum delta is 24 Bit 288 | uint32_t tb_deltaticks_to_ms(uint32_t t0, uint32_t t1){ 289 | uint32_t delta_ticks = t1-t0; 290 | return (delta_ticks * 125)/8192; // OK for ranges 0..524 secs 291 | } 292 | 293 | 294 | // tb_printf(): printf() to toolbox uart. Wait if busy 295 | void tb_printf(char* fmt, ...){ 296 | size_t ulen; 297 | va_list argptr; 298 | va_start(argptr, fmt); 299 | 300 | ulen=vsnprintf(tb_uart_line_out, TB_SIZE_LINE_OUT, fmt, argptr); // vsn: limit! 301 | va_end(argptr); 302 | // vsnprintf() limits output to given size, but might return more. 303 | if(ulen>TB_SIZE_LINE_OUT-1) ulen=TB_SIZE_LINE_OUT-1; 304 | 305 | uart_blkout((uint8_t*)tb_uart_line_out, ulen); 306 | } 307 | 308 | // tb_putc(): Wait if not ready 309 | void tb_putc(char c){ 310 | tb_printf("%c",c); 311 | } 312 | 313 | // ---- Input functions 0: Nothing available (tb_kbhit is faster than tb_getc) --------- 314 | int16_t tb_kbhit(void){ 315 | int16_t res; 316 | uint32_t key=Hwi_disable(); 317 | res=UART_RX_BUFSIZE-uart_rxfrei_anz; 318 | Hwi_restore(key); 319 | return res; 320 | } 321 | 322 | // ---- get 1 char (0..255) (or -1 if nothing available) 323 | int16_t tb_getc(void){ 324 | int16_t res; 325 | int16_t mxf; 326 | uint32_t key=Hwi_disable(); 327 | if(uart_rxidx_in == uart_rxidx_out){ 328 | mxf=UART_RX_BUFSIZE; // UART-Puffer ist leer-> Maximaler Fuellstand! 329 | res=-1; 330 | }else{ 331 | res=uart_rx_buf[uart_rxidx_out++]; // Clip 332 | if(uart_rxidx_out==UART_RX_BUFSIZE) uart_rxidx_out=0; 333 | mxf=uart_rxfrei_anz+1; 334 | } 335 | uart_rxfrei_anz=mxf; 336 | Hwi_restore(key); 337 | return res; 338 | } 339 | 340 | // Get String with Timout (if >0) in msec of infinite (Timout 0), No echo (max_uart_in without trailing \0!) 341 | int16_t tb_gets(char* input, int16_t max_uart_in, uint16_t max_wait_ms, uint8_t echo){ 342 | int16_t idx=0; 343 | int16_t res; 344 | char c; 345 | max_uart_in--; // Reserve 1 Byte for End-0 346 | for(;;){ 347 | res=tb_kbhit(); 348 | if(res>0){ 349 | res=tb_getc(); 350 | if(res<0) break; 351 | c=res; 352 | if(c=='\n' || c=='\r') { 353 | break; // NL CR or whatever (no Echo for NL CR) 354 | }else if(c==8){ // Backspace 355 | if(idx>0){ 356 | idx--; 357 | if(echo){ 358 | tb_putc(8); 359 | tb_putc(' '); 360 | tb_putc(8); 361 | } 362 | } 363 | }else if(c>=' ' && c<128 && idx 15 | #include 16 | #include 17 | 18 | #include "jesfs.h" 19 | #include "jesfs_int.h" 20 | 21 | 22 | #include // Atmel start header files 23 | 24 | //------------------- LowLevel SPI START ------------------------ 25 | struct io_descriptor *spi_io; 26 | 27 | // INIT Hardware SPI 28 | int16_t sflash_spi_init(void){ 29 | spi_m_sync_get_io_descriptor(&spi_0, &spi_io); 30 | spi_m_sync_enable(&spi_0); 31 | return 0; 32 | } 33 | 34 | void sflash_spi_close(void){ 35 | spi_m_sync_disable(&spi_0); 36 | } 37 | 38 | void sflash_wait_usec(uint32_t usec){ 39 | delay_us(usec); 40 | } 41 | 42 | void sflash_select(void){ 43 | gpio_set_pin_level(FLASH_CS, false); 44 | } 45 | 46 | void sflash_deselect(void){ 47 | gpio_set_pin_level(FLASH_CS, true); 48 | } 49 | 50 | void sflash_spi_read(uint8_t *buf, uint16_t len){ 51 | io_read( spi_io, buf, len ); 52 | } 53 | 54 | void sflash_spi_write(const uint8_t *buf, uint16_t len){ 55 | io_write( spi_io, buf, len ); 56 | } 57 | //------------------- LowLevel SPI Fertig ------------------------ 58 | -------------------------------------------------------------------------------- /platform_SAMD20/tb_tools_atmelstart.c: -------------------------------------------------------------------------------- 1 | /********************************************************************* 2 | * tb_tools_atmelstart.c - Toolbox for UART, Unix-Time, .. 3 | * 4 | * For platform ATSAMD20eXX 5 | * 6 | * 2019 (C) joembedded.de 7 | * Version: 8 | * 1.0 / 13.1.2022 9 | *********************************************************************/ 10 | 11 | #include // Atmel start headers 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include // for var_args 19 | 20 | #include "tb_tools.h" 21 | 22 | #ifndef SAMD20 // Define this Macro in ProjectOptions - PredefinedSymbols 23 | #error "Define the Platform (SAMD20)" 24 | #endif 25 | 26 | // ---- local defines -------------- 27 | 28 | // ---------- locals uart -------------------- 29 | #define TB_SIZE_LINE_OUT 80 // 1 terminal line working buffer 30 | static char tb_uart_line_out[TB_SIZE_LINE_OUT]; 31 | 32 | #define UART_RX_BUFSIZE 128 // Any size OK 33 | #define UART_TX_BUFSIZE 128 // 34 | #define UART_TX_TIMEOUT 10000 // Semaphoren-Timeout in Task-Ticks (100 msec enough for 256 Bytes(22 msec)) 35 | 36 | struct io_descriptor *serial_io; // Handle 37 | volatile bool tb_uart_tx_in_progress=false; 38 | volatile int16_t tb_uart_rx_ndx_head=0; 39 | volatile int16_t tb_uart_rx_ndx_tail=0; 40 | uint8_t tb_uart_tx_buf[UART_TX_BUFSIZE]; 41 | uint8_t tb_uart_rx_buf[UART_RX_BUFSIZE]; 42 | 43 | // ---- locals Watcdog ---- 44 | static bool tb_wdt_enabled=false; 45 | 46 | static bool tb_init_flag=false; 47 | 48 | // ---- locals RTC ---- 49 | static volatile unsigned int tb_rtc_overflows=0; 50 | static struct timer_task RTC_task1; 51 | 52 | //--------------- hardware drivers UART ---------------------- 53 | static void tx_cb_serial(const struct usart_async_descriptor *const io_descr) 54 | { 55 | tb_uart_tx_in_progress=false; 56 | } 57 | static void rx_cb_serial(const struct usart_async_descriptor *const io_descr) 58 | { 59 | io_read(serial_io, &tb_uart_rx_buf[tb_uart_rx_ndx_head % UART_TX_BUFSIZE], 1); 60 | tb_uart_rx_ndx_head++; 61 | } 62 | 63 | //---------uart_blockout--------- 64 | static int16_t uart_blkout(uint8_t* pu, uint16_t len){ 65 | while(tb_uart_tx_in_progress) 66 | ; 67 | tb_uart_tx_in_progress=true; 68 | memcpy(tb_uart_tx_buf, pu, len); 69 | io_write(serial_io, tb_uart_tx_buf, len); 70 | return 0; 71 | } 72 | // ----------- uart_open--------------------------- 73 | // Manual Flow! 74 | int16_t uart_open(void){ 75 | usart_async_register_callback(&serial, USART_ASYNC_TXC_CB, tx_cb_serial); 76 | usart_async_register_callback(&serial, USART_ASYNC_RXC_CB, rx_cb_serial); 77 | usart_async_get_io_descriptor(&serial, &serial_io); 78 | usart_async_enable(&serial); 79 | return 0; 80 | } 81 | 82 | // Kann bedenkenlos jederzeit aufgerufen werden 83 | void uart_close(void){ 84 | usart_async_disable(&serial); 85 | } 86 | // ----------- UART drivers end ------------- 87 | 88 | // RTC callback 89 | static void rtc_task1_cb(const struct timer_task *const timer_task) 90 | { 91 | tb_rtc_overflows++; 92 | } 93 | 94 | void rtc_init() 95 | { 96 | RTC_task1.interval = 33; 97 | RTC_task1.cb = rtc_task1_cb; 98 | RTC_task1.mode = TIMER_TASK_REPEAT; 99 | 100 | timer_add_task(&RTC_0, &RTC_task1); 101 | timer_start(&RTC_0); 102 | } 103 | 104 | // -------- init Toolbox ----------------- 105 | // Init UART, SPI and optionally Watchdog - Power opt. missing 106 | void tb_init(void){ 107 | if(tb_init_flag==false){ 108 | atmel_start_init(); 109 | 110 | uart_open(); 111 | 112 | rtc_init(); 113 | 114 | // TODO: SPI init 115 | 116 | tb_init_flag=true; 117 | } 118 | } 119 | 120 | // ------ uninit all -------------------- 121 | void tb_uninit(void){ 122 | if(tb_init_flag){ 123 | // LowPower ToDo... 124 | // uart_close(); etc.. 125 | tb_init_flag=false; 126 | } 127 | } 128 | 129 | // ------ Only LED 0 (RED) available on SAMD20 ----- 130 | void tb_board_led_on(uint8_t idx){ 131 | gpio_set_pin_level(LED_RED, false); 132 | } 133 | void tb_board_led_off(uint8_t idx){ 134 | gpio_set_pin_level(LED_RED, true); 135 | } 136 | void tb_board_led_invert(uint8_t idx){ 137 | gpio_toggle_pin_level(LED_RED); 138 | } 139 | 140 | 141 | // ------- System Reset ------------- 142 | void tb_system_reset(void){ 143 | while(1); 144 | } 145 | 146 | 147 | // ------Watchdog, triggered befor reset ----- 148 | // ---- enable the watchdog only once! ----------- 149 | // #define USE_WATCHDOG 150 | 151 | uint32_t tb_watchdog_init(void){ 152 | #ifdef USE_WATCHDOG 153 | wdt_enable(&WDT_0); 154 | tb_wdt_enabled=true; 155 | return 0; 156 | #endif 157 | return -1; 158 | } 159 | 160 | // ---- Feed the watchdog, No function if WD not initialized ------------ 161 | // feed_ticks currently ignored, but >0 162 | void tb_watchdog_feed(uint32_t feed_ticks){ 163 | if(feed_ticks && tb_wdt_enabled) { 164 | wdt_feed(&WDT_0); 165 | } 166 | } 167 | 168 | // --- A low Power delay --- 169 | void tb_delay_ms(uint32_t msec){ 170 | delay_ms(msec); 171 | } 172 | 173 | // ---- Unix-Timer. Must be called periodically to work, but at least twice per RTC-overflow (512..xx secs) --- 174 | uint32_t tb_time_get(void){ 175 | return (tb_rtc_overflows >> 10); 176 | } 177 | 178 | // Set time, regarding the timer 179 | void tb_time_set(uint32_t new_secs){ 180 | tb_rtc_overflows = (new_secs << 10); 181 | } 182 | 183 | // ----- fine clock ticks functions --------------------- 184 | // Use the difference of 2 timestamps to calculalte msec Time 185 | uint32_t tb_get_ticks(void){ 186 | return tb_rtc_overflows; 187 | } 188 | 189 | // Warning: might overflow for very long ticks, maximum delta is 24 Bit 190 | uint32_t tb_deltaticks_to_ms(uint32_t t0, uint32_t t1){ 191 | return t1-t0; 192 | } 193 | 194 | 195 | // tb_printf(): printf() to toolbox uart. Wait if busy 196 | void tb_printf(char* fmt, ...){ 197 | size_t ulen; 198 | va_list argptr; 199 | va_start(argptr, fmt); 200 | 201 | ulen=vsnprintf(tb_uart_line_out, TB_SIZE_LINE_OUT, fmt, argptr); // vsn: limit! 202 | va_end(argptr); 203 | // vsnprintf() limits output to given size, but might return more. 204 | if(ulen>TB_SIZE_LINE_OUT-1) ulen=TB_SIZE_LINE_OUT-1; 205 | 206 | uart_blkout((uint8_t*)tb_uart_line_out, ulen); 207 | } 208 | 209 | // tb_putc(): Wait if not ready 210 | int16_t tb_putc(char c){ 211 | tb_printf("%c",c); 212 | return 0; 213 | } 214 | 215 | // ---- Input functions 0: Nothing available (tb_kbhit is faster than tb_getc) --------- 216 | int16_t tb_kbhit(void){ 217 | return tb_uart_rx_ndx_head - tb_uart_rx_ndx_tail; 218 | } 219 | 220 | // ---- get 1 char (0..255) (or -1 if nothing available) 221 | int16_t tb_getc(void){ 222 | char c = (char)tb_uart_rx_buf[tb_uart_rx_ndx_tail % UART_RX_BUFSIZE]; 223 | tb_uart_rx_ndx_tail++; 224 | return (int16_t)c; 225 | } 226 | 227 | // Get String with Timout (if >0) in msec of infinite (Timout 0), No echo (max_uart_in without trailing \0!) 228 | int16_t tb_gets(char* input, int16_t max_uart_in, uint16_t max_wait_ms, uint8_t echo){ 229 | int16_t idx=0; 230 | int16_t res; 231 | char c; 232 | max_uart_in--; // Reserve 1 Byte for End-0 233 | max_wait_ms /= 1000; 234 | uint32_t s_time = tb_time_get(); 235 | for(;;){ 236 | res=tb_kbhit(); 237 | if(res>0){ 238 | res=tb_getc(); 239 | c=res; 240 | if(c=='\n' || c=='\r') { 241 | break; // NL CR or whatever (no Echo for NL CR) 242 | }else if(c==8){ // Backspace 243 | if(idx>0){ 244 | idx--; 245 | if(echo){ 246 | tb_putc(8); 247 | tb_putc(' '); 248 | tb_putc(8); 249 | } 250 | } 251 | }else if(c>=' ' && c<128 && idx max_wait_ms ) break; 258 | } 259 | } 260 | input[idx]=0; // Terminate String 261 | return idx; 262 | } 263 | 264 | //** 265 | -------------------------------------------------------------------------------- /platform_WIN/JesFsDemo_cpp_studio.cbproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | {8F19153B-156D-4CF2-9293-AE2EAD6091DE} 4 | 18.4 5 | None 6 | True 7 | Debug 8 | Win32 9 | 1 10 | Console 11 | 12 | 13 | true 14 | 15 | 16 | true 17 | Base 18 | true 19 | 20 | 21 | true 22 | Base 23 | true 24 | 25 | 26 | true 27 | Base 28 | true 29 | 30 | 31 | JPHNE 32 | .\$(Platform)\$(Config) 33 | .\$(Platform)\$(Config) 34 | false 35 | true 36 | true 37 | $(BDSLIB)\$(PLATFORM)\release\$(LANGDIR);$(ILINK_TranslatedLibraryPath) 38 | CppConsoleApplication 39 | CloudService;FireDAC;FireDACCommon;FireDACCommonDriver;FireDACIBDriver;FireDACSqliteDriver;inet;RESTBackendComponents;RESTComponents;soapmidas;soaprtl;soapserver;$(PackageImports) 40 | System;Xml;Data;Datasnap;Web;Soap;$(DCC_Namespace) 41 | JesFsDemo_cpp_studio 42 | <_TCHARMapping>char 43 | ..\;$(IncludePath) 44 | ..\;$(ILINK_LibraryPath) 45 | 46 | 47 | adortl;appanalytics;bcbie;bcbsmp;bindcomp;bindcompdbx;bindcompfmx;bindcompvcl;bindengine;CustomIPTransport;dbexpress;dbrtl;dbxcds;DbxClientDriver;DbxCommonDriver;DBXInterBaseDriver;DBXMySQLDriver;DBXSqliteDriver;dsnap;dsnapcon;dsnapxml;FireDACADSDriver;FireDACCommonODBC;FireDACMSAccDriver;FireDACMySQLDriver;FireDACPgDriver;fmx;fmxase;fmxdae;fmxFireDAC;fmxobj;IndyCore;IndyIPClient;IndyIPCommon;IndyIPServer;IndyProtocols;IndySystem;inetdb;inetdbxpress;rtl;svn;tethering;vcl;vclactnband;vcldb;vcldsnap;vclFireDAC;vclie;vclimg;VCLRESTComponents;VclSmp;vcltouch;vclwinx;vclx;xmlrtl;$(PackageImports) 48 | Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace) 49 | Debug 50 | CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments= 51 | 1033 52 | $(BDS)\bin\Artwork\Windows\UWP\cppreg_UwpDefault_44.png 53 | $(BDS)\bin\Artwork\Windows\UWP\cppreg_UwpDefault_150.png 54 | 55 | 56 | false 57 | true 58 | false 59 | true 60 | _DEBUG;$(Defines) 61 | false 62 | None 63 | DEBUG 64 | true 65 | true 66 | true 67 | true 68 | Full 69 | true 70 | true 71 | true 72 | true 73 | true 74 | $(BDSLIB)\$(PLATFORM)\debug;$(ILINK_LibraryPath) 75 | $(BDSLIB)\$(PLATFORM)\debug\$(LANGDIR);$(ILINK_TranslatedLibraryPath) 76 | 77 | 78 | NDEBUG;$(Defines) 79 | None 80 | 81 | 82 | 83 | 3 84 | 85 | 86 | 0 87 | 88 | 89 | 4 90 | 91 | 92 | 1 93 | 94 | 95 | 2 96 | 97 | 98 | 6 99 | 100 | 101 | 7 102 | 103 | 104 | 5 105 | 106 | 107 | Cfg_2 108 | Base 109 | 110 | 111 | Base 112 | 113 | 114 | Cfg_1 115 | Base 116 | 117 | 118 | 119 | CPlusPlusBuilder.Personality.12 120 | CppConsoleApplication 121 | 122 | 123 | 124 | False 125 | True 126 | True 127 | False 128 | 129 | 130 | 131 | 132 | 133 | .\ 134 | true 135 | 136 | 137 | 138 | 139 | true 140 | 141 | 142 | 143 | 144 | true 145 | 146 | 147 | 148 | 149 | true 150 | 151 | 152 | 153 | 154 | true 155 | 156 | 157 | 158 | 159 | true 160 | 161 | 162 | 163 | 164 | .\ 165 | true 166 | 167 | 168 | 169 | 170 | true 171 | 172 | 173 | 174 | 175 | true 176 | 177 | 178 | 179 | 180 | true 181 | 182 | 183 | 184 | 185 | true 186 | 187 | 188 | 189 | 190 | true 191 | 192 | 193 | 194 | 195 | JesFsDemo_cpp_studio.exe 196 | true 197 | 198 | 199 | 200 | 201 | .\ 202 | true 203 | 204 | 205 | 206 | 207 | true 208 | 209 | 210 | 211 | 212 | .\ 213 | true 214 | 215 | 216 | 217 | 218 | JesFsDemo_cpp_studio.tds 219 | true 220 | 221 | 222 | 223 | 224 | true 225 | 226 | 227 | 228 | 229 | true 230 | 231 | 232 | 233 | 234 | .\ 235 | true 236 | 237 | 238 | 239 | 240 | true 241 | 242 | 243 | 244 | 245 | 1 246 | 247 | 248 | Contents\MacOS 249 | 0 250 | 251 | 252 | 253 | 254 | classes 255 | 1 256 | 257 | 258 | 259 | 260 | library\lib\armeabi-v7a 261 | 1 262 | 263 | 264 | 265 | 266 | library\lib\armeabi 267 | 1 268 | 269 | 270 | 271 | 272 | library\lib\mips 273 | 1 274 | 275 | 276 | 277 | 278 | library\lib\armeabi-v7a 279 | 1 280 | 281 | 282 | 283 | 284 | res\drawable 285 | 1 286 | 287 | 288 | 289 | 290 | res\values 291 | 1 292 | 293 | 294 | 295 | 296 | res\drawable 297 | 1 298 | 299 | 300 | 301 | 302 | res\drawable-xxhdpi 303 | 1 304 | 305 | 306 | 307 | 308 | res\drawable-ldpi 309 | 1 310 | 311 | 312 | 313 | 314 | res\drawable-mdpi 315 | 1 316 | 317 | 318 | 319 | 320 | res\drawable-hdpi 321 | 1 322 | 323 | 324 | 325 | 326 | res\drawable-xhdpi 327 | 1 328 | 329 | 330 | 331 | 332 | res\drawable-small 333 | 1 334 | 335 | 336 | 337 | 338 | res\drawable-normal 339 | 1 340 | 341 | 342 | 343 | 344 | res\drawable-large 345 | 1 346 | 347 | 348 | 349 | 350 | res\drawable-xlarge 351 | 1 352 | 353 | 354 | 355 | 356 | 1 357 | 358 | 359 | 1 360 | 361 | 362 | 0 363 | 364 | 365 | 366 | 367 | 1 368 | .framework 369 | 370 | 371 | 0 372 | 373 | 374 | 375 | 376 | 1 377 | .dylib 378 | 379 | 380 | 0 381 | .dll;.bpl 382 | 383 | 384 | 385 | 386 | 1 387 | .dylib 388 | 389 | 390 | 1 391 | .dylib 392 | 393 | 394 | 1 395 | .dylib 396 | 397 | 398 | 1 399 | .dylib 400 | 401 | 402 | 0 403 | .bpl 404 | 405 | 406 | 407 | 408 | 0 409 | 410 | 411 | 0 412 | 413 | 414 | 0 415 | 416 | 417 | 0 418 | 419 | 420 | 0 421 | 422 | 423 | 0 424 | 425 | 426 | 427 | 428 | 1 429 | 430 | 431 | 1 432 | 433 | 434 | 1 435 | 436 | 437 | 438 | 439 | 1 440 | 441 | 442 | 1 443 | 444 | 445 | 1 446 | 447 | 448 | 449 | 450 | 1 451 | 452 | 453 | 1 454 | 455 | 456 | 1 457 | 458 | 459 | 460 | 461 | 1 462 | 463 | 464 | 1 465 | 466 | 467 | 1 468 | 469 | 470 | 471 | 472 | 1 473 | 474 | 475 | 1 476 | 477 | 478 | 1 479 | 480 | 481 | 482 | 483 | 1 484 | 485 | 486 | 1 487 | 488 | 489 | 1 490 | 491 | 492 | 493 | 494 | 1 495 | 496 | 497 | 1 498 | 499 | 500 | 1 501 | 502 | 503 | 504 | 505 | 1 506 | 507 | 508 | 509 | 510 | ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF 511 | 1 512 | 513 | 514 | ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF 515 | 1 516 | 517 | 518 | 519 | 520 | 521 | 522 | 523 | 1 524 | 525 | 526 | 1 527 | 528 | 529 | 1 530 | 531 | 532 | 533 | 534 | 535 | 536 | Contents\Resources 537 | 1 538 | 539 | 540 | 541 | 542 | library\lib\armeabi-v7a 543 | 1 544 | 545 | 546 | 1 547 | 548 | 549 | 1 550 | 551 | 552 | 1 553 | 554 | 555 | 1 556 | 557 | 558 | 1 559 | 560 | 561 | 0 562 | 563 | 564 | 565 | 566 | 1 567 | 568 | 569 | 1 570 | 571 | 572 | 573 | 574 | Assets 575 | 1 576 | 577 | 578 | Assets 579 | 1 580 | 581 | 582 | 583 | 584 | Assets 585 | 1 586 | 587 | 588 | Assets 589 | 1 590 | 591 | 592 | 593 | 594 | 595 | 596 | 597 | 598 | 599 | 600 | 601 | 602 | True 603 | 604 | 605 | 12 606 | 607 | 608 | 609 | 610 | 611 | -------------------------------------------------------------------------------- /platform_WIN/JesFsDemo_cpp_studio.cbproj.local: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 1899.12.30 00:00:00.000.090,=C:\c\cx\Unit1.cpp 5 | 1899.12.30 00:00:00.000.155,=C:\c\cx\Unit1.cpp 6 | 1899.12.30 00:00:00.000.741,=C:\c\cx\Unit1.cpp 7 | 1899.12.30 00:00:00.000.081,=C:\c\cx\Project1PCH1.h 8 | 1899.12.30 00:00:00.000.728,=C:\c\cx\Project1PCH1.h 9 | 1899.12.30 00:00:00.000.144,=C:\c\cx\Project1PCH1.h 10 | 2019.11.27 11:42:35.368,=C:\c\cx\Project1PCH1.h 11 | 2019.11.27 11:42:35.374,=C:\c\cx\File1.c 12 | 2019.11.27 11:43:57.097,C:\c\cx\JesFsDemo\JesFsDemo\platform_WIN\JesFsDemo_cpp_studio.cbproj=C:\c\cx\Project1.cbproj 13 | 2019.11.27 11:45:02.080,=C:\c\cx\JesFsDemo\JesFsDemo\jesfs_hl.c 14 | 2019.11.27 11:45:02.087,=C:\c\cx\JesFsDemo\JesFsDemo\JesFs_main.c 15 | 2019.11.27 11:45:02.094,=C:\c\cx\JesFsDemo\JesFsDemo\jesfs_ml.c 16 | 2019.11.27 11:45:29.110,=C:\c\cx\JesFsDemo\JesFsDemo\jesfs.h 17 | 2019.11.27 11:45:29.116,=C:\c\cx\JesFsDemo\JesFsDemo\jesfs_int.h 18 | 2019.11.27 11:45:29.122,=C:\c\cx\JesFsDemo\JesFsDemo\tb_tools.h 19 | 2019.11.27 11:46:35.072,=C:\c\cx\JesFsDemo\JesFsDemo\platform_WIN\JesFs_ll_pc.c 20 | 2019.11.27 11:46:35.082,=C:\c\cx\JesFsDemo\JesFsDemo\platform_WIN\tb_tools_win.c 21 | 22 | 23 | -------------------------------------------------------------------------------- /platform_WIN/JesFsDemo_cpp_studio.res: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joembedded/JesFs/ebabac8866c69107afa3e4e1fef24a9b6ef647d7/platform_WIN/JesFsDemo_cpp_studio.res -------------------------------------------------------------------------------- /platform_WIN/JesFs_ll_pc.c: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * JesFs_ll_pc.c: Simulation of a LowLevel-Driver with 3 | * - "Embarcadero(R) C++ Builder Community Edition" (for PC) 4 | * - "Microsoft Visual Studio Community 2019" 5 | * 6 | * JesFs - Jo's Embedded Serial File System 7 | * 8 | * This file is a very simple simulation for a serial flash, adapted 9 | * especially to the overlaying driver structure. 10 | * 11 | * (C) 2019 joembedded@gmail.com - www.joembedded.de 12 | * Version: 1.5 / 25.11.2019 13 | * 14 | *******************************************************************************/ 15 | 16 | #ifdef WIN32 // Visual Studio Code defines WIN32 17 | #define _CRT_SECURE_NO_WARNINGS // VS somtimes complains traditional C 18 | #endif 19 | 20 | // ---------------- required for JesFs ---------------------------- 21 | #include 22 | #include 23 | #include 24 | 25 | #include "jesfs.h" 26 | #include "jesfs_int.h" 27 | 28 | 29 | // ---------- local headers ------------------------------------- 30 | #include 31 | #include 32 | //#include // Own is better 33 | #define assert(p) ((p) ? (void)0 : _my_assert(#p, __FILE__, __LINE__)) 34 | 35 | //#define TRACK_SPI // If def write logfile spi_track.txt 36 | 37 | void _my_assert(char *pc, char *pf, int ln){ 38 | printf(")> ",pc, ln); 39 | exit(-1); // Fast Exit 40 | } 41 | 42 | //------------------- LowLevel SPI START ------------------------ 43 | /**************************************************************** 44 | * Select an ID for the simulated Disk 45 | * here ID (0xC228) is MACRONIX_MANU_TYP, 46 | * Density is the last Byte as 2eXX in Bytes (2e19 = 512 kByte) 47 | *****************************************************************/ 48 | #define SIM_DISK_ID ((MACRONIX_MANU_TYP<<8)+0x13) // 512kB 49 | //#define SIM_DISK_ID ((MACRONIX_MANU_TYP<<8)+0x0F) // 32kB 50 | 51 | 52 | // --- Required and simulated SPI-Commands --- 53 | #define CMD_DEEPPOWERDOWN 0xB9 54 | #define CMD_RELEASEDPD 0xAB 55 | #define CMD_RDID 0x9F // Read Identification: Manuf.8 Type.8 Density.8 56 | #define CMD_WRITEENABLE 0x06 57 | #define CMD_STATUSREG 0x05 58 | #define CMD_READDATA 0x03 59 | #define CMD_BULKERASE 0xC7 60 | #define CMD_PAGEWRITE 0x02 61 | #define CMD_SECTOR4K_ERASE 0x20 62 | 63 | typedef struct{ 64 | uint32_t sim_disk_id_set; // Wenn 0; Vorgabe. Sonst: SIM_DISK_DENSITY verwenden 65 | uint32_t sim_disk_id_used; 66 | uint8_t *pmem; 67 | uint32_t memsize; 68 | uint32_t adr_ptr; 69 | uint32_t state; // State-Machine: >=128: RD follows 70 | uint8_t select; // Monitors CS 71 | uint8_t powerdown; // -NotUsedInSimulation- 72 | uint8_t status_reg; // Status-Reg Bit1:WenableLatchBit Bit0:WriteInPrograssBit 73 | FILE *trf; // trackerFile 74 | } SIM_FLASH; 75 | 76 | SIM_FLASH sim_flash; 77 | 78 | // INIT Hardware SPI 79 | int16_t sflash_spi_init(void){ 80 | uint32_t i; 81 | // Remember the ID 82 | if(!sim_flash.sim_disk_id_set) sim_flash.sim_disk_id_set=SIM_DISK_ID; 83 | 84 | // If called again: generate new Disk 85 | if(sim_flash.sim_disk_id_set != sim_flash.sim_disk_id_used){ 86 | if(sim_flash.pmem){ 87 | free(sim_flash.pmem); // Freigeben 88 | sim_flash.pmem=NULL; 89 | } 90 | } 91 | 92 | sim_flash.sim_disk_id_used=sim_flash.sim_disk_id_set; 93 | sim_flash.memsize=(1<<(sim_flash.sim_disk_id_used&255)); 94 | assert(sim_flash.memsize>=8192 && sim_flash.memsize<=16777216); 95 | if(sim_flash.pmem==NULL){ 96 | sim_flash.pmem=malloc(sim_flash.memsize); 97 | assert(sim_flash.pmem); 98 | 99 | // Fill Disk with mit 'trash' 100 | for(i=0;i=128); 138 | switch(sim_flash.state){ 139 | case 128: // Read ManuTypDen 140 | assert(len==3); 141 | // Nimm Macronix zum simulieren 142 | buf[0]=(uint8_t)(MACRONIX_MANU_TYP>>8); // Manu 143 | buf[1]=(uint8_t)(MACRONIX_MANU_TYP); // Typ 144 | buf[2]=(uint8_t)(sim_flash.sim_disk_id_used); // Density 145 | sim_flash.state=0; 146 | break; 147 | case 129: // Read Status - As often as you want 148 | assert(len==1); 149 | buf[0]=sim_flash.status_reg; 150 | sim_flash.status_reg=0; // No Wait.. 151 | break; 152 | case 130: // ReadData 153 | adr=sim_flash.adr_ptr; 154 | for(i=0;i<(uint32_t)len;i++){ 155 | assert(adr", sim_flash.state,len); 163 | assert(0); 164 | } 165 | } 166 | 167 | 168 | /* Because of SPI page-Size (def. 256 Bytes) len is no problem. */ 169 | void sflash_spi_write(const uint8_t *buf, uint16_t len){ 170 | uint32_t adr; 171 | uint32_t mx; 172 | uint32_t i; 173 | uint8_t o,w; 174 | 175 | /* 176 | printf("\n"); 179 | */ 180 | 181 | assert(sim_flash.select==1); 182 | assert(sim_flash.state<128); 183 | if(!sim_flash.state){ 184 | 185 | switch(*buf){ 186 | case CMD_DEEPPOWERDOWN: 187 | assert(len==1); 188 | sim_flash.powerdown=1; 189 | break; 190 | case CMD_RELEASEDPD: 191 | assert(len==1); 192 | sim_flash.powerdown=0; 193 | break; 194 | case CMD_RDID: 195 | assert(len==1); 196 | sim_flash.state=128; // -> ID follows 197 | break; 198 | case CMD_WRITEENABLE: 199 | assert(len==1); 200 | sim_flash.status_reg|=2; 201 | break; 202 | case CMD_STATUSREG: 203 | assert(len==1); 204 | sim_flash.state=129; // -> Status Rd 205 | break; 206 | 207 | case CMD_READDATA: 208 | assert(len==4); 209 | adr=(buf[1]<<16)+(buf[2]<<8)+buf[3]; 210 | sim_flash.adr_ptr=adr; 211 | sim_flash.state=130; // -> Lesen 212 | break; 213 | 214 | case CMD_PAGEWRITE: 215 | assert(len==4); // MY Pagewrite: 2 Transfers : ADR DATA 216 | adr=(buf[1]<<16)+(buf[2]<<8)+buf[3]; 217 | sim_flash.adr_ptr=adr; 218 | sim_flash.state=1; // -> Write allowed 219 | break; 220 | 221 | case CMD_SECTOR4K_ERASE: 222 | assert(len==4); // MY Pagewrite: 2 Transfers : ADR DATA 223 | adr=(buf[1]<<16)+(buf[2]<<8)+buf[3]; 224 | assert(adr\n"); 243 | assert(0); 244 | return ; 245 | } 246 | }else{ 247 | switch(sim_flash.state){ 248 | case 1: // 2.nd Block of Write Cmd 249 | adr=sim_flash.adr_ptr; 250 | mx=256-(adr&255); // Maximum allowed pagewrite 251 | assert(len<=(uint16_t)mx); 252 | for(i=0;i<(uint32_t)len;i++){ 253 | assert(adr\n"); 267 | assert(0); 268 | return ; 269 | } 270 | } 271 | } 272 | 273 | //------------------- LowLevel SPI Fertig ------------------------ 274 | 275 | //------------------- Persistence-Funktion for the Disk --------- 276 | /* Returns: 277 | * 0: OK 278 | * -200: Filename too short 279 | * -201: OpenFileError Read 280 | * -202: Write Error 281 | * -203: OpenFileError Write 282 | * -204: Read Error 283 | * -205: File larger than expected 284 | * -206: No Disk 285 | */ 286 | 287 | // Read virtual Disk form File 288 | int16_t ll_write_vdisk(char *fname){ 289 | FILE *outf; 290 | int wlen; 291 | 292 | if(strlen(fname)<1) return -200; 293 | if(!sim_flash.pmem) return -206; // No Disk 294 | outf=fopen(fname,"wb"); 295 | if(!outf) return -201; 296 | wlen=fwrite(sim_flash.pmem,1,sim_flash.memsize,outf); 297 | fclose(outf); 298 | if(wlen!=(int)sim_flash.memsize) return -202; 299 | return 0; 300 | } 301 | 302 | // Write Virtual Disk to a File. No Disk-ID added. Byte 0 in File is 0 in Flash 303 | int16_t ll_read_vdisk(char *fname){ 304 | FILE *inf; 305 | int rlen,rlen2,dummy; 306 | if(strlen(fname)<1) return -200; 307 | if(!sim_flash.pmem) return -206; // No Disk 308 | inf=fopen(fname,"rb"); 309 | if(!inf) return -203; 310 | rlen=fread(sim_flash.pmem,1,sim_flash.memsize,inf); 311 | rlen2=fread(&dummy,1,1,inf); 312 | fclose(inf); 313 | if(rlen2>0) return -205; 314 | if(rlen!=(int)sim_flash.memsize) return -204; 315 | return 0; 316 | } 317 | 318 | // Set ID for virtial Disk 319 | int16_t ll_setid_vdisk(uint32_t id){ 320 | assert((id&255)>=0xD && (id&255)<=0x18); // 8kb-16MB OK 321 | if(id<256) id|=(MACRONIX_MANU_TYP<<8); 322 | sim_flash.sim_disk_id_set=id; 323 | return 0; 324 | } 325 | 326 | // Get Info for virtual Disk 327 | int16_t ll_get_info_vdisk(uint32_t *pid_used, uint8_t **pmem, uint32_t *psize){ 328 | if(!sim_flash.pmem) return -206; // No Disk 329 | if(pid_used) *pid_used=sim_flash.sim_disk_id_used; 330 | if(pmem) *pmem=sim_flash.pmem; 331 | if(psize) *psize=sim_flash.memsize; 332 | return 0; 333 | } 334 | 335 | //------------------- Fertig ------------------------ 336 | 337 | -------------------------------------------------------------------------------- /platform_WIN/ReadMe.txt: -------------------------------------------------------------------------------- 1 | # ReadMe.txt # 2 | 3 | Please read the JesFs.pdf how to build the JesFs Demo for Windows PCs 4 | -------------------------------------------------------------------------------- /platform_WIN/Win32/Debug/JesFsDemo_cpp_studio.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joembedded/JesFs/ebabac8866c69107afa3e4e1fef24a9b6ef647d7/platform_WIN/Win32/Debug/JesFsDemo_cpp_studio.exe -------------------------------------------------------------------------------- /platform_WIN/tb_tools_win.c: -------------------------------------------------------------------------------- 1 | /********************************************************************* 2 | * tb_tools_win.c - Toolbox for UART, Unix-Time, .. 3 | * 4 | * For Platform __WIN32__ / WIN32 5 | * - "Embarcadero(R) C++ Builder Community Edition" (for PC) 6 | * - "Microsoft Visual Studio Community 2019" 7 | * 8 | * 2019 (C) joembedded.de 9 | * Version: 10 | * 1.0 / 25.11.2019 11 | * 1.02 / 09.12.2019 return empty string on timeout 12 | *********************************************************************/ 13 | 14 | #ifdef WIN32 // Visual Studio Code defines WIN32 15 | #define _CRT_SECURE_NO_WARNINGS // VS somtimes complains traditional C 16 | #endif 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include // for var_args 24 | #include 25 | #include // kbhit(), getc() 26 | #include 27 | #include // Sleep() 28 | 29 | #ifdef WIN32 // Visual Studio Code defines WIN32 30 | #define __WIN32__ 31 | #define getch _getch // VS uses POSIX names 32 | #define kbhit _kbhit 33 | #endif 34 | 35 | #ifndef __WIN32__ // Embarcadero defines __WIN32__ 36 | #error "Toolbox for __WIN32__ / WIN32" 37 | #endif 38 | 39 | // ---- local defines -------------- 40 | 41 | // ---------- locals uart -------------------- 42 | 43 | // ---- locals Watcdog ---- 44 | 45 | 46 | // --- locals timestamp ---- 47 | static bool tb_init_flag=false; 48 | 49 | // -------- init Toolbox ----------------- 50 | void tb_init(void){ 51 | tb_init_flag=true; 52 | 53 | } 54 | 55 | // ------ uninit all -------------------- 56 | void tb_uninit(void){ 57 | // ToDo... 58 | 59 | tb_init_flag=false; 60 | } 61 | 62 | // ------ board support pakage ----- 63 | // No LEDs on PC 64 | void tb_board_led_on(uint8_t idx){ 65 | } 66 | void tb_board_led_off(uint8_t idx){ 67 | } 68 | void tb_board_led_invert(uint8_t idx){ 69 | } 70 | 71 | 72 | // ------- System Reset ------------- 73 | void tb_system_reset(void){ 74 | exit(-1); 75 | } 76 | 77 | 78 | // ------Watchdog, triggered befor reset ----- 79 | static void tb_wdt_event_handler(void){ 80 | // ToDo... 81 | for(;;); // Wait2Die 82 | } 83 | 84 | // ---- enable the watchdog only once! ----------- 85 | // No Watchdog on PC 86 | void tb_watchdog_init(void){ 87 | } 88 | 89 | // ---- Feed the watchdog, No function if WD not initialised ------------ 90 | // feed_ticks currently ignored, but >0 91 | void tb_watchdog_feed(uint32_t feed_ticks){ 92 | } 93 | 94 | 95 | // --- A low Power delay --- 96 | void tb_delay_ms(uint32_t msec){ 97 | Sleep(msec); 98 | } 99 | 100 | // ---- Unix-Timer. Must be called periodically to work, but at least twice per RTC-overflow (512..xx secs) --- 101 | uint32_t tb_time_get(void){ 102 | return (uint32_t)time(NULL); 103 | } 104 | 105 | // Set time, regarding the timer 106 | void tb_time_set(uint32_t new_secs){ 107 | printf("__WIN32__: tb_time_set() ignored\n"); 108 | } 109 | 110 | // ----- fine clocl ticks functions --------------------- 111 | // Use the difference of 2 timestamps to calclualte msec Time 112 | uint32_t tb_get_ticks(void){ 113 | return GetTickCount(); // msec on PC 114 | } 115 | 116 | uint32_t tb_deltaticks_to_ms(uint32_t t0, uint32_t t1){ 117 | uint32_t delta_ticks = t1-t0; 118 | return delta_ticks; 119 | } 120 | 121 | 122 | 123 | // tb_printf(): printf() to toolbox uart. Wait if busy 124 | void tb_printf(char* fmt, ...){ 125 | va_list argptr; 126 | va_start(argptr, fmt); 127 | 128 | vprintf( fmt, argptr); // vsn: limit! 129 | va_end(argptr); 130 | } 131 | 132 | // tb_putc(): Wait if not ready 133 | void tb_putc(char c){ 134 | tb_printf("%c",c); 135 | } 136 | 137 | // ---- Input functions 0: Nothing available (tb_kbhit is faster than tb_getc) --------- 138 | int16_t tb_kbhit(void){ 139 | int16_t res; 140 | res=kbhit(); 141 | return res; 142 | } 143 | 144 | // ---- get 1 char (0..255) (or -1 if nothing available) 145 | int16_t tb_getc(void){ 146 | int c; 147 | if(!kbhit()) return -1; 148 | c=getch(); 149 | return (int16_t)c; 150 | } 151 | 152 | // Get String with Timout (if >0) in msec of infinite (Timout 0), No echo (max_uart_in without trailing \0!) 153 | int16_t tb_gets(char* input, int16_t max_uart_in, uint16_t max_wait_ms, uint8_t echo){ 154 | int16_t idx=0; 155 | int16_t res; 156 | char c; 157 | max_uart_in--; // Reserve 1 Byte for End-0 158 | for(;;){ 159 | res=tb_kbhit(); 160 | if(res>0){ 161 | res=tb_getc(); 162 | if(res<0) break; 163 | c=(char)res; 164 | if(c=='\n' || c=='\r') { 165 | break; // NL CR or whatever (no Echo for NL CR) 166 | }else if(c==8){ // Backspace 167 | if(idx>0){ 168 | idx--; 169 | if(echo){ 170 | tb_putc(8); 171 | tb_putc(' '); 172 | tb_putc(8); 173 | } 174 | } 175 | }else if(c>=' ' && c<127 && idx 41 | #include 42 | #include 43 | 44 | #include "jesfs.h" 45 | #include "jesfs_int.h" 46 | 47 | /* Driver Header files */ 48 | #include "nrfx_spim.h" 49 | #include "app_util_platform.h" 50 | #include "nrf_gpio.h" 51 | #include "nrf_delay.h" 52 | // #include "boards.h" // Pin names 53 | #include "app_error.h" 54 | 55 | #ifdef NRF52840_XXAA // 52840: SPI-Flash on Board 56 | 57 | /* Driver Defines und Locals */ 58 | // Use DK PC10056 on board FLASH - Pins are fixed 59 | // Unused PINS: BSP_QSPI_IO2_PIN (22) and BSP_QSPI_IO3_PIN (23) 60 | #define FPIN_SCK_PIN NRF_GPIO_PIN_MAP(0,19) // 19 Clock (BSP_QSPI_SCK_PIN) 61 | #define FPIN_MOSI_PIN NRF_GPIO_PIN_MAP(0,20) // 20 SI/DIO0 (BSP_QSPI_IO0_PIN) 62 | #define FPIN_MISO_PIN NRF_GPIO_PIN_MAP(0,21) //21 SO/DIO1 (BSP_QSPI_IO1_PIN) 63 | #define FPIN_SS_PIN NRF_GPIO_PIN_MAP(0,17) //17 Select, (extern, BSP_QSPI_CSN_PIN) 64 | // Enable or define in Project: #define FPIN_LED BSP_LED_0 // 13 (optional, used if defined) 65 | 66 | #else // 52832 - I/Os flexible, but this makes sense 67 | // Pins mapped to optimal positions for ANNA-B112 module. 68 | #define SPI_CHUNKS 128 // If defined: SPI in smaller Chunks (nRF52832 requires <=255 Bytes) 69 | #define FPIN_SCK_PIN NRF_GPIO_PIN_MAP(0,15) // Clock 70 | #define FPIN_MOSI_PIN NRF_GPIO_PIN_MAP(0,16) // SI/DIO0 71 | #define FPIN_MISO_PIN NRF_GPIO_PIN_MAP(0,18) // SO/DIO1 72 | #define FPIN_SS_PIN NRF_GPIO_PIN_MAP(0,14) // Select, (extern) 73 | //#define FPIN_LED NRF_GPIO_PIN_MAP(0,27) // (optional, used if defined) 74 | 75 | #endif 76 | 77 | 78 | 79 | #ifdef NRF52840_XXAA 80 | #define SPI_INSTANCE 3 // M /**< SPI instance index. */ 81 | #else 82 | #define SPI_INSTANCE 2 // Assign highest available SPIM instabce for Driver.. 83 | #endif 84 | 85 | static const nrfx_spim_t spi = NRFX_SPIM_INSTANCE(SPI_INSTANCE); /**< SPI instance. */ 86 | static bool spi_init_flag=false; 87 | static nrfx_spim_config_t spi_config = NRFX_SPIM_DEFAULT_CONFIG; 88 | 89 | //------------------- LowLevel SPI START ------------------------ 90 | // INIT Hardware SPI 91 | int16_t sflash_spi_init(void){ 92 | if(spi_init_flag==true) return 0; // Already init 93 | 94 | //spi_config.frequency = NRF_SPIM_FREQ_1M; // for tests, Default: 4M 95 | #ifdef NRF52840_XXAA // 52840: max. 32MHz 96 | spi_config.frequency = NRF_SPIM_FREQ_16M; 97 | //spi_config.frequency = NRF_SPIM_FREQ_32M; // Maybe too fast with Softdevice in || (V1.6) 98 | #else // older/NRF52832: max 8MHz 99 | spi_config.frequency = NRF_SPIM_FREQ_8M; // for tests, Default: 4M 100 | #endif 101 | 102 | spi_config.miso_pin = FPIN_MISO_PIN; 103 | spi_config.mosi_pin = FPIN_MOSI_PIN; 104 | spi_config.sck_pin = FPIN_SCK_PIN; 105 | APP_ERROR_CHECK(nrfx_spim_init(&spi, &spi_config, NULL, NULL)); // Use Blocking transfer 106 | 107 | nrf_gpio_cfg_output(FPIN_SS_PIN); // We use Software CS 108 | nrf_gpio_pin_set(FPIN_SS_PIN); // De-Select Peripheral 109 | // Better use strong drivers for high Speed 110 | nrf_gpio_cfg(FPIN_SCK_PIN,NRF_GPIO_PIN_DIR_OUTPUT, NRF_GPIO_PIN_INPUT_CONNECT, NRF_GPIO_PIN_NOPULL, 111 | NRF_GPIO_PIN_H0H1, NRF_GPIO_PIN_NOSENSE); 112 | 113 | nrf_gpio_cfg(FPIN_MOSI_PIN, NRF_GPIO_PIN_DIR_OUTPUT, NRF_GPIO_PIN_INPUT_DISCONNECT, 114 | NRF_GPIO_PIN_NOPULL, NRF_GPIO_PIN_H0H1, NRF_GPIO_PIN_NOSENSE); 115 | #ifdef FPIN_LED 116 | nrf_gpio_cfg_output(FPIN_LED); // Might be already init from bsp-drivers 117 | #endif 118 | spi_init_flag=true; 119 | nrf_delay_us(10); 120 | return 0; 121 | } 122 | 123 | void sflash_spi_close(void){ 124 | if(spi_init_flag==false) return; // Already uninit 125 | nrfx_spim_uninit(&spi); 126 | spi_init_flag=false; 127 | } 128 | 129 | void sflash_wait_usec(uint32_t usec){ 130 | #ifdef FPIN_LED 131 | nrf_gpio_pin_toggle(FPIN_LED); // Hear Me Working! Led Toggle 132 | #endif 133 | nrf_delay_us(usec); 134 | } 135 | 136 | void sflash_select(void){ 137 | // nrf_delay_us(1); // (?) from Community: SPI may need a small delay to recover (?) 138 | #ifdef FPIN_LED 139 | nrf_gpio_pin_clear(FPIN_LED); // Hear Me Working! Led ON (0 on PCA10056) 140 | #endif 141 | nrf_gpio_pin_clear(FPIN_SS_PIN); // Select Peripheral 142 | } 143 | void sflash_deselect(void){ 144 | #ifdef FPIN_LED 145 | nrf_gpio_pin_set(FPIN_LED); // Hear Me Working! Led Off (1 on PCA10056) 146 | #endif 147 | nrf_gpio_pin_set(FPIN_SS_PIN); // De-Select Peripheral 148 | } 149 | 150 | void sflash_spi_read(uint8_t *buf, uint16_t len){ 151 | #ifdef SPI_CHUNKS 152 | uint16_t rlen; 153 | while(len){ 154 | rlen=len; 155 | if(rlen>SPI_CHUNKS) rlen=SPI_CHUNKS; 156 | nrfx_spim_xfer_desc_t xfer_desc = NRFX_SPIM_XFER_TRX(NULL, 0, buf, rlen); 157 | APP_ERROR_CHECK(nrfx_spim_xfer(&spi, &xfer_desc, 0)); 158 | len-=rlen; 159 | buf+=rlen; 160 | } 161 | #else 162 | nrfx_spim_xfer_desc_t xfer_desc = NRFX_SPIM_XFER_TRX(NULL, 0, buf, len); 163 | APP_ERROR_CHECK(nrfx_spim_xfer(&spi, &xfer_desc, 0)); 164 | #endif 165 | } 166 | 167 | /* Because of SPI page-Size (def. 256 Bytes) len is no problem. */ 168 | void sflash_spi_write(const uint8_t *buf, uint16_t len){ 169 | #ifdef SPI_CHUNKS 170 | uint16_t wlen; 171 | while(len){ 172 | wlen=len; 173 | if(wlen>SPI_CHUNKS) wlen=SPI_CHUNKS; 174 | nrfx_spim_xfer_desc_t xfer_desc = NRFX_SPIM_XFER_TRX(buf, wlen, NULL, 0); 175 | APP_ERROR_CHECK(nrfx_spim_xfer(&spi, &xfer_desc, 0)); 176 | len-=wlen; 177 | buf+=wlen; 178 | } 179 | #else 180 | nrfx_spim_xfer_desc_t xfer_desc = NRFX_SPIM_XFER_TRX(buf, len, NULL, 0); 181 | APP_ERROR_CHECK(nrfx_spim_xfer(&spi, &xfer_desc, 0)); 182 | #endif 183 | } 184 | //------------------- LowLevel SPI End ------------------------ 185 | -------------------------------------------------------------------------------- /platform_nRF52/ReadMe.txt: -------------------------------------------------------------------------------- 1 | # ReadMe.txt # 2 | 3 | Please read the JesFs.pdf how to build the JesFs Demo for nRF52 CPUs 4 | -------------------------------------------------------------------------------- /platform_nRF52/nrf52832/ses/flash_placement.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /platform_nRF52/nrf52840/ses/flash_placement.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /platform_nRF52/tb_pins_nrf52.h: -------------------------------------------------------------------------------- 1 | /*************************************************************************************************************** 2 | * tb_pins_nrf52.c - Pin definitins for my used HW platforms 3 | * 4 | * For platform nRF52 5 | * 6 | * (C) joembedded.de 7 | ***************************************************************************************************************/ 8 | 9 | 10 | //-------- NRF52840-CPUS ------------- 11 | #ifdef NINA_B3_EVK 12 | //#warning "INFO: TB_TOOLS for NINA_B3_EVK" // Just as Info 13 | #ifndef NRF52840_XXAA 14 | #error "WRONG CPU" 15 | #endif 16 | #define TB_LED0 NRF_GPIO_PIN_MAP(0,13) // Active LOW 17 | #define TB_BUT0 NRF_GPIO_PIN_MAP(0,25) // Button and GREEN Led .. 18 | #define TB_RX_PIN NRF_GPIO_PIN_MAP(0,29) 19 | #define TB_TX_PIN NRF_GPIO_PIN_MAP(1,13) 20 | #endif 21 | 22 | #if defined(NINA_B3_LTX) || defined(NINA_B3_EPA) || defined(BT840_BB) || defined(LTX_INTENT) || defined(LTX_MN) 23 | //#warning "INFO: TB_TOOLS for NINA_B3_LTX/_EPA/BT840_BB" // Just as Info 24 | #ifndef NRF52840_XXAA 25 | #error "WRONG CPU" 26 | #endif 27 | #define TB_LED0 NRF_GPIO_PIN_MAP(0,13) // Actice LOW 28 | //#define TB_BUT0 NRF_GPIO_PIN_MAP(xx) // No Button 29 | #define TB_RX_PIN NRF_GPIO_PIN_MAP(0,15) 30 | #define TB_TX_PIN NRF_GPIO_PIN_MAP(0,14) 31 | #endif 32 | 33 | #ifdef XM126_EVK 34 | //#warning "INFO: TB_TOOLS for XM126_EVK (ACCONEER)" // Just as Info 35 | #ifndef NRF52840_XXAA 36 | #error "WRONG CPU" 37 | #endif 38 | #define TB_LED0 NRF_GPIO_PIN_MAP(0,4) // Active LOW 39 | #define TB_BUT0 NRF_GPIO_PIN_MAP(0,25) // (DFU) Button 40 | #define TB_RX_PIN NRF_GPIO_PIN_MAP(0,6) 41 | #define TB_TX_PIN NRF_GPIO_PIN_MAP(0,16) 42 | #endif 43 | 44 | 45 | //-------- NRF52832-CPUS ------------- 46 | #ifdef ANNA_B112_EVK 47 | //#warning "INFO: TB_TOOLS for NINA_B112_EVK" // Just as Info 48 | #ifndef NRF52832_XXAA 49 | #error "WRONG CPU" 50 | #endif 51 | #define TB_BUT0 NRF_GPIO_PIN_MAP(0,25) // Button and GREEN Led .. 52 | #define TB_LED0 NRF_GPIO_PIN_MAP(0,27) // Active LOW 53 | #define TB_RX_PIN NRF_GPIO_PIN_MAP(0,2) 54 | #define TB_TX_PIN NRF_GPIO_PIN_MAP(0,3) 55 | #endif 56 | 57 | #ifdef YJ_NRF52832 // YJ_16048 from HolyIot (NO CE/FCC uncertified Low-Cost module) 58 | //#warning "INFO: TB_TOOLS for YJ_16048_NRF52832 (NO CE/FCC)" // Just as Info 59 | #ifndef NRF52832_XXAA 60 | #error "WRONG CPU" 61 | #endif 62 | #define TB_LED0 NRF_GPIO_PIN_MAP(0,19) // Active LOW 63 | //#define TB_BUT0 NRF_GPIO_PIN_MAP(xx) // No Button 64 | #define TB_RX_PIN NRF_GPIO_PIN_MAP(0,2) 65 | #define TB_TX_PIN NRF_GPIO_PIN_MAP(0,3) 66 | #endif 67 | 68 | #ifdef EBYTE_E73 // Easy-2-Solder CE certified Module from EBYTE (!! No DC/DC !!) 69 | //#warning "INFO: TB_TOOLS for EBYTE_E73" // Just as Info 70 | #ifndef NRF52832_XXAA 71 | #error "WRONG CPU" 72 | #endif 73 | #define TB_LED0 NRF_GPIO_PIN_MAP(0,13) // Active LOW 74 | //#define TB_BUT0 NRF_GPIO_PIN_MAP(xx) // No Button 75 | #define TB_RX_PIN NRF_GPIO_PIN_MAP(0,2) 76 | #define TB_TX_PIN NRF_GPIO_PIN_MAP(0,3) 77 | #endif 78 | 79 | #ifdef ANNA_SDI12 // ANNA-SDI12 Sensor platform with ANNA-B112 80 | //#warning "INFO: TB_TOOLS for ANNA_B112" // Just as Info 81 | #ifndef NRF52832_XXAA 82 | #error "WRONG CPU" 83 | #endif 84 | #define TB_LED0 NRF_GPIO_PIN_MAP(0,19) // Active LOW 85 | //#define TB_BUT0 NRF_GPIO_PIN_MAP(xx) // No Button 86 | #define TB_RX_PIN NRF_GPIO_PIN_MAP(0,2) 87 | #define TB_TX_PIN NRF_GPIO_PIN_MAP(0,3) 88 | #endif 89 | 90 | //---- Check Platform 91 | #if !defined(TB_RX_PIN) || !defined(TB_TX_PIN) 92 | #error "No Platform set: can not define I/O Pins" 93 | #endif 94 | 95 | //*** -------------------------------------------------------------------------------- /platform_nRF52/tb_tools_nrf52.c: -------------------------------------------------------------------------------- 1 | /*************************************************************************************************************** 2 | * tb_tools_nrf52.c - Toolbox for UART, Unix-Time, .. 3 | * 4 | * For platform nRF52 5 | * 6 | * (C) joembedded.de 7 | * 8 | * Versions: 9 | * 1.0: 25.11.2019 10 | * 1.1: 06.12.2019 added support for Low Power uninit, deep sleep current with RTC wakeup <= 2.7uA on nRF52840 11 | * 1.1b: 09.12.2019 return empty string on timeout 12 | * 1.2: 09.12.2019 changed init to presence of softdevice 13 | * 1.3: 23.12.2019 USE_TBIO for LED (removed in 2.50) 14 | * 1.4: 05.01.2020 tb_isxxx_init() 15 | * 1.5: 06.01.2020 Button added 16 | * 1.5b: 09.01.2020 tb_watchdog_init return type 17 | * 1.6: 19.01.2020 WDT optimised and GUARD-functions and Framing Errors 18 | * 1.7: 25.02.2020 Added Defines for u-Blox NINA-B3 19 | * 2.0: 06.09.2020 Changed UART Driver to APP_UART for Multi-Use 20 | * 2.01: 08.09.2020 Fixed Error in SDK17 (see tb_tools_nrf52.c-> 'SDK17') 21 | * 2.02: 23.09.2020 Adapted to SDK17.0.2 (still Problem in 'nrf_drv_clock.c' -> search in this file 'SDK17') 22 | * 2.11: 16.05.2021 removed 'board.h', small changes in PIN-Names 23 | * 2.50: 02.07.2021 changed Platform PIN Setup 24 | * 2.51: 10.07.2021 added 'tb_pins_nrf52.h' 25 | * 2.54: 06.10.2021 added 'tb_get_runtime()' and 'tb_runtime2time()' 26 | * 2.55: 06.10.2021 INFO: SDK17.1.0: There is still an Error on nrf_drv_clk.c ( -> search in this file 'SDK17') 27 | * 2.56: 14.11.2021 added 'tb_putsl(char* pc)' 28 | * 2.27: 10.11.2022 'tb_runtime2time()': save time to non-init-RAM, see comment 29 | * 2.28: 27.11.2022 added 'tb_time2runtime()' 30 | * 2.29: 20.03.2025 added '_tb_default_uart_flag' 31 | ***************************************************************************************************************/ 32 | 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include // for var_args 39 | 40 | #include "nrf.h" 41 | #include "nrf_drv_clock.h" 42 | #include "nrf_gpio.h" 43 | #include "nrf_delay.h" 44 | #include "nrf_log.h" 45 | #include "nrf_log_ctrl.h" 46 | #include "nrf_drv_power.h" 47 | 48 | #include "app_timer.h" // uses RTC1 49 | 50 | #include "nrf_drv_wdt.h" 51 | 52 | #include "app_uart.h" // uses Driver Instanz from sdk_config.h (1 on 52840, 0 on 52832) 53 | #include "app_error.h" 54 | #include "app_util.h" 55 | 56 | #include "tb_tools.h" 57 | 58 | #if !defined(NRF52) && !defined(PLATFORM_NRF52) 59 | #error "Define Platform in Project!" 60 | #endif 61 | 62 | 63 | #if defined (UART_PRESENT) 64 | #include "nrf_uart.h" 65 | #endif 66 | #if defined (UARTE_PRESENT) 67 | #include "nrf_uarte.h" 68 | #endif 69 | 70 | // ------ Custom IO Setup - Pin Definitions ------------ 71 | #include "tb_pins_nrf52.h" 72 | 73 | /******* SES has a default section for Non-Volatile RAM ***********/ 74 | /* _tb_novo is valid if _tb_novo[0]==RAM_MAGIC and _tb_novo[1] = ~_tb_novo[2]; 75 | * _tb_novo[1] holds the RTC, _tb_novo[3] the GUARD-Value 76 | * _tb_novo[4,5,6,7 frei] (4,5 for Energy-Management) 77 | */ 78 | 79 | #define RAM_MAGIC (0xBADC0FFEUL) 80 | uint32_t _tb_novo[8] __attribute__ ((section(".non_init"))); 81 | uint32_t _tb_bootcode_backup; // Holds initial Bootcode 82 | 83 | // ---- local defines -------------- 84 | 85 | // ---------- locals uart -------------------- 86 | #define UART_TX_BUF_SIZE 256 /* Also as default buffers for UART */ 87 | #define UART_RX_BUF_SIZE 256 /* Also as default buffers for UART */ 88 | 89 | static uint8_t _tb_app_uart_def_rx_buf[UART_RX_BUF_SIZE]; 90 | static uint8_t _tb_app_uart_def_tx_buf[UART_TX_BUF_SIZE]; 91 | 92 | static const app_uart_comm_params_t _tb_app_uart_def_comm_params = { 93 | TB_RX_PIN, 94 | TB_TX_PIN, 95 | UART_PIN_DISCONNECTED /*RTS_PIN_NUMBER*/, 96 | UART_PIN_DISCONNECTED /*CTS_PIN_NUMBER*/, 97 | /*APP_UART_FLOW_CONTROL_ENABLED */ APP_UART_FLOW_CONTROL_DISABLED, 98 | false, // Not Use Parity 99 | #if defined (UARTE_PRESENT) 100 | NRF_UARTE_BAUDRATE_115200 101 | #else 102 | NRF_UART_BAUDRATE_115200 103 | #endif 104 | }; 105 | static app_uart_buffers_t _tb_app_uart_buffers; 106 | static int32_t _tb_app_timout_ms; 107 | 108 | static uint8_t _tb_app_uart_errorcode; // 1 res. for data, 16: Fifo OVF, ... 109 | static int16_t _tb_app_uart_peekchar; // -1: nothing or 0..255 110 | static bool _tb_uart_init_flag=false; 111 | static bool _tb_default_uart_flag=false; // if true: tb_tools_uart, false: uart redirected by user 112 | 113 | #define TB_SIZE_LINE_OUT 120 // 1 terminal line working buffer (opt. long filenames to print) 114 | static char _tb_app_uart_line_out[TB_SIZE_LINE_OUT]; 115 | 116 | 117 | #if !APP_TIMER_KEEPS_RTC_ACTIVE 118 | #error "Need APP_TIMER_KEEPS_RTC_ACTIVE enabled" 119 | #endif 120 | 121 | // ---- locals Watcdog ---- 122 | static nrf_drv_wdt_channel_id tb_wd_m_channel_id; 123 | static bool tb_wdt_enabled=false; 124 | 125 | 126 | // --- locals timestamp ---- 127 | static uint32_t old_rtc_secs=0; // counts 0...511, Sec-fraction of RTC 128 | static uint32_t cnt_secs=0; // To compare 129 | static uint32_t ux_run_delta=0; // Difference Runtime to Unixtime 130 | 131 | static bool tb_basic_init_flag=false; // Always ON, only init once 132 | 133 | //----------- UART helpers ------------ 134 | static void _tb_app_uart_error_handle(app_uart_evt_t * p_event){ 135 | /* Required, but Dummy is OK too, BREAK gibt 8+4, also ERR 28.d -> 0001 1100 */ 136 | if (p_event->evt_type == APP_UART_COMMUNICATION_ERROR){ 137 | // ref. NRF52840 Datasheeet: Bits: OVERRUN:1 PARITY:2 FRAMING:4: BREAK:8 138 | // APP_ERROR_HANDLER(p_event->data.error_communication); 139 | _tb_app_uart_errorcode = 16+(p_event->data.error_communication&0xF); 140 | }else if (p_event->evt_type == APP_UART_FIFO_ERROR){ 141 | // APP_ERROR_HANDLER(p_event->data.error_code); 142 | _tb_app_uart_errorcode = 2; // 2: Comm Error 143 | } 144 | } 145 | 146 | // tb_putc(): Wait if not ready. With Timout from init 147 | int16_t tb_putc(char c){ 148 | int32_t h=_tb_app_timout_ms; 149 | if(_tb_uart_init_flag==false) return -1; // Not init... 150 | 151 | for(;;){ 152 | if(app_uart_put(c) != NRF_ERROR_NO_MEM) return 0; // NRF_ERROR_NO_MEM (4) -> No ERROR, just wait. 153 | if(!(h--)) return -2; 154 | tb_delay_ms(1); 155 | } 156 | } 157 | 158 | // ---- Test: return 0:Nothing available, -2:UART OK, but not INIT, -1:ERROR, 1:Char available 159 | int16_t tb_kbhit(void){ 160 | uint8_t cr; 161 | if(_tb_uart_init_flag==false) { 162 | if(nrf_gpio_pin_read(TB_RX_PIN)) return -2; // UART RX Level OK, but not init 163 | else return 0; // Not init = nothing 164 | } 165 | if(_tb_app_uart_errorcode) return -1; // Error 166 | if(app_uart_get(&cr) == NRF_SUCCESS){ // nothing: NRF_ERROR_NOT_FOUND 167 | _tb_app_uart_peekchar=(int16_t)cr; 168 | return 1; // Ready 169 | } 170 | return 0; // nothing 171 | } 172 | // ---- get 1 char (0..255) (or -1 if nothing available, or < -1 on Framing Errors) 173 | // Framing Errors (-2...-xx) see _tb_app_uart_error_handle() 174 | int16_t tb_getc(void){ 175 | uint8_t cr; 176 | int16_t ret; 177 | if(_tb_uart_init_flag==false) return -1; // Not init... 178 | if(_tb_app_uart_errorcode){ 179 | cr=_tb_app_uart_errorcode; // Error: Report one time 180 | _tb_app_uart_errorcode=0; 181 | return -(int16_t)cr; // -2.. 182 | }else if(_tb_app_uart_peekchar>=0){ 183 | ret = _tb_app_uart_peekchar; 184 | _tb_app_uart_peekchar=-1; 185 | return ret; 186 | }else if(app_uart_get(&cr) == NRF_SUCCESS){ // nothing: NRF_ERROR_NOT_FOUND 187 | return (int16_t) cr; 188 | }else return -1; // Probably NOT_FOUND or sth. else 189 | } 190 | 191 | // tb_putsl - as puts, but without CR/NL 192 | void tb_putsl(char* pc){ 193 | if(_tb_uart_init_flag==false) return; // Not init... 194 | while(*pc){ 195 | if(tb_putc(*pc++)) break; 196 | } 197 | } 198 | 199 | // tb_printf(): printf() to toolbox uart. Wait if busy 200 | void tb_printf(char* fmt, ...){ 201 | ret_code_t ret; 202 | size_t ulen; 203 | uint8_t *pl; 204 | va_list argptr; 205 | va_start(argptr, fmt); 206 | 207 | if(_tb_uart_init_flag==false) return; // Not init... 208 | // Info: ulen is unlimited size, *_tb_app_uart_line_out has TB_SIZE_LINE_OUT elements, but vsnprintf prints max. TB_SIZE_LINE_OUT-1 plus trailing \0. 209 | ulen=vsnprintf((char*)_tb_app_uart_line_out, TB_SIZE_LINE_OUT, fmt, argptr); // vsn: limit! 210 | va_end(argptr); 211 | 212 | if(ulen>TB_SIZE_LINE_OUT-1) ulen=TB_SIZE_LINE_OUT-1; 213 | pl=_tb_app_uart_line_out; 214 | while(ulen--){ 215 | if(tb_putc(*pl++)) break; 216 | } 217 | } 218 | 219 | // Get String with Timeout (if >0) in msec of infinite (Timout 0), No echo (max_uart_in without trailing \0!) 220 | int16_t tb_gets(char* input, int16_t max_uart_in, uint16_t max_wait_ms, uint8_t echo){ 221 | int16_t idx=0; 222 | int16_t res; 223 | char c; 224 | max_uart_in--; // Reserve 1 Byte for End-0 225 | 226 | if(_tb_uart_init_flag==false) return 0; // Not init... 227 | 228 | for(;;){ 229 | res=tb_getc(); 230 | if(res>=0){ 231 | c=res; 232 | if(c=='\n' || c=='\r') { 233 | break; // NL CR or whatever (no Echo for NL CR) 234 | }else if(c==8){ // Backspace 235 | if(idx>0){ 236 | idx--; 237 | if(echo){ 238 | tb_putc(8); 239 | tb_putc(' '); 240 | tb_putc(8); 241 | } 242 | } 243 | }else if(c>=' ' && c<128 && idx nrf_drv_clock_init()": 390 | * Reported to NORDIC as 'Case ID: 277657' 391 | * Remove: "if (nrf_wdt_started()) m_clock_cb.lfclk_on = true;" 392 | 393 | Remove or disable THIS part: nrf_drv_clock.c (arround line 196-202 in SDK17): 394 | // if (nrf_wdt_started()) 395 | // { 396 | // m_clock_cb.lfclk_on = true; 397 | // } 398 | 399 | 400 | */ 401 | ret = nrf_drv_clock_init(); 402 | APP_ERROR_CHECK(ret); 403 | nrf_drv_clock_lfclk_request(NULL); 404 | #endif 405 | 406 | ret = app_timer_init(); // Baut sich eine Event-FIFO, Timer wird APP_TIMER_CONFIG auf 32k..1kHz gesetzt 407 | APP_ERROR_CHECK(ret); 408 | tb_basic_init_flag=true; 409 | /* Minimum Required Basic Block ---END--- */ 410 | } 411 | 412 | ret = tb_uart_init(NULL, NULL, 0, NULL, 0, -1); // Use default UART 413 | APP_ERROR_CHECK(ret); 414 | } 415 | // ------ uninit all higher power peripherals, currently only UART -------------------- 416 | void tb_uninit(void){ 417 | tb_uart_uninit(); 418 | //Special: Default UART to LOW if OFF 419 | nrf_gpio_cfg_input(TB_RX_PIN,GPIO_PIN_CNF_PULL_Pulldown); 420 | } 421 | 422 | 423 | // Get Startup-Bootcode 424 | inline uint32_t tb_get_bootcode(bool ok){ 425 | uint32_t res = _tb_bootcode_backup; 426 | if(ok) _tb_bootcode_backup=1; // Reset Bootcode to known state Starts with 1 427 | return res; 428 | } 429 | 430 | 431 | // ------ board support pakage or direct I/O ----- 432 | inline void tb_board_led_on(uint8_t idx){ 433 | nrf_gpio_pin_clear(TB_LED0); // LED OFF Active LOW 434 | 435 | } 436 | inline void tb_board_led_off(uint8_t idx){ 437 | nrf_gpio_pin_set(TB_LED0); // LED OFF Active LOW 438 | } 439 | inline void tb_board_led_invert(uint8_t idx){ 440 | nrf_gpio_pin_toggle(TB_LED0); // LED OFF Active LOW 441 | } 442 | // Get the Button State (optionally present) 443 | inline bool tb_board_button_state(uint8_t idx){ 444 | #ifdef TB_BUT0 445 | return nrf_gpio_pin_read(TB_BUT0); 446 | #else 447 | return 1; // Assume NOT PRESSED if not pressent 448 | #endif 449 | } 450 | 451 | // ------- System Reset (Will keep Watchdog active, if enabled) ------------ 452 | void tb_system_reset(void){ 453 | NVIC_SystemReset(); 454 | } 455 | 456 | // ShowPin - Debug-Function!: pin_number=NRF_GPIO_PIN_MAP(port, pin) // == ((pin_0_31)+port_0_1*32) 457 | // Will raise FATAL, if pin not existing... 458 | void tb_dbg_pinview(uint32_t pin_number){ 459 | nrf_gpio_pin_dir_t dir; 460 | nrf_gpio_pin_input_t input; 461 | nrf_gpio_pin_pull_t pull; 462 | nrf_gpio_pin_drive_t drive; 463 | nrf_gpio_pin_sense_t sense; 464 | 465 | tb_printf("P:%u.%02u: ",pin_number>>5,pin_number&31); 466 | tb_printf("I:%u ",nrf_gpio_pin_read(pin_number)); 467 | tb_printf("O:%u ",nrf_gpio_pin_out_read(pin_number)); 468 | 469 | NRF_GPIO_Type * reg = nrf_gpio_pin_port_decode(&pin_number); // Modifies PIN-Number to %32!!! 470 | uint32_t pr=reg->PIN_CNF[pin_number]; 471 | 472 | dir=(pr>>GPIO_PIN_CNF_DIR_Pos)&1; // 0: Input, 1: Output 473 | input=(pr>>GPIO_PIN_CNF_INPUT_Pos)&1; // 0: Connect, 1: Disconnect 474 | pull=(pr>>GPIO_PIN_CNF_PULL_Pos)&3; // 0: Disabled, 1: Pulldown, 3(!): Pullup 475 | drive=(pr>>GPIO_PIN_CNF_DRIVE_Pos)&7; // "S0S1","H0S1","S0H1","H0H1","D0S1","D0H1","S0D1","H0D1" 476 | sense=(pr>>GPIO_PIN_CNF_SENSE_Pos)&3; // 0: Disabled, 2(!):Sense_High 3(!):Sens_low 477 | 478 | tb_printf(dir?"Output ":"Input "); // 7 479 | tb_printf(input?"Disconn. ":"Connected "); // 10 480 | const char* drp[]={"NoPull ","PullDown","?Pull2? ","PullUp "}; // 8 481 | tb_printf("%s ",drp[pull]); 482 | const char* drv[]={"S0S1","H0S1","S0H1","H0H1","D0S1","D0H1","S0D1","H0D1"}; 483 | tb_printf("%s ",drv[drive]); 484 | const char* drs[]={"Sens.Disbl.","?Sense1?","SenseHigh","SenseLow"}; 485 | tb_printf("%s\n",drs[sense]); 486 | } 487 | 488 | 489 | //----- toolfunktion tools_get_hex_byte(): Holt ein HexByte aus einem HEX String, Ret: <0 ERR oder 0..255 ----- 490 | int16_t tb_tools_get_hex_byte(uint8_t **ppu){ 491 | uint8_t val = 0,n, *pu; 492 | pu=*ppu; 493 | for (uint8_t i = 0; i < 2; i++) { 494 | n = *pu++; 495 | if (n >= '0' && n <= '9') n -= '0'; 496 | else if (n >= 'a' && n <= 'f') n = n- 'a' + 10; 497 | else if (n >= 'A' && n <= 'F') n = n- 'A' + 10; 498 | else return -1; // Unknown 499 | val <<= 4; 500 | val += n; 501 | } 502 | *ppu=pu; 503 | return val; 504 | } 505 | 506 | 507 | //---------Watchdog, designed to run in unist of 10 sec----------- 508 | #ifdef PLATFORM_NRF52 509 | #if NRFX_WDT_CONFIG_RELOAD_VALUE < 250000 // if used with JesFs 510 | #warning "Watchdog Interval <250 seconds not recommended" 511 | #endif 512 | #endif 513 | 514 | // ------Watchdog, triggeres 60usec before reset ----- 515 | static uint32_t tb_wd_dcounter=0; // Max. Interval 2560 secs 516 | 517 | static void tb_wdt_event_handler(void){ 518 | _tb_bootcode+=0x10000000; // WD increments Hx from HH-Guard - Special 519 | for(;;); // Wait2Die - No chance to prevent this 520 | } 521 | 522 | // ---- enable the watchdog only once! ----------- 523 | // on nRF52: WD has 8 channels, here only 1 used 524 | uint32_t tb_watchdog_init(void){ // Will trigger after 10 sec 525 | ret_code_t ret; 526 | //Configure WDT. RELAOD_VALUE set in sdk_config.h 527 | // max. 131000 sec... 528 | ret = nrf_drv_wdt_init(NULL, tb_wdt_event_handler); 529 | APP_ERROR_CHECK(ret); 530 | ret = nrf_drv_wdt_channel_alloc(&tb_wd_m_channel_id); 531 | APP_ERROR_CHECK(ret); 532 | nrf_drv_wdt_enable(); 533 | tb_wdt_enabled=true; 534 | return tb_wd_m_channel_id; // 0..7 on nRF52 535 | } 536 | 537 | // ------ is Watchdog init? ---------------------- 538 | inline bool tb_is_wd_init(void){ 539 | return tb_wdt_enabled; 540 | } 541 | 542 | // ---- Feed the watchdog, No function if WD not initialised ------------ 543 | // feed_ticks currently ignored, but >0 544 | void tb_watchdog_feed(uint32_t feed_ticks){ 545 | if(feed_ticks && tb_wdt_enabled) { 546 | nrf_drv_wdt_channel_feed(tb_wd_m_channel_id); 547 | } 548 | } 549 | 550 | 551 | // --- A low Power delay --- 552 | APP_TIMER_DEF(tb_delaytimer); 553 | static bool _tb_expired_flag; 554 | static void tb_timeout_handler(void * p_context){ 555 | _tb_expired_flag=true; 556 | } 557 | 558 | void tb_delay_ms(uint32_t msec){ 559 | 560 | #if 0 561 | #warning "NRF_DELAY SDK16/SDK17-Problem: LFtimer not init! (-> search in this file 'SDK17')" 562 | nrf_delay_ms(msec); 563 | return; 564 | #endif 565 | 566 | uint32_t ticks = APP_TIMER_TICKS(msec); 567 | if(ticks0 23 | bool tb_is_wd_init(void); 24 | 25 | void tb_delay_ms(uint32_t msec); // --- Lower power delay than nrf_delay 26 | 27 | uint32_t tb_get_runtime(void); // This timer ALWAYS increments sec and is only set on Reset 28 | uint32_t tb_get_ticks(void); // System dependant for precise short periods (<1h) 29 | uint32_t tb_deltaticks_to_ms(uint32_t t0, uint32_t t1); 30 | uint32_t tb_runtime2time(uint32_t run_secs); 31 | uint32_t tb_time2runtime(uint32_t ux_secs); 32 | 33 | uint32_t tb_time_get(void); // ---- Unix-Timer. Must be called periodically to work, but at least twice per RTC-overflow --- 34 | void tb_time_set(uint32_t new_secs); // Set time, regarding the timer 35 | 36 | // --UART-- 37 | void tb_printf(char* fmt, ...); // tb_printf(): printf() to toolbox uart. Wait if busy 38 | void tb_putsl(char* pc); // // tb_putsl - as puts, but without CR/NL 39 | int16_t tb_putc(char c); // tb_putc(): Wait if not ready, may return -2 40 | int16_t tb_kbhit(void); // ---- Input functions 0: Nothing available 41 | int16_t tb_getc(void); // ---- get 1 char (0..255) (or -1 if nothing available) 42 | // Get String with Timout (if >0) in msec of infinite (Timout 0), No echo (max_uart_in without trailing \0!) 43 | int16_t tb_gets(char* input, int16_t max_uart_in, uint16_t max_wait_ms, uint8_t echo); 44 | bool tb_is_uart_init(void); 45 | bool tb_is_default_uart(void); 46 | // pcomm_params: (const app_uart_comm_params_t*): 47 | int16_t tb_uart_init(void *pcomm_params, uint8_t *prx_buf, uint16_t rx_buf_size, uint8_t *ptx_buf, uint16_t tx_buf_size, int32_t timout_ms); 48 | int16_t tb_uart_uninit(void); 49 | 50 | 51 | #if defined(NRF52) || defined(PLATFORM_NRF52) 52 | // Debug-Fkt to show Pin Config 53 | void tb_dbg_pinview(uint32_t pin_number); 54 | // Novo contains 4 uint32 to keep time and track software for post-mortem 55 | // GUARD: Each Sourcefile gets an uniqe ID (0..255), Guard write ID and LINE to bootcode 56 | extern uint32_t _tb_novo[8]; // __attribute__ ((section(".non_init"))); 57 | 58 | uint32_t tb_get_bootcode(bool ok); 59 | 60 | #define _tb_bootcode _tb_novo[3] // Bootcode for post-mortem analysis 61 | // 2 Type of Guards: Absolute and only for DEBUG see mcs_novo_init() for details 62 | #define GUARD(x) _tb_bootcode=(((x)<<16) | __LINE__ ) 63 | #ifdef DEBUG 64 | #define DBG_GUARD(x) _tb_bootcode=( ((x)<<16)|__LINE__) 65 | #else 66 | #define DBG_GUARD(x) // Nothing 67 | #endif 68 | #endif 69 | 70 | //*** 71 | 72 | -------------------------------------------------------------------------------- /usecase_BlackBox/BlackBox_Eval.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joembedded/JesFs/ebabac8866c69107afa3e4e1fef24a9b6ef647d7/usecase_BlackBox/BlackBox_Eval.pdf -------------------------------------------------------------------------------- /usecase_BlackBox/blackbox_helpers.c: -------------------------------------------------------------------------------- 1 | /***************************************************************** 2 | * blackbox_helpers.c 3 | * 4 | * Source-File with some less important stuff for the blackbox 5 | *******************************************************************************/ 6 | 7 | #ifdef WIN32 // Visual Studio Code defines WIN32 8 | #define _CRT_SECURE_NO_WARNINGS // VS somtimes complains traditional C 9 | #endif 10 | 11 | 12 | #include "blackbox_helpers.h" // Some unimportant stuff for this demo 13 | #include "tb_tools.h" 14 | 15 | #include "JesFs.h" 16 | 17 | #ifdef WIN32 // Visual Studio Code defines WIN32 18 | #define __WIN32__ // Embarcadero defines __WIN32__ 19 | #endif 20 | #ifdef __WIN32__ 21 | extern int16_t ll_read_vdisk(char* fname); // Helpers to write/read virtual Disk to fFile on PC 22 | extern int16_t ll_setid_vdisk(uint32_t id); 23 | extern int16_t ll_get_info_vdisk(uint32_t* pid_used, uint8_t** pmem, uint32_t* psize); 24 | #endif 25 | 26 | 27 | //************** Globals **************** 28 | FS_DATE fs_date; // A JesFs-Structure for dates 29 | 30 | 31 | #ifdef __WIN32__ 32 | #define USE_DEFAULT_DISK // Enable for persistance 33 | // * Only on Windows - Load Disk from file (if available) 34 | void helper_load_disk_from_file(void){ 35 | #ifdef USE_DEFAULT_DISK 36 | int16_t res; 37 | // There may be an old image available 38 | tb_printf("__WIN32__ Read VirtualDisk from File: 'default.disk' -> "); 39 | fs_start(FS_START_NORMAL); // On PC: 40 | res=ll_read_vdisk("default.disk"); // Read raw image 1:1 to RAM 41 | if(res) tb_printf("Result: %d\n",res); 42 | else tb_printf("OK\n"); 43 | #endif 44 | } 45 | 46 | // * Only on Windows - Save Disk to file 47 | void helper_save_disk_to_file(void){ 48 | #ifdef USE_DEFAULT_DISK 49 | int16_t res; 50 | tb_printf("__WIN32__ Write VirtualDisk to File: 'default.disk' -> "); 51 | res=ll_write_vdisk("default.disk"); 52 | if(res) tb_printf("Result: %d\n",res); 53 | else tb_printf("OK\n"); 54 | #endif 55 | } 56 | #endif 57 | 58 | // * Convert a UNIX-Time to date (as string) 59 | void helper_conv_secs_to_date(uint32_t asecs, uint8_t *sbuffer){ 60 | // Use JesFs-builtin Fkt 61 | fs_sec1970_to_date(asecs,&fs_date); 62 | sprintf((char*)sbuffer,"%02u.%02u.%04u %02u:%02u:%02u",fs_date.d,fs_date.m,fs_date.a,fs_date.h,fs_date.min,fs_date.sec); 63 | } 64 | 65 | 66 | // * Show Disk Directory ** 67 | void helper_show_directory(void){ 68 | FS_STAT fs_stat; 69 | FS_DESC fs_desc; 70 | uint8_t dbuffer[40]; // Date buffer (Text) 71 | int16_t res=0; 72 | int16_t i; 73 | 74 | tb_printf("Disk size: %d Bytes\n", sflash_info.total_flash_size); 75 | if(sflash_info.creation_date==0xFFFFFFFF){ // Severe Error 76 | tb_printf("Error: Invalid/Unformated Disk! (-108)\n"); 77 | return; 78 | } 79 | tb_printf("Disk available: %d Bytes / %d Sectors\n",sflash_info.available_disk_size,sflash_info.available_disk_size/SF_SECTOR_PH); 80 | helper_conv_secs_to_date(sflash_info.creation_date, dbuffer); 81 | tb_printf("Disk formated [%s]\n",dbuffer); 82 | for(i=0;i 9 | #include 10 | #include 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #ifdef __WIN32__ 18 | // external Low-Level-Helper functions for WIN32 to save RAM as JesFs-File in JesFs_ll_pc.c 19 | extern int16_t ll_write_vdisk(char *fname); // PC LowLevel LL-Driver 20 | extern int16_t ll_read_vdisk(char *fname); // PC LowLevel LL-Driver 21 | extern void ll_setid_vdisk(uint32_t id); // PC LowLevel LL-Driver 22 | 23 | void helper_save_disk_to_file(void); 24 | void helper_load_disk_from_file(void); 25 | 26 | #endif 27 | 28 | // Common Helper Functions 29 | void helper_show_board(void); 30 | void helper_conv_secs_to_date(uint32_t asecs, uint8_t *sbuffer); 31 | void helper_show_directory(void); 32 | 33 | // END 34 | 35 | -------------------------------------------------------------------------------- /usecase_BlackBox/blackbox_main.c: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * BlackBox_main.c 3 | * 4 | * This Demo shows how to use JesFs for a "BlackBox": a History-Logger. 5 | * 'History' means: The logger can see some history data, but will NEVER 6 | * overflow. So you can use a small part of the Flash for history data e.g. 7 | * for post-mortem analysis 8 | * 9 | * The BlackBox was tested on: 10 | * - TI CC13xx/CC26xx Launchpad 11 | * - Nordic nRF52840 DK_PCA10056 (nRF52) 12 | * - Windows (Compilers: "Embarcadero(R) C++ Builder Community Edition" (for PC) 13 | * and "Microsoft Visual Studio Community 2019") 14 | * 15 | * (C)2020 joembedded@gmail.com - www.joembedded.de 16 | * Versions: 17 | * 1.5 / 25.11.2019 18 | * 2.0 / 24.09.2020 (nRF52) SDK 17.0.2 and SES 5.10b on NORDIC PCA10056-Evalboard 19 | * 2.01 / 17.03.2023 _supply_voltage_check(void) 20 | * 21 | *******************************************************************************/ 22 | 23 | #ifdef WIN32 // Visual Studio Code defines WIN32 24 | #define _CRT_SECURE_NO_WARNINGS // VS somtimes complains traditional C 25 | #endif 26 | 27 | #include "blackbox_helpers.h" // Some unimportant stuff for this demo 28 | #include "tb_tools.h" 29 | 30 | /**************************************************************** 31 | * - Core of BlackBox-Demo 32 | ******************************************************************/ 33 | #include "JesFs.h" 34 | #include "JesFs_int.h" // JesFs-helpers like fs_get_time() 35 | 36 | #ifdef CC13XX_CC26XX // Define this Macro in ProjectOptions - PredefinedSymbols 37 | #define main mainThread // main_start is a Task 38 | #endif 39 | #ifdef WIN32 // Visual Studio Code defines WIN32 40 | #define __WIN32__ // Embarcadero defines __WIN32__ 41 | #endif 42 | 43 | 44 | /***************************************************************** 45 | * Globals 46 | ******************************************************************/ 47 | static uint8_t sbuffer[256]; // Test buffer (universal use) 48 | 49 | #define MAX_INPUT 80 50 | static char input[MAX_INPUT+1]; 51 | 52 | #define HISTORY 1000 // Max. History for Data in Bytes 53 | static int32_t value=0; // Sample Value to record 54 | 55 | /***************************************************************** 56 | * Platform specific 57 | ******************************************************************/ 58 | uint32_t _time_get(void) { 59 | return tb_time_get(); 60 | } 61 | int16_t _supply_voltage_check(void){ 62 | return 0; // Assume Power OK 63 | } 64 | 65 | 66 | /******************************************************************* 67 | * log_blackbox(char* logtext, uint16_t len) 68 | * 69 | * This funktion logs one line to the the history 70 | ********************************************************************/ 71 | int16_t log_blackbox(char* logtext, uint16_t len){ 72 | FS_DESC fs_desc, fs_desc_sec; // 2 JesFs file descriptors 73 | int16_t res; 74 | 75 | res=fs_start(FS_START_RESTART); 76 | if(res) return res; 77 | 78 | // Flags (see docu): Create File if not exists and open in RAW-mode, 79 | // in RAW-Mode file is not truncated if existing 80 | res=fs_open(&fs_desc,"Data.pri",SF_OPEN_CREATE|SF_OPEN_RAW); 81 | if(res) return res; 82 | 83 | // Place (internal) file pointer to the end of the file to allow write 84 | fs_read(&fs_desc,NULL,0xFFFFFFFF); // (dummy) read as much as possible 85 | 86 | // write the new data (ASCII) to the file 87 | res=fs_write(&fs_desc,(uint8_t*)logtext,len); 88 | if(res) return res; 89 | 90 | // Show what was written 91 | tb_printf("Pos:%u Log:%s",fs_desc.file_len,logtext); 92 | 93 | // Now make a file shift if more data than HISTORY 94 | if(fs_desc.file_len>= HISTORY){ 95 | 96 | tb_printf("Shift 'Data.pri' -> 'Data.sec'\n"); 97 | 98 | // Optionally delete and (create in any case) backup file 99 | res=fs_open(&fs_desc_sec,"Data.sec",SF_OPEN_CREATE); 100 | if(res) return res; 101 | 102 | // rename (full) data file to secondary file 103 | res=fs_rename(&fs_desc,&fs_desc_sec); 104 | if(res) return res; 105 | } 106 | fs_deepsleep(); // Set Filesystem to UltraLowPowerMode 107 | return 0; // OK 108 | } 109 | 110 | /******************************************************************* 111 | * run_blackbox(asec) 112 | * Take a record each asec secs, until Data.pri is >= HISTORY, 113 | * then shift it to Data.sec and delete Data.pri. 114 | * This demo uses "unclosed Files", which is very useful here. 115 | * Run recoder loop *FOREVER* or until user hits key 116 | ********************************************************************/ 117 | int16_t run_blackbox(uint32_t delay_secs){ 118 | uint32_t asecs; 119 | uint16_t len; 120 | int16_t res; 121 | uint32_t i; 122 | for(;;){ // Forever 123 | // modify a random value and get time (UNIX seconds) 124 | value+=(rand()&255)-128; // Move sample value 125 | asecs=fs_get_secs(); 126 | 127 | // Build the data we want to save: Time + Value 128 | len=sprintf((char*)sbuffer,"%u %d\n",asecs,value); 129 | 130 | // Filesystem may be sleeping (= UltraLowPowerMode), WAKE fast 131 | res=log_blackbox((char*)sbuffer, len); 132 | if(res) break; // Error? 133 | 134 | // SLEEP 135 | for(i=0;i80 chars, so read less 176 | res=fs_read(&fs_desc,sbuffer,40); // read max. 40 177 | if(res<=0) break; 178 | sbuffer[res]=0; // make it a string 179 | total+=res; 180 | tb_printf("%s",sbuffer); 181 | } 182 | tb_printf("Total read: %u Bytes\n",total); 183 | return res; // (fs_close not required in JesFs) 184 | } 185 | 186 | /****************************************************************** 187 | * M A I N 188 | *******************************************************************/ 189 | void *main(void *arg0){ 190 | int32_t res,par; 191 | char *pc; // Points to argument 192 | uint32_t asecs; 193 | 194 | tb_init(); 195 | 196 | tb_printf("\n*** JesFs *BlackBox-Test* V1.5 "__TIME__ " " __DATE__ " ***\n\n"); 197 | tb_printf("(C)2019 joembedded@gmail.com - www.joembedded.de\n\n"); 198 | 199 | #ifdef __WIN32__ 200 | helper_load_disk_from_file(); // Use a File to store JesFs-Disk 201 | #endif 202 | 203 | tb_printf("'f': Format Disk\n"); 204 | tb_printf("'n': New Measure, Delete Data Files\n"); 205 | tb_printf("'r NUMBER' Run BlackBox with Delay NUMBER secs...\n"); 206 | tb_printf("'1' Show File 'Data.pri'\n"); 207 | tb_printf("'2' Show File 'Data.sec'\n"); 208 | tb_printf("'v' Disk Directory\n"); 209 | tb_printf("'! [SECONDS]' Print Time or optionally set UNIX-Seconds\n"); 210 | tb_printf("'q' Exit (on __WIN32__/WIN32: save Disk as File 'default.disk')\n\n"); 211 | 212 | tb_printf("Init-JesFS: Res:%d\n",fs_start(FS_START_NORMAL)); // Unformated: Return -108 (see jesfs.h) 213 | 214 | while (1) { 215 | tb_board_led_invert(0); // Toggle LED (if available) 216 | tb_printf("> "); 217 | res=tb_gets(input,MAX_INPUT, 60000, 1); // 60 seconds time with echo 218 | tb_putc('\n'); 219 | 220 | if(res>0){ 221 | pc=&input[1]; 222 | while(*pc==' ') pc++; // Remove Whitspaces from Input 223 | switch(input[0]){ 224 | 225 | case 'f': // Format Disk 226 | par=2; // Full:1 Soft:2 (here: Soft is faster, up to 240 secs on Serial Flash) 227 | tb_printf("'f' Format Serial Flash (Mode:%d) (may take up to 240 secs!)...\n",par); 228 | tb_printf("Result: %d\n",fs_format(par)); 229 | break; 230 | 231 | case 'n': 232 | tb_printf("'n' New Measure. Delete Data Files\n"); 233 | tb_printf("Result: %d\n",new_measure()); // 0:OK 234 | break; 235 | 236 | case 'r': // (0 possible too for FAST data ;-) ) 237 | asecs=strtoul(pc,NULL,0); 238 | tb_printf("'r' Run BlackBox with Delay %d secs...\n",asecs); 239 | tb_printf("\n"); 240 | run_blackbox(asecs); 241 | break; 242 | 243 | case '1': 244 | tb_printf("'1' Show File 'Data.pri'\n"); 245 | tb_printf("Result: %d\n",show_file("Data.pri")); // 0:OK 246 | break; 247 | case '2': 248 | tb_printf("'2' Show File 'Data.sec'\n"); 249 | tb_printf("Result: %d\n",show_file("Data.sec")); // 0:OK 250 | break; 251 | 252 | 253 | case 'v': // Listing on virtual Disk - Only basic infos. No checks, Version with **File Health-Check** for all files with CRC in JesFs_cmd.c 254 | tb_printf("'v' Directory:\n"); 255 | helper_show_directory(); 256 | break; 257 | 258 | case 'q': // Quit: System Reset. 259 | tb_printf("'q' Exit in 1 sec...\n"); 260 | tb_delay_ms(1000); 261 | tb_printf("Bye!\n"); 262 | #ifdef __WIN32__ 263 | helper_save_disk_to_file(); 264 | #endif 265 | tb_system_reset(); // PC: exit(), TI-RTOS: Up to Debugger what happens: Reset, Stall, Nirvana, .. See TI docu. 266 | 267 | case '!': // Time Management - Set the embedded Timer (in unix-Seconds) 268 | asecs=strtoul(pc,NULL,0); 269 | if(asecs) tb_time_set(asecs); // Only accepted on CPU 270 | asecs=tb_time_get(); 271 | helper_conv_secs_to_date(asecs, sbuffer); 272 | tb_printf("'!': Time: [%s] (%u secs)\n",sbuffer,asecs); 273 | break; 274 | 275 | default: 276 | tb_printf("???\n"); 277 | } 278 | } 279 | } 280 | } 281 | 282 | // END 283 | -------------------------------------------------------------------------------- /usecase_BlackBox/platform_CC13XX_CC26XX/ReadMe.txt: -------------------------------------------------------------------------------- 1 | # ReadMe.txt # 2 | 3 | Please read the JesFs.pdf how to build the JesFs Demo for CC13XX and CC26XX CPUs. 4 | -------------------------------------------------------------------------------- /usecase_BlackBox/platform_WIN/BlackBox_cpp_stdio.cbproj.local: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 1899.12.30 00:00:00.000.306,=C:\c\cx\JesFsDemo\JesFsDemo\usecase_Blackbox\blackbox_main.c 5 | 1899.12.30 00:00:00.000.292,=C:\c\cx\JesFsDemo\JesFsDemo\usecase_Blackbox\blackbox_helpers.h 6 | 1899.12.30 00:00:00.000.096,=C:\c\cx\JesFsDemo\JesFsDemo\jesfs_hl.c 7 | 1899.12.30 00:00:00.000.952,C:\c\cx\Project1.cbproj=C:\c\cx\JesFsDemo\JesFsDemo\usecase_Blackbox\win\BlackBox_cpp_stdio.cbproj 8 | 1899.12.30 00:00:00.000.144,=C:\c\cx\Project1PCH1.h 9 | 1899.12.30 00:00:00.000.098,=C:\c\cx\Project1PCH1.h 10 | 1899.12.30 00:00:00.000.081,=C:\c\cx\Project1PCH1.h 11 | 1899.12.30 00:00:00.000.728,=C:\c\cx\Project1PCH1.h 12 | 1899.12.30 00:00:00.000.104,=C:\c\cx\JesFsDemo\JesFsDemo\jesfs_ml.c 13 | 1899.12.30 00:00:00.000.153,=C:\c\cx\JesFsDemo\JesFsDemo\platform_WIN\JesFs_ll_pc.c 14 | 1899.12.30 00:00:00.000.161,=C:\c\cx\JesFsDemo\JesFsDemo\platform_WIN\tb_tools_win.c 15 | 1899.12.30 00:00:00.000.296,=C:\c\cx\JesFsDemo\JesFsDemo\usecase_Blackbox\blackbox_helpers.c 16 | 1899.12.30 00:00:00.000.104,=C:\c\cx\File1.c 17 | 1899.12.30 00:00:00.000.155,=C:\c\cx\Unit1.cpp 18 | 1899.12.30 00:00:00.000.741,=C:\c\cx\Unit1.cpp 19 | 1899.12.30 00:00:00.000.108,=C:\c\cx\JesFsDemo\JesFsDemo\tb_tools.h 20 | 1899.12.30 00:00:00.000.090,=C:\c\cx\Unit1.cpp 21 | 22 | 23 | -------------------------------------------------------------------------------- /usecase_BlackBox/platform_WIN/BlackBox_cpp_stdio.res: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joembedded/JesFs/ebabac8866c69107afa3e4e1fef24a9b6ef647d7/usecase_BlackBox/platform_WIN/BlackBox_cpp_stdio.res -------------------------------------------------------------------------------- /usecase_BlackBox/platform_WIN/BlackBox_cpp_stdio.stat: -------------------------------------------------------------------------------- 1 | [Stats] 2 | EditorSecs=1 3 | DesignerSecs=1 4 | InspectorSecs=1 5 | CompileSecs=462 6 | OtherSecs=2 7 | StartTime=28.11.2019 17:21:25 8 | RealKeys=0 9 | EffectiveKeys=0 10 | DebugSecs=4 11 | -------------------------------------------------------------------------------- /usecase_BlackBox/platform_WIN/Win32/Debug/BlackBox_cpp_stdio.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joembedded/JesFs/ebabac8866c69107afa3e4e1fef24a9b6ef647d7/usecase_BlackBox/platform_WIN/Win32/Debug/BlackBox_cpp_stdio.exe -------------------------------------------------------------------------------- /usecase_BlackBox/platform_nRF52_nrf52840/ReadMe.txt: -------------------------------------------------------------------------------- 1 | # ReadMe.txt # 2 | 3 | Please read the JesFs.pdf how to build the JesFs Demo for nRF52 CPUs 4 | -------------------------------------------------------------------------------- /usecase_BlackBox/platform_nRF52_nrf52840/ses/flash_placement.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /usecase_BlackBox/readme.md: -------------------------------------------------------------------------------- 1 | # JesFs – BlackBox-Demo # 2 | ## A Flight Recorder for Home Use ## 3 | 4 | Many technical devices work reliable for years and years and no one cares about them. But if they fail, there is always the question: WHAT WENT WRONG? 5 | 6 | This is, where the JesFs ( Jo’s Embedded Serial File System) could become extremely useful. 7 | 8 | Read more: [BlackBox_Eval.pdf](https://github.com/joembedded/JesFs/blob/master/usecase_BlackBox/BlackBox_Eval.pdf) 9 | 10 | --------------------------------------------------------------------------------