12 Replies Latest reply on Sep 9, 2019 6:37 AM by KyTr_1955226

    What happened to the C# .NET PSoC UART bootloader?

    KyTr_1955226

      Hi everyone, can someone clear up something for me regarding the C# .NET UART Bootloader?

       

      I make lots of use of the UART Bootloader, but now it's appeared to have disappeared from the Cypress site.  Something about compatibility problems?  Is anyone able to elaborate on what exactly the problem is?

       

      For whatever reason, my customized UART Bootloader project for C# .NET is now refusing to bootload, always throwing a timeout exception.  Even when I use the old unmodified version of the program (sending my "Enter Bootloader" command from a terminal) it still gives me the same error code.

       

      This is a big problem, as I've built a custom application built off the old AN68272 project that I send to customers to load new firmware in the field, and now it suddenly no longer works.

       

      However I did find that if I use the Bootloader Host built into Creator 4.1, it works just fine.  I send my serial command to have the firmware call Bootloadable_Load() through a terminal, open up the Creator 4.1 Bootloader Host and it loads via UART with no trouble.  The target project bootloader component version is 1.60.

       

      Asking our customers to download and install PSoC Creator isn't really an ideal option.  I'd like to get my application up and running again.  I just want to know what the problem actually is before digging in there. Do I just build a new bootloader_utils library?  If this is the case, isn't the bootloader host in creator using the same bootloader_utils since I built mine with presumably the same source (located at PSoC Creator\4.1\PSoC Creator\cybootloaderutils)?  If so why is it working there but not in my application?

       

      Am I just way off base with all of this?

       

      I attached my project source code for the UART Bootloader Host (It's mostly the one that used to be available from AN68272 modified to send a command to enter the bootloader).  What needs changing to get this up and running again?

       

      EDIT:

      I just re-built bootloader_utils.dll using the source files in the Creator 4.2 directory.

      I now get an exception thrown when I attempt to call Bootload_Utils.CyBtldr_Program():

       

      int result = Bootload_Utils.CyBtldr_Program(Chosen_File_Cyacd, ref comm_data, update);

      System.AccessViolationException: 'Attempted to read or write protected memory. This is often an indication that other memory is corrupt.'

       

      So something is going wonky in there.

        • 1. Re: What happened to the C# .NET PSoC UART bootloader?
          GeonaP_26

          C# based Custom Bootloader host application previously shared along with AN68272 is not compatible with the latest PSoC Creator versions. However, the user can still follow the same approach to build the custom bootloader host tool using the bootloader API modules available as part of PSoC Creator installation:  \ PSoC Creator \ <version> \ PSoC Creator \ cybootloaderutils. For more details, please refer to the section: 5.2 Create the Bootloader Host Application in AN73503 - PSoC USB HID Bootloader.

           

          Could you test the legacy C# based custom bootloader application with PSoC Creator 3.3?

          Are you observing time out exception after calling Bootloadable_Load() from application project?

          • 2. Re: What happened to the C# .NET PSoC UART bootloader?
            KyTr_1955226

            Yes the timeout is after Bootloadable_Load() was called from the application.  I have a status LED that blinks at 1Hz in the application.  When it stops blinking I know I entered the bootloader.

             

            From the bootloader host:

                                serialPort.Open();
                                serialPort.Write("RESET\r\n");      //PSoC Calls Bootloadable_Load() upon reception of this command
                                serialPort.Close();                 //Free up port for bootloader proper
                                textBox_StatusLog.Text += " Bootload Started at " + DateTime.Now.ToLongTimeString() + "\r\n";
                                Thread.Sleep(500);                  //Delay to ensure we have had enough time to enter bootloader
                                this.Refresh();                     //Refresh UI
            
                                if (backgroundWorker.IsBusy != true)
                                {
                                    backgroundWorker.RunWorkerAsync();  //Begin bootload on seperate thread
                                }
            

             

            private void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
                    {
                        /* Exception occuring here will be passed as e.Error to _RunWorkerCompleted event handler */
                        Bootload_Utils.CyBtldr_ProgressUpdate update = new Bootload_Utils.CyBtldr_ProgressUpdate(ProgressUpdate);
                        e.Result = Bootload_Utils.CyBtldr_Program(Chosen_File_Cyacd, ref comm_data, update);
                    }
            

             

            What actually changed that has rendered this incompatible?  This was all working not even 4 months ago.

            We've been using Creator 4.1 and the UART Custom Bootloader Host with no issues for well over a year at this point.

             

            Also, if I send my Enter Bootloader command manually from a terminal and bootload via the host built into Creator 4.1/4.2 it all works perfectly fine.  What's the difference between that and the C# application?

             

            Could you test the legacy C# based custom bootloader application with PSoC Creator 3.3?

            How exactly do you mean?  Do you mean with my PSoC Firmware/Bootloader built in Creator 3.3?  With Bootloader_Utils.dll built from the source files included with Creator 3.3?

            • 3. Re: What happened to the C# .NET PSoC UART bootloader?
              KyTr_1955226

              Some additional information:

               

              I hooked a digital logic analyzer to the serial lines for a bootload attempt that gives a timeout error  This is using Bootloader v1.60 and the bootload_utils.dll from Creator 4.1.  Here's what I found:

               

              Entire transmission:

              Capture Timeout.JPG

              The capture begins at my "RESET" (Enter Bootloader) command.  I then get two commands from the bootloader host and two responses from the PSoC Bootloader:

               

              Host Command 1:

              Host 1.JPG

               

              PSoC Response 1:

              PSoC 1.JPG

               

              Host Command 2:

              Host 2.JPG

               

              PSoC Response 2:

              PSoC 2.JPG

               

              Past this I receive nothing more on the lines.

               

              Looks like the Host Command 2 is the culprit?  0x33 is the command for "Get Application Status", which looks to be for Dual Application bootloader only.

              The PSoC is responding with 0x05 - ERR_CMD, since this is a single application bootloader.

               

              So the question is now why is it sending this command in the first place?  Am I missing a way to have the host skip the "Get Application Status" command?

               

              Like I said before, the bootload process works if I use the host built into Creator 4.1.  It is not sending the 0x33 Get Application Status command:

               

              After my "RESET" command - Host Command 1 (0x38 - Enter Bootloader):

               

              PSoC Response (0x00 - SUCCESS):

               

              Host Command 2 (0x32 - Get Flash Size):

               

              PSoC Response (0x00 - SUCCESS):

               

              Host Command 3 (0x37 - Send Data):

               

              And then we proceed from there, sending the data from the host.

               

              I also tried building bootloader_utils.dll from the Creator 3.3 source files, but attempts to use any version of the dll other than the one that came with the old C# UART Sample Project throws an exception:

              Attempted to read or write protected memory. This is often an indication that other memory is corrupt.

              • 4. Re: What happened to the C# .NET PSoC UART bootloader?
                KyTr_1955226

                The tale deepens....

                 

                I decided to look into this "Get Application Status" setting.  According to the datasheet this is only to be used with Dual-Application Bootloader.

                 

                I took a look at my bootloader component in the PSoC project:

                 

                Note how Get Application Status is checked, while Dual Application bootloader is unchecked.  I checked Dual-application bootloader to unlock the Get Application Status box, unchecked Get Application Status, and now I am loading with no issue (with the original bootload_utils.dll that came with the C# .NET Example).

                 

                If I'm not mistaken, if Dual Application bootloader is unselected, Get Application Status should not be checked.  Could there potentially be a bug with that box being treated as default-checked even when Dual-Application bootloader is unchecked?  At least until the user unchecks it manually?

                 

                It's also odd, now that I did this, even if I undo it (re-check Get Application Status) and rebuild the project, I am still able to load with no problems. 

                 

                How is this setting communicated to the bootloader host?  is it reading the loaded-in .cyacd file for this setting?  Or is it somehow querying it off the target PSoC before loading?

                 

                Thoughts?

                 

                EDIT:

                I think this is just a red herring, changing "Get Application Status" does not change anything in the hex or cyacd files so long as Dual-Application is not selected.

                • 5. Re: What happened to the C# .NET PSoC UART bootloader?
                  GeonaP_26

                  The latest cybootloaderutils API modules are updated to support new features and devices. The legacy C# Bootloader Host application is not guaranteed to work with the latest bootloader utils.

                   

                  • Get Application Status (0x33) is a Dual-application bootloader only command. So the bootloader host should not send this command for a single application bootloader. Please refer to Bootloader component datasheet for more details.

                  • Once you enable the Get Application Status in the Bootloader configuration window, the correponding code will be enabled in the Bootloader project to prepare the valid response.
                  • PSoC Creator Bootloader Host sends this command only if Active Application is configured to be Image 1 or Image 2. You can follow this approach in your custom bootloader host project as well. There is only one application in the case of Single Application Bootloader. Hence, 'Active Application' should be always 'No Change' for the Single application Bootloader.

                   

                  How exactly do you mean?  Do you mean with my PSoC Firmware/Bootloader built in Creator 3.3?  With Bootloader_Utils.dll built from the source files included with Creator 3.3?

                  Instead of PSoC Creator 4.x, please use cybootloaderutils available as part of PSoC Creator 3.3 to build the custom bootloader host.

                  • 6. Re: What happened to the C# .NET PSoC UART bootloader?
                    KyTr_1955226

                    Instead of PSoC Creator 4.x, please use cybootloaderutils available as part of PSoC Creator 3.3 to build the custom bootloader host.

                    I have tried this, but there's probably something wrong with the build or something because it doesn't event begin sending commands when I attempt to use it.  It just throws the following when I call CyBtldr_Program:

                    Attempted to read or write protected memory. This is often an indication that other memory is corrupt.

                    [EDIT]  I have attached the BootloadUtils project using the source from Creator 3.3.  I am using it with the customized C# UART Bootloader Host application I posted earlier.  The exception is being thrown inside CyBtldr_StartBootloadOperation on

                    err = g_comm->OpenConnection();

                     

                    The only copy of the host library that seems to work for me is the one that came with the C# UART Bootloader Host.  It has a created date of June 15, 2017, which would coincide w/ when Creator 4.1 released.

                     

                    PSoC Creator Bootloader Host sends this command only if Active Application is configured to be Image 1 or Image 2. You can follow this approach in your custom bootloader host project as well. There is only one application in the case of Single Application Bootloader. Hence, 'Active Application' should be always 'No Change' for the Single application Bootloader.

                    I understand this, but I don't see how this is set on the host side in a custom application.  Where is this setting changed?  Because it looks like it automatically determines if this command should be sent based on the cyacd file that is loaded into the host application.

                     

                    [EDIT] I have confirmed this theory.  It looks like this is something to do with the cyacd file being used.  I tried another cyacd and had no problems loading (and no 0x33 command is ever sent), but when attempting to load a different cyacd file, 0x33 is sent and the process fails.

                     

                    What's strange is that these two cyacd files I used SHOULD be identical code, but one is significantly different from the other.  The one I built several months ago refuses to load unless through the Host inside Creator.  In the custom application it always fails on the response to the 0x33 command.  I just built what should be an identical cyacd and it loads no problem.  Like I said though, the two files are significantly different.  Unfortunately I built this PSoC project long enough ago I haven't a clue why the hex is so different (I wonder if maybe I changed compiler settings or something and just don't recall).  I'm not sure what could have changed in the project to trick the cyacd parser into thinking 0x33 should be sent.

                    • 7. Re: What happened to the C# .NET PSoC UART bootloader?
                      BiBi_1928986

                      Hello KyTr.

                       

                      I wish I had your debugging skills (and your logic analyzer).

                       

                      Just a shot in the dark...

                      Have you tried a build in 'debug' and in 'release'?  I know this always makes my cyacd files significantly different (I'm sure you already know this).  I can't see how this would cause (or not cause) the 0x33 command.  But hey, strange things can happen with Creator.

                       

                      Keep plugging away.

                       

                      Bill

                      • 8. Re: What happened to the C# .NET PSoC UART bootloader?
                        KyTr_1955226

                        Hi Bill,

                         

                        I had actually thought of that, and tried a debug build to see if it would line things up, but no dice unfortunately.

                         

                        I must have changed something in the build settings or updated components and I just don't remember it (this was built several months ago).

                        I have a couple #defines that communicate the Firmware Version, Revision, and Build Date and I found them in the cyacd that isn't bootloading, so I can at least have a little confidence that they are in fact the same project and I didn't just accidentally use the wrong firmware.  I just was a little weirded out by the hex changing so drastically between builds.

                         

                        Anyway, I think the question now is what is forcing the bootloader host to send an Application Status command.  From what I can see in the cybootloadutils source code I think this is interesting:

                         

                        int RunAction_v0(CyBtldr_Action action, uint32_t lineLen, uint8_t* line, uint8_t appId,
                            const uint8_t* securityKey, CyBtldr_CommunicationsData* comm, CyBtldr_ProgressUpdate* update)
                        {
                            const uint8_t INVALID_APP = 0xFF;
                            uint32_t blVer = 0;
                            uint32_t siliconId = 0;
                            uint8_t siliconRev = 0;
                            uint8_t chksumtype = SUM_CHECKSUM;
                            uint8_t isValid;
                            uint8_t isActive;
                            int err;
                            uint8_t bootloaderEntered = 0;
                        
                        
                            err = CyBtldr_ParseHeader(lineLen, line, &siliconId, &siliconRev, &chksumtype);
                        
                            if (CYRET_SUCCESS == err)
                            {
                                CyBtldr_SetCheckSumType(chksumtype);
                        
                                err = CyBtldr_StartBootloadOperation(comm, siliconId, siliconRev, &blVer, securityKey);
                                bootloaderEntered = 1;
                        
                                appId -= 1; /* 1 and 2 are legal inputs to function. 0 and 1 are valid for bootloader component */
                                if (appId > 1)
                                {
                                    appId = INVALID_APP;
                                }
                        
                                if ((CYRET_SUCCESS == err) && (appId != INVALID_APP))
                                {
                                    /* This will return error if bootloader is for single app */
                                    err = CyBtldr_GetApplicationStatus(appId, &isValid, &isActive);
                        
                                    /* Active app can be verified, but not programmed or erased */
                                    if (CYRET_SUCCESS == err && VERIFY != action && isActive)
                                    {
                                        /* This is multi app */
                                        err = CYRET_ERR_ACTIVE;
                                    }
                                }
                            }
                        
                            while (CYRET_SUCCESS == err)
                            {
                                if (g_abort)
                                {
                                    err = CYRET_ABORT;
                                    break;
                                }
                        
                                err = CyBtldr_ReadLine(&lineLen, line);
                                if (CYRET_SUCCESS == err)
                                {
                                    err = ProcessDataRow_v0(action, lineLen, line, update);
                                }
                                else if (CYRET_ERR_EOF == err)
                                {
                                    err = CYRET_SUCCESS;
                                    break;
                                }
                            }
                        
                            if (err == CYRET_SUCCESS)
                            {
                                if (PROGRAM == action && INVALID_APP != appId)
                                {
                                    err = CyBtldr_GetApplicationStatus(appId, &isValid, &isActive);
                        
                                    if (CYRET_SUCCESS == err)
                                    {
                                        /* If valid set the active application to what was just programmed */
                                        /* This is multi app */
                                        err = (0 == isValid)
                                            ? CyBtldr_SetApplicationStatus(appId)
                                            : CYRET_ERR_CHECKSUM;
                                    }
                                    else if (CYBTLDR_STAT_ERR_CMD == (err ^ (int)CYRET_ERR_BTLDR_MASK))
                                    {
                                        /* Single app - restore previous CYRET_SUCCESS */
                                        err = CYRET_SUCCESS;
                                    }
                                }
                                else if (PROGRAM == action || VERIFY == action)
                                {
                                    err = CyBtldr_VerifyApplication();
                                }
                                CyBtldr_EndBootloadOperation();
                            }
                            else if (CYRET_ERR_COMM_MASK != (CYRET_ERR_COMM_MASK & err) && bootloaderEntered)
                            {
                                CyBtldr_EndBootloadOperation();
                            }
                            return err;
                        }
                        

                         

                        Lines 68 and 78 are my concern here.  If this is to be believed, the 0x33 command should be sent every time I start loading, and if the bootloader responds with an error code, it should basically ignore it and treat it as single application so long as the packet it sent back to the host was a valid packet (see below):

                         

                        int CyBtldr_GetApplicationStatus(uint8_t appID, uint8_t* isValid, uint8_t* isActive)
                        {
                            uint32_t inSize = 0;
                            uint32_t outSize = 0;
                            uint8_t inBuf[MAX_COMMAND_SIZE];
                            uint8_t outBuf[MAX_COMMAND_SIZE];
                            uint8_t status = CYRET_SUCCESS;
                            int err;
                        
                            err = CyBtldr_CreateGetAppStatusCmd(appID, inBuf, &inSize, &outSize);
                            if (CYRET_SUCCESS == err)
                                err = CyBtldr_TransferData(inBuf, inSize, outBuf, outSize);
                            if (CYRET_SUCCESS == err)
                                err = CyBtldr_ParseGetAppStatusCmdResult(outBuf, outSize, isValid, isActive, &status);
                            else if (CyBtldr_TryParseParketStatus(outBuf, outSize, &status) == CYRET_SUCCESS)
                                err = status | CYRET_ERR_BTLDR_MASK; //if the response we get back is a valid packet override the err with the response's status
                        
                            if (CYRET_SUCCESS == err)
                            {
                                if (CYRET_SUCCESS != status)
                                    err = status | CYRET_ERR_BTLDR_MASK;
                            }
                        
                            return err;
                        }
                        

                         

                        Of course the version of the Bootload_Utils library that came with the C# UART Bootloader, when it works, doesn't seem to send 0x33 at all.  It sends 0x38, 0x32, then proceeds to loading.  So there must be a way to skip this code block entirely that I'm perhaps just not seeing?  It almost seems like it should be using RunAction_v1 (which doesn't even check AppStatus) instead of RunAction_v0?

                         

                        First thing I'd like to try is just removing this AppStatus check (or just force it to come back with the proper status).  Of course this is rather hard to test and tweak when every time I try to use a library that I built myself I can't even get to this point.  It just throws an Access Violation Exception when it tries to call OpenConnection() for some reason.  Does anyone know if there are potential issues building bootload_utils in Visual Studio 2019/Windows SDK 10?  Maybe I need to dig up an older version of VS/Windows SDK for it to build correctly?

                        • 9. Re: What happened to the C# .NET PSoC UART bootloader?
                          GeonaP_26

                          If you send Get Application Status Command (0x33) to a single application bootloader, it will send Bootloader_ERR_CMD(0x05u) error. Note that PSoC Creator 4.x based cybootloaderutils exits bootloading if this error is received. However, PSoC Creator 3.3 proceeds to next step even if 0x33 command receives failure from a single application bootloader. Please confirm whether you are observing the same.

                          • 10. Re: What happened to the C# .NET PSoC UART bootloader?
                            KyTr_1955226

                            I'm not quite observing the same thing.

                             

                            In my case it seems to be the cyacd that I load in that determines if Application Get Status command is sent.  I have attached the working/non-working cyacd to this post.

                             

                            Unfortunately I do not know the version of cybootloaderutils that the dll I'm using (that's working) is built from.  It's the one that came with the old download for the C# Bootloader Host Application.  I have attached it to this post.  Maybe there's a way to determine the version that I'm not aware of?  Like I've said, any attempts by me to build and use a new version results in the library throwing an access violation when it tries to call the OpenConnection():

                             

                            Attempted to read or write protected memory. This is often an indication that other memory is corrupt.

                            at

                            CyBtldr_StartBootloadOperation()

                            at line

                            err = g_comm->OpenConnection();

                             

                            This occurs regardless of if I'm using cybootloaderutils built from the Creator 3.3/4.1/4.2 source.  I'm assuming this has something to do with my project or build settings.  Do I need a specific Windows SDK or Platform Toolset version?  I am using 10.0 and v142 (Visual Studio 2019) respectively.

                            • 11. Re: What happened to the C# .NET PSoC UART bootloader?
                              GeonaP_26

                              Are you building the VS project for any CPU? Please change to x86 platform as explained here and let me know if it helps: https://stackoverflow.com/questions/4074585/attempted-to-read-or-write-protected-memory-this-is-often-an-indication-that…

                              • 12. Re: What happened to the C# .NET PSoC UART bootloader?
                                KyTr_1955226

                                Yes I am building the application for x86 and bootloadutils.dll for Win32