Cómo programar microcontroladores multinúcleo



Durante los últimos diez años, los procesadores de casi todos nuestros dispositivos se han convertido en multinúcleo. Les siguen microcontroladores multinúcleo. En los catálogos de los principales fabricantes, ya puedes encontrar microcontroladores de uso general con múltiples núcleos a precios razonables. Por lo tanto, parece que es hora de comenzar a usar microcontroladores de múltiples núcleos en sus propios dispositivos. Por supuesto, en los casos en que esté justificado.



. , . , . . .



-. ARM Cortex M NXP (LPC), STMicroelectronics Infineon (Cypress).





, .



  • . , , . - , , .
  • . ( , , ), . , ( Cortex M0) (, Cortex M4). , . , .
  • . , . , . , , . .




.



. . . .



, (Master Core). . , (Slave Core), , reset. . System Control ( ).





, . . .



, , . , (Cortex M0), , (Cortex M4 / M7).





, . , – , . . . , .





, . (, LPC55S6x Cypress CY8C6xx5) . . (bus matrix). , . , , .







, STM32H747. , . , . .







, . , . , , . , , .



, , . , .



. . () FLASH- SRAM. . .



, (AHB1, AHB2, APB1, APB2…). , , «» .







(NVIC). . , , , NVIC. , NVIC . , : , , / . , , . , GPIO , , , .







. -. STM32 Hardware Semaphore (HSEM), NXP – Inter-CPU mailbox, Cypress – Inter-Processor Communication Block (IPC). , .



. « » (mailbox). , . NVIC . , , , - ( ).





– , . . . , , . , . , . , , . , . , . .





. .





. (Debug Access Port). - . ( ) . . .







. , , .



LPC55S69-EVK NXP LPC55S69, Cortex M33. IAR Embedded Workbench 8. , , . , .





CMSIS. . , .



0



. CPU0.



.



  1. C: Project > Create New Project. C / main. , 0, . CPU0.
  2. : File > Save Workspace.
  3. General Options > Target .

    : , , .

  4. General Options > Library Configuration Use CMSIS.
  5. (C/C++ Compiler > Preprocessor) : < SDK>\devices\LPC55S69. Defined symbols CPU_LPC55S69JBD100_cm33_core0 ( , ).
  6. Linker > Config Override default LPC55S69_cm33_core0_flash.icf SDK ( < SDK>\devices\LPC55S69\iar).
  7. Debugger > Setup (Driver) CMSIS DAP.
  8. , Debugger > Download Verify Download Use flash loader(s).
  9. system_LPC55S69_cm33_core0.c startup_LPC55S69_cm33_core0.s ( < SDK>\devices\LPC55S69 < SDK>\devices\LPC55S69\iar ). , .
  10. , GPIO1_7.





    #include "LPC55S69_cm33_core0.h"
    
    #define LED_GPIO_BLOCK 1
    #define LED_GPIO_PIN 7
    
    static inline void Delay(void)
    {
     for(int i = 0; i < 8000000; i++);
    }
    
    int main()
    {  
     /**** LED setup ****/
     // Enable clocking for GPIO1 (located on AHB bus)
     SYSCON->AHBCLKCTRLX[0] |= SYSCON_AHBCLKCTRL0_GPIO1_MASK;
    
     // Set direction for GPIO1 7 as output
     GPIO->DIR[LED_GPIO_BLOCK] |= GPIO_DIR_DIRP(1 << LED_GPIO_PIN);
    
     while(1)
     {
       /**** LED blinking ****/
       GPIO->B[LED_GPIO_BLOCK][LED_GPIO_PIN] = 0;  // Turn led On
       Delay();
       GPIO->B[LED_GPIO_BLOCK][LED_GPIO_PIN] = 1;  // Turn led off
       Delay();
     }
    }


  11. , , , .


1



, . . , .



, 3, 5, 6, 9, 10 core0 core1.



, , , GPIO1_4:



#define LED_GPIO_PIN 7  -->  #define LED_GPIO_PIN 4


. … Reading CPU status failed.





, , LPC55S69 . 0 , 1 — . 1 0 :



  • 1.
  • , 1 .
  • 1.
  • reset 1.


0 :





// Sequence required to be written
// to SYSCON->CPUCTRL register ORed with other bits
// to applay settings
// See UM11126 4.5.70 for more details
#define SYSCON_CPUCTRL_ENABLING_SEQ 0xC0C40000

