Forum Rule: Always post complete source code & details to reproduce any issue!
Page 1 of 2 1 2 LastLast
Results 1 to 25 of 26

Thread: Update files on SD Card through Teensy without removing card or reprogramming Teensy

  1. #1

    Update files on SD Card through Teensy without removing card or reprogramming Teensy

    I'm running an Arduino sketch that uses an SD card for storage, but didn't like having to remove the card and connect it to my computer every time I wanted to update files. The uTasker project has code that can share the SD card over USB-MSD so the Teensy 3.1 looks like a memory stick, but I didn't want to have to reprogram the Teensy twice each time I want to update the SD card and go back to the sketch, or port my Arduino sketches over to uTasker.

    I had the idea of creating a small uTasker project (<32kB) that shares the SD card like a memory stick, and putting that program at the end of flash, leaving 224kB left for my Arduino sketch. The work I did already on jumping from one Arduino sketch to another lets me jump from the Arduino sketch to the uTasker project, and go back to the Arduino sketch after a reset.

    I released an example Arduino sketch that shows how to jump to the uTasker project, and binaries for two uTasker projects - one with SPI pinouts for the SmartMatrix Shield, and another for the Teensy Audio Adapter Board.
    JumpToUsbMsdAppWithOffset - Github

    Please note that the uTasker project is licensed software, and in keeping with the terms of their license, the binaries are for non-commercial use. I do plan to open source my changes to the stock uTasker project so you can purchase a license (or get a free non-commercial license) and compile the software yourself. Please post here if you are interested so I can prioritize sharing the changes.
    Last edited by embedded-creations; 04-09-2015 at 02:55 AM.

  2. #2
    Wow, that would be incredible. Having a relatively easy way to add USB-MSD to a data logger is extremely attractive. Color me very interested.

    I've been trying to get my own USB-MSD up and running but have not been making a lot of progress. I'd definitely appreciate even a diff of your config.h, what else did you have to change other than setting the MK20 defines, enabling USB-MSD, and SDCARD_SUPPORT? Pinouts didn't seem to be my issue, as I found where to change those as appropriate.

  3. #3
    Did you get the right linker file set up? I'd start there.

  4. #4
    Believe so -

    Code:
    "${uTaskerLinkerScripts}/K_256_64.ld"
    for the Teensy 3.1.

  5. #5
    To update, I also double checked that the target processor was a cortex-m4.

    Did you have to reduce the clock speed to 48MHz?

  6. #6
    This might be hard to use, but here's a patch file showing all changes I committed to a private git repo starting from uTasker 1.4.7. There's some stuff in there that probably shouldn't be, like .hex files and settings files. Let me know if that helps, or you need something different:

    https://db.tt/bpIv8WiG

  7. #7
    Here's another patch with just the changes to 1.4.7 I made to share the SD card over USB using the default SPI pinout.

    https://db.tt/KGmYAxh2

    I don't recall changing any clock speeds (I don't even know where I'd go to do that in KDS/uTasker).

  8. #8
    Excellent, I'm digging through it now. The diff looks fine to determine the changes to make. I'll report back and get a little guide of sorts posted once I get it running.

    I should also note that I had your compiled version up and running immediately, works perfectly.

  9. #9
    Success!

    Went through your diffs and have it working with the default SPI0 pins. Working on adding your defines in for the different boards, although I might change them up a bit to allow for more flexibility. Will post a quick-start guide detailing the changes I had to make in case someone would like to follow in your footsteps.

    I've yet to add in the flash offset. Did you offset the utasker hex, or the arduino hex? I assume you moved the utasker hex flash location and kept the arduino at default?

  10. #10
    Flash Offset is done in KDS and it's just a linker file change.

    https://db.tt/Zs6oDatG

    Flash starts with an offset, and is shorter
    Vectors are at an offset
    Remove the config segment (that's now set by the Arduino app located at 0x0000)

  11. #11
    The macros for configuring pins are a little tricky, I couldn't find a way to define SPI_PORT for example and use that for all the config statements. I had to put "D" directly into the _CONFIG_PERIPHERAL macro, SPI_PORT wouldn't work.

  12. #12
    Oh, I see what you ran into. I ran into it face first as well.

    In kinetis.h, line ~9142:

    Code:
    #define _CONFIG_DRIVE_PORT_OUTPUT_VALUE(ref, pins, value, chars) SIM_SCGC5 |= SIM_SCGC5_PORT##ref; fnConnectGPIO(PORT##ref, pins, chars); GPIO##ref##_PDOR = ((GPIO##ref##_PDOR & ~(pins)) | (value)); GPIO##ref##_PDDR |= (pins); _SIM_PORT_CHANGE
    Requires one to pass 'C' or 'D' directly, and doesn't like macro expansions. I'm admittedly clueless when it comes to expansion order of operations, but I'm going to read up on it now.

    Seems this is ok:

    Code:
    _CONFIG_DRIVE_PORT_OUTPUT_VALUE(C, SPI_CS1_0, SPI_CS1_0, (PORT_SRE_FAST | PORT_DSE_HIGH)); \
    Where this is not:

    Code:
    #define TEENSY_3_1_CS1_PORT		C
    
    _CONFIG_DRIVE_PORT_OUTPUT_VALUE(TEENSY_3_1_CS1_PORT, SPI_CS1_0, SPI_CS1_0, (PORT_SRE_FAST | PORT_DSE_HIGH)); \
    Last edited by kam42; 04-21-2015 at 10:33 PM.

  13. #13
    For anyone reading along, it seems that the reason for the above problem is that the preprocessor does not expand macros recursively except in certain situations, as detailed here, with a workaround:

    http://stackoverflow.com/questions/1...sitioning-macr

  14. #14
    Senior Member
    Join Date
    Mar 2014
    Location
    Switzerland
    Posts
    109
    Hi

    I can confirm that this 'restriction' is due to the compiler pre-processor not being able to use defines for its macro input.

    One 'help' is to use the port reference in the pin name:


    _CONFIG_DRIVE_PORT_OUTPUT_VALUE(D, PORTD_BIT3, PORTD_BIT3, (PORT_SRE_FAST | PORT_DSE_HIGH));
    is in fact quite easy to handle because if the pin is changed to PORTC_BIT7, for example, it is very obvious that also the port (C) needs to be adjusted but of course working directly with the port bit is not normally the best solution.

    Therefore
    #define SPI_CS1_0_ON_PTD3 PORTD_BIT3
    would automatically give that extra bit of information to avoid 'forgetting' to adjust the port parameter when moving around.
    _CONFIG_DRIVE_PORT_OUTPUT_VALUE(D, SPI_CS1_0_ON_PTD3, SPI_CS1_0_ON_PTD3, (PORT_SRE_FAST | PORT_DSE_HIGH));
    would be a good compromise.


    Note that peripheral pin definitions used in the peripheral configuration, eg.
    _CONFIG_PERIPHERAL(A, 6, (PA_6_TPM0_CH0 | PORT_SRE_FAST | PORT_DSE_HIGH)); // TPM0_CH0 on PA.6 (alt. function 2)

    are all defined to work like this - as is seen, the name of the peripheral function automatically gives the port and bit references that are to be used.


    Final point, note that there are also _CONFIG_DRIVE_PORT_OUTPUT_VALUE_FAST_LOW() and _CONFIG_DRIVE_PORT_OUTPUT_VALUE_FAST_HIGH() macros which make use of the processor's PORTx_GPCLR and PORTx_GPCHR registers to configure quicker, with the restriction that LOW only handles the ports bits 0..15 and HIGH handles only the port bits 16..31, whereas the general (slower) _CONFIG_DRIVE_PORT_OUTPUT_VALUE() handles all 32 bits of a port (either one or multiple pins requiring the same settings).

    The complete macro list is available at http://www.utasker.com/forum/index.php?topic=1875.0

    Regards

    Mark

  15. #15
    Senior Member
    Join Date
    Mar 2014
    Location
    Switzerland
    Posts
    109
    Hi

    Note on processor speed configuration. This is in app_hw_kinetis.h - for the Teensy 3.1 it is 72MHz by default, which is set by this block

    #define OSC_LOW_GAIN_MODE
    #define CRYSTAL_FREQUENCY 16000000 // 16 MHz crystal
    #define _EXTERNAL_CLOCK CRYSTAL_FREQUENCY
    #define CLOCK_DIV 8 // input must be divided to 2MHz..4MHz range (/1 to /25 possible)
    #define CLOCK_MUL 36 // the PLL multiplication factor to achieve operating frequency of 48MHz (x24 to x55 possible)
    #define USB_CLOCK_GENERATED_INTERNALLY // use USB clock from internal source rather than external pin


    Low gain mode is used when there is little loading on the ocillator (with caps and feedback resistor the high gain mode would be needed to allow the oscillator to start reliably).
    This will use the PLL from the 16MHz crystal / 8 = 2MHz, multiplied by 36 = 72MHz.
    The USB clock is derived internally from this, rather than being taken from a 48MHz source on the dedicated USB clock input pin.

    To modify the CPU frequency you can play around with CLOCK_MUL; the build will fail if anything is out-of-spec so there is no risk.
    The only thing to be weary of is that the internal 48MHz USB clock frequency cannot be derived from all speeds (when running in the simulator this will be signalled if not possile) but 48MHz, 72MHz and 96MHz are certainly fine. To run at 96MHz (overclocking) you will however need to remove the error catch in the code which will cause the build to fail - for real products 72MHz would be the limit since higher is not guaranteed [by Freescale] to be reliable.

    All other settings are adjusted automatically to match the CPU speed.

    Regards

    Mark

  16. #16
    Mark,

    Thanks for the advice. Here's my changes so far. I've tested all of the defined pins, although I didn't run through every combination. Have a few more things to change, mostly the offset and watchdog, and then will put this on github in case people would like to try it on their Teensy. Really impressed with this capability - it really makes the Arduino side simpler with regards to not needing a serial downloader/uploader for data.

    Starting at line 3757 in app_hw_kinetis.h:

    Code:
    #elif defined TEENSY_3_1 || defined TWR_K20D72M
            // Configure to suit SD card SPI mode at between 100k and 400k
            // SD Card SPI default pin configuration for Teensy 3.1
    		#define TEENSY_3_1_SCK()		_CONFIG_PERIPHERAL(D, 1, PD_1_SPI0_SCK) 									// Teensy 3.1 pin D14/A0
    		#define TEENSY_3_1_SCK_ALT1()	_CONFIG_PERIPHERAL(C, 5, PC_5_SPI0_SCK) 									// Teensy 3.1 pin D13/LED
    
    		#define TEENSY_3_1_DOUT()		_CONFIG_PERIPHERAL(C, 6, (PC_6_SPI0_SOUT | PORT_SRE_FAST | PORT_DSE_HIGH))	// Teensy 3.1 pin D11
    		#define TEENSY_3_1_DOUT_ALT1()	_CONFIG_PERIPHERAL(D, 2, (PD_2_SPI0_SOUT | PORT_SRE_FAST | PORT_DSE_HIGH))	// Teensy 3.1 pin D7
    
    		#define TEENSY_3_1_DIN()		_CONFIG_PERIPHERAL(C, 7, (PC_7_SPI0_SIN | PORT_PS_UP_ENABLE))				// Teensy 3.1 pin D12
    		#define TEENSY_3_1_DIN_ALT1()	_CONFIG_PERIPHERAL(D, 3, (PD_3_SPI0_SIN | PORT_PS_UP_ENABLE))				// Teensy 3.1 pin D8
    
    		#define SPI_CS1_0_ON_PTD4	PORTD_BIT4 		// Teensy 3.1 pin D6 - TODO Change to pin D10 to match teensy 3.1 pinout card default
    		#define SPI_CS1_0_ON_PTC3	PORTC_BIT3		// Teensy 3.1 pin D9
    		#define SPI_CS1_0_ON_PTD5	PORTD_BIT5		// Teensy 3.1 pin D20/A6
    		#define SPI_CS1_0_ON_PTD6	PORTD_BIT6		// Teensy 3.1 pin D21/A7
    		#define SPI_CS1_0_ON_PTD1	PORTD_BIT1		// Teensy 3.1 pin D15/A1
    		#define SPI_CS1_0_ON_PTC4	PORTC_BIT4		// Teensy 3.1 pin D10
    
            // *****************************************************************
            // Edit pin assignments below to match your SPI SD card connections!
    
            // Define Chip Select (CS) Pin for Teensy 3.1
            //	Choose from the above list (eg SPI_CS1_0_ON_PTD4)
            #define SPI_CS1_0 			SPI_CS1_0_ON_PTC3
    
            // Define SCK, DOUT, DIN Pins for Teensy 3.1
            //	Choose from the above list for each assignment.
            //  NOTE - Modify _CONFIG_DRIVE_PORT_OUTPUT_VALUE(D -> accordingly depending on choice of SPI_CS1_0 port (C or D)
            #define INITIALISE_SPI_SD_INTERFACE() POWER_UP(6, SIM_SCGC6_SPI0); \
            TEENSY_3_1_SCK_ALT1(); \
            TEENSY_3_1_DOUT(); \
            TEENSY_3_1_DIN(); \
            _CONFIG_DRIVE_PORT_OUTPUT_VALUE(C, SPI_CS1_0, SPI_CS1_0, (PORT_SRE_FAST | PORT_DSE_HIGH)); \
            SPI0_CTAR0 = (SPI_CTAR_ASC_6 | SPI_CTAR_FMSZ_8 | SPI_CTAR_CPHA | SPI_CTAR_CPOL | SPI_CTAR_BR_128); SPI0_MCR = (SPI_MCR_DIS_TXF | SPI_MCR_DIS_RXF | SPI_MCR_MSTR | SPI_MCR_DCONF_SPI | SPI_MCR_CLR_RXF | SPI_MCR_CLR_TXF | SPI_MCR_PCSIS_CS0 | SPI_MCR_PCSIS_CS1 | SPI_MCR_PCSIS_CS2 | SPI_MCR_PCSIS_CS3 | SPI_MCR_PCSIS_CS4 | SPI_MCR_PCSIS_CS5)
    
    
            // NOTE - Change the first parameter in each function call to either C or D, depending on the PORTx letter for TEENSY_3_1_CS_X.
            // 	e.g. for TEENSY_3_1_CS_ALT1, keep them C
            //	for TEENSY_3_1_CS_ALT2, change them to D.
            // Also do the same for the first parameter in _CONFIG_DRIVE_PORT_OUTPUT_VALUE() above.
    		#define SET_SD_DI_CS_HIGH()  _SETBITS(C, SPI_CS1_0)              // force DI and CS lines high ready for the initialisation sequence
            #define SET_SD_CS_LOW()      _CLEARBITS(C, SPI_CS1_0)            // assert the CS line of the SD card to be read
            #define SET_SD_CS_HIGH()     _SETBITS(C, SPI_CS1_0)              // negate the CS line of the SD card to be read
    
            // End pin modification section for Teensy 3.1
            // *****************************************************************

  17. #17
    Just curious, why do you need to change the watchdog? The uTasker application is set to use it, and it gets reset when you go back to running a Teensyduino application, so no harm done.

    What offset are you going to use? In case you didn't see it in my changes, if you remove the USE_MAINTENANCE definition the application gets much smaller.

    I talked to Mark about posting my uTasker code on GitHub, and I'm pretty sure he doesn't want a full project including code that is copyright uTasker to go on GitHub. A patch file showing changes from a uTasker release would be fine. I don't have enough experience with patch files to know the best option here.

  18. #18
    Quote Originally Posted by embedded-creations View Post
    Just curious, why do you need to change the watchdog? The uTasker application is set to use it, and it gets reset when you go back to running a Teensyduino application, so no harm done.
    Hmm - after thinking on it, the watchdog status doesn't matter to me, but I would prefer to shut the LED off. I'll likely keep the watchdog in - as you said, it can't hurt.

    Quote Originally Posted by embedded-creations View Post
    What offset are you going to use? In case you didn't see it in my changes, if you remove the USE_MAINTENANCE definition the application gets much smaller.
    I'm not adding anything additional into the code, so I was going to keep the offset you came up with. I have a little dedicated data logger that would benefit greatly from being able to show up as a flash drive for data downloading, and this seems like a really easy to use solution.

    I did turn off USE_MAINTENANCE, saw a 50% decrease in the flash memory usage from that change.

    Quote Originally Posted by embedded-creations View Post
    I talked to Mark about posting my uTasker code on GitHub, and I'm pretty sure he doesn't want a full project including code that is copyright uTasker to go on GitHub. A patch file showing changes from a uTasker release would be fine. I don't have enough experience with patch files to know the best option here.
    Yes, I should have rephrased my statement above - I think it would be helpful for others to perhaps see (or even just describe) the changes needed to config.h to get this working for default pinouts, and perhaps a short snippet to detail how to change the pins. I'm out of my depth when working with a huge code base like the uTasker project; I wouldn't have made much progress myself if it were not for your diff. I'll certainly talk to Mark before putting anything at all up.

  19. #19
    Glad I could help!

  20. #20
    Senior Member
    Join Date
    Aug 2014
    Posts
    143
    I'm looking to create something very similar to this with uTasker.

    1. Program microcontroller in bootloader mode, either with USB-MSD (using now), or with SD CARD
    2. Able to access SD card to change files on 4gB SD card, delete/copy/paste files in Windows file explorer to SD card
    3. Go back out of bootloader/SD card mode and go to main Arduino application (revert to UART mode for USB port)

    Any ideas on how to accomplish this task? OR is jumping around from bootloader to SD CARD to Arduino Application the only way to do this?
    --would get very tedious to keep combining applications every time I want to test a small firmware change..
    ** can enter bootloader mode by holding a button down while power up, default otherwise always to main Arduino application
    *** if unable to combine bootloader mode with SD card, then maybe enter separate SD card program by holding different button on bootup, with default if no button held always back to main arduino program, no need to enter bootload or SD card mode until recycle power honestly.
    Last edited by zachtos; 07-10-2015 at 08:28 PM.

  21. #21
    I'm basically doing what you suggest with three separate applications. I don't know of a better way.

    You might have already seen this:
    https://github.com/pixelmatix/uTaskerBootWithArduinoApp

    It does a lot of what you're suggesting. Holding a button down to jump to the SD program from boot should be easy. Just change the application address from 0x8080 for the Arduino app to 0x38080 and use uTasker's jumpToApplication()

    Agreed it's tedious to do all that for a simple change, but the srec_cat scripts make it faster. I suggest doing development using a Teensy (or the Teensy Loader Chip) and not using the uTasker bootloader, then changing the linker script and test everything including the bootloader when you're done.

  22. #22
    Senior Member
    Join Date
    Aug 2014
    Posts
    143
    Is there a way to just combine the SD card loader and SD card USB_MSD capability into one program?

    Then just upload firmware updates via SD card loader instead of teensy loader?

    I want to develop with teensy but load with uTasker, and just need to add SD card support outside of the main application somehow.

  23. #23
    I asked Mark the same thing and he recommended not combining the two separate capabilities into one program.

  24. #24
    Senior Member
    Join Date
    Mar 2014
    Location
    Switzerland
    Posts
    109
    Zachtos

    I don't recommend USB-MSD to do firmware loading and SD card (memory stick) on the same interface due to the fact that this would involve having multiple LUMs (two disk drives appear to the PC) whereby one would be an emulated disk and the other would be the SD card.
    This is possible but complicated since each LUM would have to be handled totally differently - meaning a special USB-MSD interface to handle it (needing to be developed).

    The simplest solution is to configure the USB interface as a USB-MSD to SD card interface and also enable the SD card loader (also works with the SD card). Whilst in the loader mode the SD card will be visible as a memory stick type disk drive so files can be read, written, renamed, deleted etc. Also, new firmware can be copied to the card, with a specified name (or wildcard) at a specified location. The SD loader will search for this file at each reset and update the appliation if it is found (and is different - it can also automatically delete it after the update) and so you effecively have the full-featured USB-MSD on SD card operation, plus a firmware update capabilty thanks to the SD card loader.

    This won't involve any complication or new developments since it is just a configuration (just enable SD card and USB-MSD and use the USB-MSD interface task from the TaskerV1.4 project, rather than the emulated task of the serial loader).

    Regards

    Mark

  25. #25
    Senior Member
    Join Date
    Aug 2014
    Posts
    143
    Quote Originally Posted by uTasker View Post
    Zachtos

    I don't recommend USB-MSD to do firmware loading and SD card (memory stick) on the same interface due to the fact that this would involve having multiple LUMs (two disk drives appear to the PC) whereby one would be an emulated disk and the other would be the SD card.
    This is possible but complicated since each LUM would have to be handled totally differently - meaning a special USB-MSD interface to handle it (needing to be developed).

    The simplest solution is to configure the USB interface as a USB-MSD to SD card interface and also enable the SD card loader (also works with the SD card). Whilst in the loader mode the SD card will be visible as a memory stick type disk drive so files can be read, written, renamed, deleted etc. Also, new firmware can be copied to the card, with a specified name (or wildcard) at a specified location. The SD loader will search for this file at each reset and update the appliation if it is found (and is different - it can also automatically delete it after the update) and so you effecively have the full-featured USB-MSD on SD card operation, plus a firmware update capabilty thanks to the SD card loader.

    This won't involve any complication or new developments since it is just a configuration (just enable SD card and USB-MSD and use the USB-MSD interface task from the TaskerV1.4 project, rather than the emulated task of the serial loader).

    Regards

    Mark
    Excellent, this is exactly what I need. I will work and see if I can get a modified version of the uTaskerSerialLoader project running in VisualBasic10. I will post if I get it working, and update my license to the full cost version from the bootloader only version.
    Click image for larger version. 

Name:	Capture.JPG 
Views:	173 
Size:	22.8 KB 
ID:	4658
    Which of these should I select to start configuring in simulator?

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •