This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Getting hard fault when launching application from custom boot loader

I am building a custom boot loader to work with out application on a custom board based on the UBLOX NINA-302 module.  The boot loader will use USB as the only connection and that will use a USB driver we already developed for the application.  The idea is to use a simple boot loader without a soft device or MBR that will interface directly to our host application over USB.   The boot loader will start at 0x0 (FLASH_START=0x0) and a length of 0x10000 (FLASH_SIZE=0x10000).  The application is built in SES with FLASH_START set to offset address (0x10000) and FLASH_SIZE set to 0x20000.  The application was loaded into flash using J-Link before starting up the boot loader solution.

I am launching the application using the same funcitons that the Nordic boot loader wit some modifications specific to the implementation (files included below).  I have tried this with the standard "start_app' with optimization and also by replacing the function with an updated version I found on the developer blog.  The application seems to be starting up since I can track it using breakpoints up to "start_app" and then single set through the application code after the jump to the new reset handler.  I can single step through code but hit a hard fault whenever I let it free run.  The application has been stripped down to just blinky code with no interrupt service.  I even stripped the boot loader down to just the launch code but the application still crashes.  Any ideas?

/**
 * Copyright (c) 2016 - 2019, Nordic Semiconductor ASA
 *
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this
 *    list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form, except as embedded into a Nordic
 *    Semiconductor ASA integrated circuit in a product or a software update for
 *    such product, must reproduce the above copyright notice, this list of
 *    conditions and the following disclaimer in the documentation and/or other
 *    materials provided with the distribution.
 *
 * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
 *    contributors may be used to endorse or promote products derived from this
 *    software without specific prior written permission.
 *
 * 4. This software, with or without modification, must only be used with a
 *    Nordic Semiconductor ASA integrated circuit.
 *
 * 5. Any software provided in binary form under this license must not be reverse
 *    engineered, decompiled, modified and/or disassembled.
 *
 * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 */
#include <stdint.h>
#include "nrf.h"
#include "nrf_bootloader_app_start.h"
//#include "nrf_bootloader_info.h"
#include "nrf_log.h"
//#include "nrf_dfu_mbr.h"
#include "nrf_log_ctrl.h"

#include "g4_global_defs.h"

// Do the final stages of app_start. Protect flash and run app. See nrf_bootloader_app_start_final.c
void nrf_bootloader_app_start_final(uint32_t start_addr);

void nrf_bootloader_app_start(void)
{
//    uint32_t start_addr = MBR_SIZE; // Always boot from end of MBR. If a SoftDevice is present, it will boot the app.
    uint32_t start_addr = (uint32_t)FLASH_START_APP;
    NRF_LOG_DEBUG("Running nrf_bootloader_app_start with address: 0x%08x", start_addr);
    uint32_t err_code;

    // Disable and clear interrupts
    // Notice that this disables only 'external' interrupts (positive IRQn).
    NRF_LOG_DEBUG("Disabling interrupts. NVIC->ICER[0]: 0x%x", NVIC->ICER[0]);

    NVIC->ICER[0]=0xFFFFFFFF;
    NVIC->ICPR[0]=0xFFFFFFFF;
#if defined(__NRF_NVIC_ISER_COUNT) && __NRF_NVIC_ISER_COUNT == 2
    NVIC->ICER[1]=0xFFFFFFFF;
    NVIC->ICPR[1]=0xFFFFFFFF;
#endif

/* not using DFU for G4
    err_code = nrf_dfu_mbr_irq_forward_address_set();
    if (err_code != NRF_SUCCESS)
    {
        NRF_LOG_ERROR("Failed running nrf_dfu_mbr_irq_forward_address_set()");
    }
*/

    NRF_LOG_FLUSH();
    nrf_bootloader_app_start_final(start_addr);
}
/**
 * Copyright (c) 2016 - 2019, Nordic Semiconductor ASA
 *
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this
 *    list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form, except as embedded into a Nordic
 *    Semiconductor ASA integrated circuit in a product or a software update for
 *    such product, must reproduce the above copyright notice, this list of
 *    conditions and the following disclaimer in the documentation and/or other
 *    materials provided with the distribution.
 *
 * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
 *    contributors may be used to endorse or promote products derived from this
 *    software without specific prior written permission.
 *
 * 4. This software, with or without modification, must only be used with a
 *    Nordic Semiconductor ASA integrated circuit.
 *
 * 5. Any software provided in binary form under this license must not be reverse
 *    engineered, decompiled, modified and/or disassembled.
 *
 * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 */
#include "sdk_config.h"
#include "nrf_bootloader_app_start.h"
#include <stdint.h>
#include "nrf.h"
#include "nrf_peripherals.h"
//#include "nrf_bootloader_info.h"
//#include "nrf_dfu_types.h"
//#include "nrf_dfu_utils.h"
//#include "nrf_dfu_settings.h"
#include "nrf_assert.h"
#include "nrf_log.h"
#include "sdk_config.h"


/*
// Enabling the NRF_BOOTLOADER_READ_PROTECT define is untested.
// Read-protecting the bootloader requires certain functions to run from RAM.
// In GCC and SES this is done automatically when the define is enabled. You will
// get warnings which can be ignored.
// In Keil you must change project settings to run the entire file from RAM.
#ifndef NRF_BOOTLOADER_READ_PROTECT
#define NRF_BOOTLOADER_READ_PROTECT 0
#endif
*/


#define HANDLER_MODE_EXIT 0xFFFFFFF9 // When this is jumped to, the CPU will exit interrupt context
                                     // (handler mode), and pop values from the stack into registers.
                                     // See ARM's documentation for "Exception entry and return".
#define EXCEPTION_STACK_WORD_COUNT 8 // The number of words popped from the stack when
                                     // HANDLER_MODE_EXIT is branched to.


/**@brief Function that sets the stack pointer and link register, and starts executing a particular address.
 *
 * @param[in]  new_msp  The new value to set in the main stack pointer.
 * @param[in]  new_lr   The new value to set in the link register.
 * @param[in]  addr     The address to execute.
 */
#if defined ( __CC_ARM )
__ASM __STATIC_INLINE void jump_to_addr(uint32_t new_msp, uint32_t new_lr, uint32_t addr)
{
    MSR MSP, R0;
    MOV LR,  R1;
    BX       R2;
}
#else
/*
__STATIC_INLINE void jump_to_addr(uint32_t new_msp, uint32_t new_lr, uint32_t addr)
{
    __ASM volatile ("MSR MSP, %[arg]" : : [arg] "r" (new_msp));
    __ASM volatile ("MOV LR,  %[arg]" : : [arg] "r" (new_lr) : "lr");
    __ASM volatile ("BX       %[arg]" : : [arg] "r" (addr));
}
*/

//replacement to avoid optimization bug with above version
void jump_to_addr(uint32_t new_msp, uint32_t new_lr, uint32_t addr)
{
    __set_MSP(new_msp);
    ((void (*)(void))addr)();
}

#endif


/**@brief Function for booting an app as if the chip was reset.
 *
 * @param[in]  vector_table_addr  The address of the app's vector table.
 */
__STATIC_INLINE void app_start(uint32_t vector_table_addr)
{
    const uint32_t current_isr_num = (__get_IPSR() & IPSR_ISR_Msk);
    const uint32_t new_msp         = *((uint32_t *)(vector_table_addr));                    // The app's Stack Pointer is found as the first word of the vector table.
    const uint32_t reset_handler   = *((uint32_t *)(vector_table_addr + sizeof(uint32_t))); // The app's Reset Handler is found as the second word of the vector table.
    const uint32_t new_lr          = 0xFFFFFFFF;

    __set_CONTROL(0x00000000);   // Set CONTROL to its reset value 0.
    __set_PRIMASK(0x00000000);   // Set PRIMASK to its reset value 0.
    __set_BASEPRI(0x00000000);   // Set BASEPRI to its reset value 0.
    __set_FAULTMASK(0x00000000); // Set FAULTMASK to its reset value 0.

    ASSERT(current_isr_num == 0); // If this is triggered, the CPU is currently in an interrupt.

    // The CPU is in Thread mode (main context).
    jump_to_addr(new_msp, new_lr, reset_handler); // Jump directly to the App's Reset Handler.
}

/*
#if NRF_BOOTLOADER_READ_PROTECT
#ifdef __ICCARM__
__ramfunc
#elif  defined ( __GNUC__ ) || defined ( __SES_ARM )
__attribute__((noinline, long_call, section(".data")))
#elif  defined ( __CC_ARM )
#warning "Keil requires changes to project settings to run this file from RAM. Ignore this warning if configuration has been made."
#endif
#endif
ret_code_t nrf_bootloader_flash_protect(uint32_t address, uint32_t size, bool read_protect)
{
    if ((size & (CODE_PAGE_SIZE - 1)) || (address > BOOTLOADER_SETTINGS_ADDRESS))
    {
        return NRF_ERROR_INVALID_PARAM;
    }

#if defined(ACL_PRESENT)

    // Protect using ACL.
    static uint32_t acl_instance = 0;

    uint32_t const wmask  = (ACL_ACL_PERM_WRITE_Disable << ACL_ACL_PERM_WRITE_Pos);
    uint32_t const rwmask = wmask | (ACL_ACL_PERM_READ_Disable << ACL_ACL_PERM_READ_Pos);
    uint32_t const mask   = read_protect ? rwmask: wmask;

    do
    {
        if (acl_instance >= ACL_REGIONS_COUNT)
        {
            return NRF_ERROR_NO_MEM;
        }

        NRF_ACL->ACL[acl_instance].ADDR = address;
        NRF_ACL->ACL[acl_instance].SIZE = size;
        NRF_ACL->ACL[acl_instance].PERM = mask;

        acl_instance++;

    } while (NRF_ACL->ACL[acl_instance - 1].ADDR != address
          || NRF_ACL->ACL[acl_instance - 1].SIZE != size
          || NRF_ACL->ACL[acl_instance - 1].PERM != mask); // Check whether the acl_instance has been used before.

#elif defined (BPROT_PRESENT)

    // Protect using BPROT. BPROT does not support read protection.
    uint32_t pagenum_start = address / CODE_PAGE_SIZE;
    uint32_t pagenum_end   = pagenum_start + ((size - 1) / CODE_PAGE_SIZE);

    for (uint32_t i = pagenum_start; i <= pagenum_end; i++)
    {
        uint32_t config_index = i / 32;
        uint32_t mask         = (1 << (i - config_index * 32));

        switch (config_index)
        {
            case 0:
                NRF_BPROT->CONFIG0 = mask;
                break;
            case 1:
                NRF_BPROT->CONFIG1 = mask;
                break;
#if BPROT_REGIONS_NUM > 64
            case 2:
                NRF_BPROT->CONFIG2 = mask;
                break;
            case 3:
                NRF_BPROT->CONFIG3 = mask;
                break;
#endif
        }
    }

#endif

    return NRF_SUCCESS;
}
*/


#if NRF_BOOTLOADER_READ_PROTECT
#ifdef __ICCARM__
__ramfunc
#elif  defined ( __GNUC__ ) || defined ( __SES_ARM )
__attribute__((noinline, long_call, section(".data")))
#elif  defined ( __CC_ARM )
#warning "Keil requires changes to project settings to run this file from RAM. Ignore this warning if configuration has been made."
#endif
#endif
void nrf_bootloader_app_start_final(uint32_t vector_table_addr)
{
    ret_code_t ret_val;

/*
    // Protect MBR & bootloader code and params pages.
    if (NRF_BOOTLOADER_READ_PROTECT)
    {
        ret_val = nrf_bootloader_flash_protect(0, MBR_SIZE, NRF_BOOTLOADER_READ_PROTECT);
    }

    // Size of the flash area to protect.
    uint32_t area_size;

    area_size = BOOTLOADER_SIZE + NRF_MBR_PARAMS_PAGE_SIZE;
    if (!NRF_BL_DFU_ALLOW_UPDATE_FROM_APP && !NRF_BL_DFU_ENTER_METHOD_BUTTONLESS && !NRF_DFU_TRANSPORT_BLE)
    {
        area_size += BOOTLOADER_SETTINGS_PAGE_SIZE;
    }

    ret_val = nrf_bootloader_flash_protect(BOOTLOADER_START_ADDR,
                                           area_size,
                                           NRF_BOOTLOADER_READ_PROTECT);

    if (!NRF_BOOTLOADER_READ_PROTECT && (ret_val != NRF_SUCCESS))
    {
        NRF_LOG_ERROR("Could not protect bootloader and settings pages, 0x%x.", ret_val);
    }
    APP_ERROR_CHECK(ret_val);

    ret_val = nrf_bootloader_flash_protect(0,
                    nrf_dfu_bank0_start_addr() + ALIGN_TO_PAGE(s_dfu_settings.bank_0.image_size),
                    false);

    if (!NRF_BOOTLOADER_READ_PROTECT && (ret_val != NRF_SUCCESS))
    {
        NRF_LOG_ERROR("Could not protect SoftDevice and application, 0x%x.", ret_val);
    }
    APP_ERROR_CHECK(ret_val);
*/

    // Run application
    app_start(vector_table_addr);
}

Parents
  • I am confused by your post. You stated that you added LED controls to the bootloader and application code and both execute correctly but didn't state the operating condition.  Was this done by starting the bootloader and having it launch the application or was this done on each project in a stand alone manner?

  • Well, the application starts at 0x10000 right, so there is no way for that to run on its own. I did not modify the start address.

    I will send you the projects I used for testing, to see if there is any difference when you use those.

  • Did you actually change something in the project or the code (beyond adding the LED commands)?  This does seem to work now but I have a couple of issues:

    1.) adding a break point on the call to nrf_bootloader_app_start() results in a hard fault.  Why is that?

    2.) There seems to be some connection between calling functions before nrf_bootloader_app_start() and a hard fault result.  For example, a call to my CRC function to validate the application always results in a hard fault but replacing it with a simple query of a flag in flash memory (for example, the application size) seems to work all the time.

    3.) Are there any conditions on using the nrf_bootloader_app_start() call?

    Thank you

  • I commented out a few header files that was not included in the packets you provided, for instance crc.h in util.c and nvmem.c, and radio.h in mvmem.c.

    1. I'm not able to reproduce this. I just tested, and I hit the breakpoint on nrf_bootloader_app_start(), and I'm able to continue to a breakpoint on nrf_bootloader_app_start_final() which is hit twice before I get a HardFault. I assume this HardFault is expected as the bootloader have branched outside of the debugged application at this point.

    2. Do this happen with every functions, or just the CRC functions? Is the HardFault happening immediately, or when jumping to the application. Could this be related to that the application works with crc header commented out on my test applications?

    3. Not that I can think of, It should just take care of interrupt handling and then jump to the application.

  • I have resolved these issues and moved onto the full bootloader, which uses a USB driver based on one of your examples.  The bootloader is setup to reside in flash at 0x0000-0xFFFF (64 KB) and the application at 0x20000-0x3FFFF (128 KB).  I used this setup to test downloading the application into flash over USB and it worked correctly, including updating the CRC in a parameters block up at 0xFF000.  I then download a new boot loader using the emulator in SES and it seems to be placing some NRF functions in the SD space identified in the Nordic literature (below 0x27000).  I specifically noted that the USB driver did not function after programming flash, even though it was used in the image download.  The section placement macros were set for FLASH_START=0x0 and FLASH_SIZE=0x10000 so I would expect SES to force the boot loader image in that region. I resolved this by moving the application start up to 0x30000 (inside the region reserved for the application the Nordic memory map) but am concerned that I don't fully understand how the sections are placed in flash.   Is there another factor controlling the placement of these NRF functions in flash memory? Do I need to adhere to the Nordic memory map defined in the boot loader user guide?

Reply
  • I have resolved these issues and moved onto the full bootloader, which uses a USB driver based on one of your examples.  The bootloader is setup to reside in flash at 0x0000-0xFFFF (64 KB) and the application at 0x20000-0x3FFFF (128 KB).  I used this setup to test downloading the application into flash over USB and it worked correctly, including updating the CRC in a parameters block up at 0xFF000.  I then download a new boot loader using the emulator in SES and it seems to be placing some NRF functions in the SD space identified in the Nordic literature (below 0x27000).  I specifically noted that the USB driver did not function after programming flash, even though it was used in the image download.  The section placement macros were set for FLASH_START=0x0 and FLASH_SIZE=0x10000 so I would expect SES to force the boot loader image in that region. I resolved this by moving the application start up to 0x30000 (inside the region reserved for the application the Nordic memory map) but am concerned that I don't fully understand how the sections are placed in flash.   Is there another factor controlling the placement of these NRF functions in flash memory? Do I need to adhere to the Nordic memory map defined in the boot loader user guide?

Children
  • I sendt you a PM regarding the project. Please let me know if you need further assistance with this and can provide the requested project.

  • So I sent you the project files this morning in a private message but have some questions:

    1.) My application does not use an soft devices and I am running ESB for my wireless protocol.  My plan is to write a simple boot loader that passes to the application using nrf_bootloader_app_start() with the vector table address changed to my application load address.  Does this require a MBR? Is the MBR automatically inserted into a code load when running SES?  If it does require an MBR where can I find detailed information on how to use it (please be specific)?

    2.) Recently I wrote the application into flash with SES, switched to the boot loader and wrote it to memory.  With this setup my code seemed to work until I erased all flash and tried to repeat the operation.  After that point I could not get the application to launch from the boot loader (getting hard error).  This suggests to me that the successful application boot was using something that was erased in the chip erase operation. I had previously been working with the application in a standard development environment (loaded at 0x0) so there was code in there that was obviously being used to run the application.  Any idea how this might have worked?

    3.) When attempting to launch the application from the bootloader, I can follow execution from the application interrupt vector for a period of time but the it hits a hard fault whenever I let it free run.  I suspect this is caused by a Nordic library module (USBD perhaps or ESB) that has an invalid jump address due to an incorrect SES build configuration.  What is the correct procedure to configure SES to generate an image with a starting address other than 0x0?  Do I need to allocate the flash memory range for soft devices to support Nordic library usage even though I am not using a soft device?

    4.) The DFU module literature talks about using nrfprog to process an application for download into the Nordic flash memory allocation scheme.  Is nrfprog remapping the application to the target address as part of this processing?

  • Hi,

    I ran your projects and they seems to run correctly until I hit a HardFault inside nrf_drv_clock_hfclk_request() in sys_init/init_power_clock. I tracked this down to the CRITICAL_REGION_EXIT() macro at the end of the function, and specifically the call to __enable_irq(). The debugger reports that the application is in the Hardfault_Handler in the bootloader. Are you seeing the same problem, or are you able to pass this function call in the application? I would need to look some more into why this is happening.

    henryh said:
    1.) My application does not use an soft devices and I am running ESB for my wireless protocol.  My plan is to write a simple boot loader that passes to the application using nrf_bootloader_app_start() with the vector table address changed to my application load address.  Does this require a MBR? Is the MBR automatically inserted into a code load when running SES?  If it does require an MBR where can I find detailed information on how to use it (please be specific)?

    The MBR is used for jumping to the bootloader (which is normally placed at the end of flash), and together with the softdevice. I cannot see any reasons that you should need it for your use-case. The MBR is a separate hex-file, it will not be merged with the application during build/flashing. The softdevice hex-files includes the MBR, but it is also available as a standalone hex-file for use with other bootloaders. Some SES projects are configured to flash the MBR hex-file along with the application (see Debug > Loader > Additional Load File[0]), but this is not the case with the projects you are using.

    henryh said:
    2.) Recently I wrote the application into flash with SES, switched to the boot loader and wrote it to memory.  With this setup my code seemed to work until I erased all flash and tried to repeat the operation.  After that point I could not get the application to launch from the boot loader (getting hard error).  This suggests to me that the successful application boot was using something that was erased in the chip erase operation. I had previously been working with the application in a standard development environment (loaded at 0x0) so there was code in there that was obviously being used to run the application.  Any idea how this might have worked?

    That sounds very strange, I would not think that any code outside the written bootloader/application areas should run. I have not seen this behavior with the projects you uploaded.

    henryh said:
    3.) When attempting to launch the application from the bootloader, I can follow execution from the application interrupt vector for a period of time but the it hits a hard fault whenever I let it free run.  I suspect this is caused by a Nordic library module (USBD perhaps or ESB) that has an invalid jump address due to an incorrect SES build configuration.  What is the correct procedure to configure SES to generate an image with a starting address other than 0x0?  Do I need to allocate the flash memory range for soft devices to support Nordic library usage even though I am not using a soft device?

    I do not have a lot of experience with other setups than the one used by the SDK (MBR/softdevice in start of flash, bootlaoder at end of flash), but in theory it should just be to move the application start address and provide the correct address in the booloader. I'm not sure how ESB or USBD should be able to perform such a jump, that must be related to some interrupt handling or something similar. Changing the "Section Placement Macros" option should be sufficient to move the application in flash. 

    henryh said:
    4.) The DFU module literature talks about using nrfprog to process an application for download into the Nordic flash memory allocation scheme.  Is nrfprog remapping the application to the target address as part of this processing?

    Can you provide an exact link to where you read this? I'm not aware of any such features in nrfjprog. DFU are normally handled by nrfutil.

    Best regards,
    Jørgen

  • I have resolved this issue by including the MBR in the firmware load, using it as a bootstrap to bring up my boot loader.  My boot loader starts at 0x1000 so the MBR jumps into it directly after running.  My bootloader uses a modified  nrf_bootloader_app_start module to launch my application.  After discovering that interrupts were causing erratic behavior I was able to determine that the MBR would solve this using "interrupt forwarding".  It required some digging but I was finally able to find detailed information on the MBR boot process in the DevZone and was able to assemble the various modifications required for my needs.  This is up and running now with full interrupt support and I ma moving onto other issues.  Thank you for your help.

Related