// Warning!!! IAR specific code. 
// core1_image_start is defined in 
// LPC55S69_cm33_core0_flash.icf linker config file
extern unsigned char core1_image_start[];
#define CORE1_IMAGE_START core1_image_start


main() 1:



/**** CPU1 (slave) setup ****/
// Enable CPU1
SYSCON->CPUCFG |= SYSCON_CPUCFG_CPU1ENABLE_MASK;

// Setup firmware boot address
SYSCON->CPBOOT = SYSCON_CPBOOT_CPBOOT(CORE1_IMAGE_START);

// Enable clock and reset CPU1
SYSCON->CPUCTRL = SYSCON->CPUCTRL | SYSCON_CPUCTRL_ENABLING_SEQ | 
                  SYSCON_CPUCTRL_CPU1RSTEN_MASK | SYSCON_CPUCTRL_CPU1CLKEN_MASK;

// Release reset for CPU1
SYSCON->CPUCTRL = (SYSCON->CPUCTRL | SYSCON_CPUCTRL_ENABLING_SEQ) & 
                  (~SYSCON_CPUCTRL_CPU1RSTEN_MASK);


, 0.



1 . .





. . .



, :



  1. ( 1).
  2. . Converter > Output, Generate Additional Output Raw binary.

  3. Debugger > Download Verify Download. .

  4. .
  5. ( 0).
  6. Debugger > Multicore, Simple .



  7. Linker > Input . ( ). _CPU1_image, , 1, __sec_core 4.



  8. . , . , .







    IAR , .







Failed to synch with multicore partner, . CPU1 CPU0.







The debugging session could not be started.
Either the debugger initialization filed, or else the file "iar_all_modules_loaded" was missing, corrupt or of an unsupported format.




, Verify download 3. , , .



: , , , , . . , 6 7. ( , ), , , . , .



SRAM



FLASH-. . . SRAM. FLASH-, SRAM . :



  1. ( 1).
  2. (Linker > Config) LPC55S69_cm33_core1_flash.icf LPC55S69_cm33_core1_ram.icf.
  3. .
  4. ( 0).
  5. main.c:



    • #include "string.h" // for memcpy.
    • SRAM, 1.



      // Address of RAM, where the image for CPU1 should be copied
      // According to UM11126 2.1.5 it is SRAM 3 on CM33 data bus
      #define CORE1_BOOT_ADDRESS (void *)0x20033000
    • .



      // Firmware image size calculation
      uint32_t get_core1_image_size(void)
      {
        uint32_t core1_image_size;
      #pragma section = "__sec_core"
        core1_image_size = (uint32_t)__section_end("__sec_core") - 
                           (uint32_t)&core1_image_start;
        return core1_image_size;
      }
  6. 1 FLASH- SRAM.



    //  Copy CPU1 image to an other SRAM block
    memcpy(CORE1_BOOT_ADDRESS, (void *)CORE1_IMAGE_START, get_core1_image_size());
  7. ( , ).



    // Setup boot address
    SYSCON->CPBOOT = SYSCON_CPBOOT_CPBOOT(CORE1_BOOT_ADDRESS);
  8. 0, , .


, ( 2 7 ).





, . - MAILBOX.



MAILBOX, . .



/**** Mailbox setup for mutex ****/
// Enable mailbox clocking
SYSCON->AHBCLKCTRLX[0] |=  SYSCON_AHBCLKCTRL0_MAILBOX_MASK;


- , , .



— , . .



// Try to acquire mutex
while (!(MAILBOX->MUTEX & MAILBOX_MUTEX_EX_MASK));


.



// Release mutex
MAILBOX->MUTEX = MAILBOX_MUTEX_EX_MASK;


.



, .





.



0 ( )
#include "LPC55S69_cm33_core0.h"
#include "string.h"  // for memcpy

#define LED_GPIO_BLOCK 1
#define LED_GPIO_PIN 7

// Address of RAM, where the image for CPU1 should be copied
// According to UM11126 2.1.5 it is SRAM 3 on CM33 data bus
#define CORE1_BOOT_ADDRESS (void *) 0x20033000

// Sequence required to be written
// to SYSCON->CPUCTRL register ORed with other bits
// to applay settings
// See UM11126 4.5.70 for more details
#define SYSCON_CPUCTRL_ENABLING_SEQ 0xC0C40000

// Warning!!! IAR specific code. 
// core1_image_start is defined in 
// LPC55S69_cm33_core0_flash.icf linker config file
extern unsigned char core1_image_start[];
#define CORE1_IMAGE_START core1_image_start

static inline void Delay(void)
{
  for(int i = 0; i < 8000000; i++);
}

// Firmware image size calculation
uint32_t get_core1_image_size(void)
{
    uint32_t core1_image_size;
#pragma section = "__sec_core"
    core1_image_size = (uint32_t)__section_end("__sec_core") - 
                       (uint32_t)&core1_image_start;
    return core1_image_size;
}

int main()
{  
  /**** LED setup ****/
  // Enable clocking for GPIO1 (located on AHB bus)
  SYSCON->AHBCLKCTRLX[0] |= SYSCON_AHBCLKCTRL0_GPIO1_MASK;

  // Set direction for GPIO1 7 as output
  GPIO->DIR[LED_GPIO_BLOCK] |= GPIO_DIR_DIRP(1 << LED_GPIO_PIN);

  /**** Mailbox setup for mutex ****/
  // Enable mailbox clocking
  SYSCON->AHBCLKCTRLX[0] |=  SYSCON_AHBCLKCTRL0_MAILBOX_MASK;

  /**** CPU1 (slave) setup ****/
  //  Copy CPU1 image to an other SRAM block
  memcpy(CORE1_BOOT_ADDRESS, (void *)CORE1_IMAGE_START, get_core1_image_size());

  // Enable CPU1
  SYSCON->CPUCFG |= SYSCON_CPUCFG_CPU1ENABLE_MASK;

  // Setup firmware boot address
  SYSCON->CPBOOT = SYSCON_CPBOOT_CPBOOT(CORE1_BOOT_ADDRESS);

  // Enable clock and reset CPU1
  SYSCON->CPUCTRL = SYSCON->CPUCTRL | SYSCON_CPUCTRL_ENABLING_SEQ | 
                    SYSCON_CPUCTRL_CPU1RSTEN_MASK | SYSCON_CPUCTRL_CPU1CLKEN_MASK;

  // Release reset for CPU1
  SYSCON->CPUCTRL = (SYSCON->CPUCTRL | SYSCON_CPUCTRL_ENABLING_SEQ) & 
                    (~SYSCON_CPUCTRL_CPU1RSTEN_MASK);

  while(1)
  {
    /**** LED blinking ****/
    while (!(MAILBOX->MUTEX & MAILBOX_MUTEX_EX_MASK));  // Try to acquire mutex
    GPIO->B[LED_GPIO_BLOCK][LED_GPIO_PIN] = 0;          // Turn led On

    Delay();

    GPIO->B[LED_GPIO_BLOCK][LED_GPIO_PIN] = 1;  // Turn led off
    MAILBOX->MUTEX = MAILBOX_MUTEX_EX_MASK;     // Release mutex

    Delay();
  }
}


1 ( )
#include "LPC55S69_cm33_core1.h"

#define LED_GPIO_BLOCK 1
#define LED_GPIO_PIN 4

static inline void Delay(void)
{
  for(int i = 0; i < 8000000; i++);
}

int main()
{  
  /**** LED setup ****/
  // Enable clocking for GPIO1 (located on AHB bus)
  SYSCON->AHBCLKCTRLX[0] |= SYSCON_AHBCLKCTRL0_GPIO1_MASK;

  // Set direction for GPIO1 7 as output
  GPIO->DIR[LED_GPIO_BLOCK] |= GPIO_DIR_DIRP(1 << LED_GPIO_PIN);

  /**** Mailbox setup for mutex ****/
  // Enable mailbox clocking
  SYSCON->AHBCLKCTRLX[0] |=  SYSCON_AHBCLKCTRL0_MAILBOX_MASK;

  while(1)
  {
    /**** LED blinking ****/
    while (!(MAILBOX->MUTEX & MAILBOX_MUTEX_EX_MASK)); //  Try to acquire mutex
    GPIO->B[LED_GPIO_BLOCK][LED_GPIO_PIN] = 0;         // Turn led On

    Delay();

    GPIO->B[LED_GPIO_BLOCK][LED_GPIO_PIN] = 1;  // Turn led off
    MAILBOX->MUTEX = MAILBOX_MUTEX_EX_MASK;     // Release mutex

    Delay();
  }
}


GitHub.





:






All Articles