Difference between revisions of "How to configure system resources"

[quality revision] [quality revision]
m (System resource management on the Cortex-M4 context)
m
 


1 Article purpose[edit]

This article explains how to configure the GPIO, EXTI, clocks and regulators system resources shared between the Arm® Cortex®-A7 and the Arm® Cortex®-M4 contexts.

In this article, it is assumed that the system runs in production boot mode where both the Cortex-A7 non-secure and Cortex-M4 contexts are running. The specificities of the engineering boot mode are not covered here.

2 Introduction[edit]

When a peripheral is assigned to the Cortex®-M4 context (refer to How to assign an internal peripheral to a runtime context for details), the developer has to pay attention to the configuration of the system resources, shared between the Cortex®-A7 and the Cortex®-M4 contexts. It is mandatory to avoid concurrent accesses to these resources from the Cortex®-A7 and the Cortex®-M4.

The system resources can be accessed:

  • from the Cortex®-A7 core:
  • from the Cortex®-M4 by the STM32Cube firmware.


To ensure an exclusive access to these system resources, two strategies are implemented in the STM32MPU Embedded Software distribution:

  • a protection by a hardware semaphore (seeHSEM) for GPIO and EXTI configurations,
  • an exclusive access by the Cortex-A7 non-secure context. In that case, the Cortex-M4 context relies on the resources manager to configure the clocks and regulators via the Linux kernel .

3 Protecting GPIO and EXTI system resources by hardware semaphores[edit]

The GPIO and EXTI configurations are protected from concurrent accesses by hardware semaphores from HSEM.
Each execution context must use a hardware semaphore to ensure the exclusive access to the critical registers of the GPIO and EXTI resources.

Info.png The developer has to ensure the consistency of the hardware semaphore usage accross the Cortex-A7 non-secure and Cortex-M4 contexts: in the STM32MPU Embedded Software distribution, the HSEM 0 and the HSEM 1 are used to protect the GPIO and the EXTI configurations, respectively.

3.1 Cortex-A7 secure context[edit]

In the STM32MPU Embedded Software distribution, the TF-A and OP-TEE do not use HSEM protection, since no concurrent accesses to GPIO and EXTI system resource have been identified. Nevertheless this protection has to be taken into account in secure firmware development.

3.2 Cortex-A7 non-secure context[edit]

3.2.1 U-boot[edit]

No specific protection is required in U-Boot since it configures the system resources before starting the Cortex-M4 firmware.

3.2.2 Linux kernel[edit]

The Linux GPIO and EXTI drivers use semaphores to protect the registers from being acessed: these semaphores are defined in the corresponding device tree nodes.

exti: interrupt-controller@5000d000 {
        compatible = "st,stm32mp1-exti", "syscon";
        ...
        hwlocks = <&hsem 1>;
        ...
};

pinctrl: pin-controller@50002000 {
        compatible = "st,stm32mp157-pinctrl";
        ...
        hwlocks = <&hsem 0>;
        ...
}

3.3 Cortex-M4 context[edit]

In the STM32Cube application, the developer must protect the GPIO and EXTI configuration registers by hardware semaphores managed by the HSEM. This can be done by using the lock resource service.

Info.png The selection of HSEM 0 for GPIO and HSEM 1 for EXTI protection is hidden inside STM32Cube code and visible inside the above lock resource service
.
void main(void)
{
  GPIO_InitStruct.Pin = USER_BUTTON_PIN;

  /*HW semaphore Clock enable*/
  __HAL_RCC_HSEM_CLK_ENABLE();

  PERIPH_LOCK(GPIOA);
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
  PERIPH_UNLOCK(GPIOA); 
  ...
  PERIPH_LOCK(EXTI);
  HAL_EXTI_SetConfigLine(&hexti, &EXTI_ConfigStructure);
  PERIPH_UNLOCK(EXTI);
}

4 Configuring clock and regulator system resources[edit]

The Linux kernel provides services, implemented by the resource manager, to control the clock and regulator configuration for the peripherals assigned to the Cortex-M4 context:

  • The resource manager configures the clocks and the regulators before the Cortex-M4 starts.
  • At runtime, the Cortex-M4 STM32Cube application can ask the resource manager to update the clock and regulator configurations:
    • clock rate
    • regulator settings

4.1 System resource manager on the Cortex-A7 non-secure context[edit]

The resource manager Linux Kernel driver is in charge of configuring the clocks and regulators used to operate the peripherals assigned to the Cortex-M4 context. The configurations are defined in the m4_system_resources node of the Linux kernel device tree.

To help developers, the Linux kernel predefines the clock system resources for most of the peripherals that can be assigned to the Cortex-M4 context: see arch/arm/boot/dts/stm32mp157c-m4-srm.dtsi .

4.2 System resource management on the Cortex-M4 context[edit]

As clock and regulator system resources are under the Linux kernel responsibility, the Cortex-M4 context must NOT configure these system resources directly:

  • The Cortex-M4 must not set the initial configuration of these resources: this is done by the Linux kernel.
  • The Cortex-M4 can use the STM32Cube ResourceManager utility to update the configuration of these resources.
Info.png In addition to the peripheral configuration, the Cortex-M4 still has to enable/disable the pheripheral clock. The peripheral clock enable is implemented in the HAL_MSPInit code generated by the STM32CubeMX tool.

4.3 ADC example[edit]

This example describes how to configure the system resources of the ADC peripheral assigned to the Cortex-M4 coprocessor.

4.3.1 Device tree on the Cortex-A7 non-secure context[edit]

&adc {
	status = "disabled";
	...
};
m4_adc: adc@48003000 {
	compatible = "rproc-srm-dev";
	reg = <0x48003000>;
	clocks = <&rcc ADC12>, <&rcc ADC12_K>;
	clock-names = "bus", "adc";
	status = "disabled";
};
  • Enable the resource manager
&m4_rproc {
	m4_system_resources {
		status = "okay";
	};
};
  • Enable the Linux ADC resource node for the Cortex-M4 and assign a regulator to it
&m4_adc {
	vref-supply = <&vdda>;
	status = "okay";
};

4.3.2 Firmware update on the Cortex-M4 context[edit]

No implementation is required to have the resources configured to their initial state.

The below example describes how to update the ADC1 regulator configuration:

  • Initialization:
int main(void)
{
  ...
  /* Initialize the ResourceManager with OpenAMP */
  HAL_IPCC_Init(&hipcc);
  OPENAMP_Init(RPMSG_REMOTE, NULL);
  ResMgr_Init(NULL, NULL);

  ...
 
  while (1)
  {
    /* ResourceManager with OpenAMP polling */
    OPENAMP_check_for_message();

    /* Application main processing */
    ...
}
  • Update of the regulator voltage:
 config_in.regu.index = 0;
 config_in.regu.enable = 1;
 config_in.regu.min_voltage_mv = 1000;
 config_in.regu.max_voltage_mv = 4000;

 ResMgr_SetConfig(RESMGR_ID_ADC1, NULL, RESMGR_REGU, &config_in, &config_out);

 log_info("Regulator voltage is now=%ld mv\n", config_out.regu.curr_voltage_mv);


<noinclude>

{{ClonedFrom | stm32mpu}}</noinclude>

== Article purpose ==
This article explains how to configure the '''GPIO''', '''EXTI''', '''clocks''' and '''regulators''' [[Resource_manager_for_coprocessing#Terminology | system resources]] shared between the Arm<sup>&reg;</sup> Cortex<sup>&reg;</sup>-A7 and the Arm<sup>&reg;</sup> Cortex<sup>&reg;</sup>-M4 contexts.

In this article, it is assumed that the system runs in [[STM32CubeMP1 Package#Introduction to boot mode|production boot mode]] where both the Cortex-A7 non-secure and Cortex-M4 contexts are running. The specificities of the [[STM32CubeMP1 development guidelines|engineering boot mode]] are not covered here.

==Introduction==
When a peripheral is '''assigned to the Cortex<sup>&reg;</sup>-M4''' context (refer to [[How_to_assign_an_internal_peripheral_to_a_runtime_context |How to assign an internal peripheral to a runtime context]] for details), the developer has to pay attention to the configuration of the [[Resource_manager_for_coprocessing#Terminology | system resources]], shared between the Cortex<sup>&reg;</sup>-A7 and the Cortex<sup>&reg;</sup>-M4 contexts. It is mandatory to '''avoid concurrent accesses''' to these resources from the Cortex<sup>&reg;</sup>-A7 and the Cortex<sup>&reg;</sup>-M4.<br><br />


The system resources can be accessed:
* from the Cortex<sup>&reg;</sup>-A7 core:
:*during the platform boot, by [[U-Boot overview|U-Boot]] or [[TF-A overview |TF-A]], (refer to [[Boot chainschain overview]]),
:*during the Linux<sup>&reg;</sup> firmware execution.
* from the Cortex<sup>&reg;</sup>-M4 by the [[STM32CubeMP1 architecture|STM32Cube]] firmware.<br>

To ensure an exclusive access to these system resources, two strategies are implemented in the [[STM32MPU Embedded Software distribution]]:
*a protection by a hardware semaphore (see[[HSEM internal peripheral|HSEM]]) for '''GPIO''' and '''EXTI''' configurations,
*an exclusive access by the Cortex-A7 non-secure context. In that case, the Cortex-M4 context relies on the [[Resource_manager_for_coprocessing | resources manager]] to configure the '''clocks''' and '''regulators''' via the [[STM32MP15 Linux kernel overview|Linux kernel]] .

== Protecting GPIO and EXTI system resources by hardware semaphores ==
The '''GPIO''' and '''EXTI''' configurations are protected from concurrent accesses by '''hardware semaphores''' from [[HSEM internal peripheral|HSEM]].<br />

Each execution context must use a hardware semaphore to ensure the exclusive access to the '''critical registers''' of the GPIO and EXTI resources.
{{Info|The developer has to ensure the consistency of the hardware semaphore usage accross the Cortex-A7 non-secure and Cortex-M4 contexts: in the STM32MPU Embedded Software distribution, the '''HSEM 0''' and the '''HSEM 1''' are used to protect the '''GPIO''' and the '''EXTI''' configurations, respectively.}}

=== Cortex-A7 secure context ===
In the [[STM32MPU Embedded Software distribution]], the [[TF-A overview |TF-A]] and [[OP-TEE overview|OP-TEE]] do not use HSEM protection, since no concurrent accesses to GPIO and EXTI system resource have been identified. Nevertheless this protection has to be taken into account in secure firmware development.

=== Cortex-A7 non-secure context ===
==== U-boot ====
No specific protection is required in U-Boot since it configures the system resources before starting the Cortex-M4 firmware.
==== Linux kernel ====
The Linux GPIO and EXTI drivers use semaphores to protect the registers from being acessed: these semaphores are defined in the corresponding device tree nodes.

 exti: interrupt-controller@5000d000 {
         compatible = "st,stm32mp1-exti", "syscon";
         ...
         {{Highlight|hwlocks {{=}} <&hsem 1>;}}
         ...
 };

 pinctrl: pin-controller@50002000 {
         compatible = "st,stm32mp157-pinctrl";
         ...
         {{Highlight|hwlocks {{=}} <&hsem 0>;}}
         ...
 }

=== Cortex-M4 context ===
In the [[STM32CubeMP1 architecture|STM32Cube]] application, the developer must protect the '''GPIO''' and EXTI configuration registers by '''hardware semaphores''' managed by the [[HSEM internal peripheral|HSEM]]. This can be done by using the {{CodeSource | STM32CubeMP1 | Projects/STM32MP157C-DK2/Templates/Src/lock_resource.c | lock resource}} service.
{{Info | The selection of '''HSEM 0''' for '''GPIO''' and '''HSEM 1''' for '''EXTI''' protection is hidden inside STM32Cube code and visible inside the above '''lock resource''' service}}.

 void main(void)
 {
   GPIO_InitStruct.Pin = USER_BUTTON_PIN;

   /*HW semaphore Clock enable*/
   {{Highlight|__HAL_RCC_HSEM_CLK_ENABLE();}}

   {{Highlight|PERIPH_LOCK(GPIOA);}}
   HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
   {{Highlight|PERIPH_UNLOCK(GPIOA); }}
   ...
   {{Highlight|PERIPH_LOCK(EXTI);}}
   HAL_EXTI_SetConfigLine(&hexti, &EXTI_ConfigStructure);
   {{Highlight|PERIPH_UNLOCK(EXTI);}}
 }

== Configuring clock and regulator system resources ==
The [[STM32MP15 Linux kernel overview|Linux kernel]] provides services, implemented by the [[Resource_manager_for_coprocessing|resource manager]], to control the '''clock''' and '''regulator''' configuration for the peripherals assigned to the Cortex-M4 context:
* The resource manager [[Resource_manager_for_coprocessing#System_resource_configuration_set_service|configures]] the clocks and the regulators before the Cortex-M4 starts.
* At runtime, the Cortex-M4 STM32Cube application can ask the resource manager to [[Resource_manager_for_coprocessing#Dynamic_system_resource_update_service|update]] the clock and regulator configurations: 
**clock rate
**regulator settings

===System resource manager on the Cortex-A7 non-secure context===
The [[Resource_manager_for_coprocessing#System_resource_configuration_set_service | resource manager]] Linux Kernel driver is in charge of configuring the clocks and regulators used to operate the peripherals assigned to the Cortex-M4 context. The configurations are defined  in the '''m4_system_resources''' node of the Linux kernel [[Device tree|device tree]]. 

To help developers, the [[STM32MP15 Linux kernel overview|Linux kernel]] predefines the clock system resources for most of the peripherals that can be assigned to the Cortex-M4 context: see {{CodeSource | Linux kernel | arch/arm/boot/dts/stm32mp157c-m4-srm.dtsi}}.

=== System resource management on the Cortex-M4 context===
As clock and regulator system resources are under the [[STM32MP15 Linux kernel overview|Linux kernel]] responsibility, the Cortex-M4 context '''must NOT''' configure these system resources directly:
*The Cortex-M4 must not set the initial configuration of these resources: this is done by the [[STM32MP15 Linux kernel overview|Linux kernel]].
*The Cortex-M4 can use the [[STM32CubeMP1 architecture|STM32Cube]] ResourceManager utility to update the configuration of these resources.

{{Info| In addition to the peripheral configuration, the Cortex-M4 still has to enable/disable the pheripheral clock. The peripheral clock enable is implemented in the [[STM32CubeMP1_development_guidelines#HAL_MspInit | HAL_MSPInit]] code generated by the [[STM32CubeMX]] tool.}}

=== ADC example ===
This example describes how to configure the system resources of the ADC peripheral assigned to the Cortex-M4 coprocessor.

==== Device tree on the Cortex-A7 non-secure context====
* Disable the Linux ADC device node for the Cortex-A7 non-secure context (see [[How to assign an internal peripheral to a runtime context]] for details):
 &adc {
 	status = {{Highlight|"disabled"}};
 	...
 };

* Notice that the ADC clocks are already defined in {{CodeSource | Linux kernel | arch/arm/boot/dts/stm32mp157c-m4-srm.dtsi}}.

 m4_adc: adc@48003000 {
 	compatible = "rproc-srm-dev";
 	reg = <0x48003000>;
 	{{Highlight|clocks {{=}} <&rcc ADC12>, <&rcc ADC12_K>;}}
 	{{Highlight|clock-names {{=}} "bus", "adc";}}
 	status = "disabled";
 };

* Enable the resource manager
 &m4_rproc {
 	m4_system_resources {
 		{{Highlight|status {{=}} "okay";}}
 	};
 };
* Enable the Linux ADC resource node for the Cortex-M4 and assign a regulator to it
 &m4_adc {
 	{{Highlight|vref-supply {{=}} <&vdda>;}}
 	{{Highlight|status {{=}} "okay";}}
 };

==== Firmware update on the Cortex-M4 context ====
No implementation is required to have the resources configured to their initial state.

The below example describes how to update the ADC1 regulator configuration:

* Initialization:
 int main(void)
 {
   ...
   /* Initialize the ResourceManager with OpenAMP */
   HAL_IPCC_Init(&hipcc);
   OPENAMP_Init(RPMSG_REMOTE, NULL);
   {{Highlight|ResMgr_Init}}(NULL, NULL);

   ...

   while (1)
   {
     /* ResourceManager with OpenAMP polling */
     OPENAMP_check_for_message();

     /* Application main processing */
     ...
 }

* Update of the regulator voltage:
  config_in.regu.index = 0;
  config_in.regu.enable = 1;
  config_in.regu.min_voltage_mv = 1000;
  config_in.regu.max_voltage_mv = 4000;

  {{Highlight|ResMgr_SetConfig}}({{Highlight|RESMGR_ID_ADC1}}, NULL, {{Highlight|RESMGR_REGU}}, &config_in, &config_out);

  log_info("Regulator voltage is now=%ld mv\n", config_out.regu.curr_voltage_mv);
<noinclude>

[[Category:How to customize software]]
[[Category:Coprocessor management Linux]]
[[Category:Coprocessor management STM32Cube]]
{{PublicationRequestId | 10649 | 2019-02-07 | AnneJ}}
{{ReviewsComments | W906.2 ArnaudP : this article will need to be updated for A7 secure context part, after the implementation of the management of slim firmware}}</noinclude>
Line 13: Line 13:
 
The system resources can be accessed:
 
The system resources can be accessed:
 
* from the Cortex<sup>&reg;</sup>-A7 core:
 
* from the Cortex<sup>&reg;</sup>-A7 core:
:*during the platform boot, by [[U-Boot overview|U-Boot]] or [[TF-A overview |TF-A]], (refer to [[Boot chains overview]]),
+
:*during the platform boot, by [[U-Boot overview|U-Boot]] or [[TF-A overview |TF-A]], (refer to [[Boot chain overview]]),
 
:*during the Linux<sup>&reg;</sup> firmware execution.
 
:*during the Linux<sup>&reg;</sup> firmware execution.
 
* from the Cortex<sup>&reg;</sup>-M4 by the [[STM32CubeMP1 architecture|STM32Cube]] firmware.
 
* from the Cortex<sup>&reg;</sup>-M4 by the [[STM32CubeMP1 architecture|STM32Cube]] firmware.