How to add more FLAG of reason cause reboot with watchdog in Linux? - yocto

I'm using iMX8MM with Yocto. I'm trying to figure out the reason cause reboot with Watchdog.
I find out watchdog.h and there are a lot of FLAGs:
#define WDIOF_OVERHEAT 0x0001 /* Reset due to CPU overheat */
#define WDIOF_FANFAULT 0x0002 /* Fan failed */
#define WDIOF_EXTERN1 0x0004 /* External relay 1 */
#define WDIOF_EXTERN2 0x0008 /* External relay 2 */
#define WDIOF_POWERUNDER 0x0010 /* Power bad/power fault */
#define WDIOF_CARDRESET 0x0020 /* Card previously reset the CPU */
#define WDIOF_POWEROVER 0x0040 /* Power over voltage */
#define WDIOF_SETTIMEOUT 0x0080 /* Set timeout (in seconds) */
#define WDIOF_MAGICCLOSE 0x0100 /* Supports magic close char */
#define WDIOF_PRETIMEOUT 0x0200 /* Pretimeout (in seconds), get/set */
#define WDIOF_KEEPALIVEPING 0x8000 /* Keep alive ping reply */
But when I check with command, I get only 4 FLAGs:
$ wdctl
Device: /dev/watchdog
Identity: imx2+ watchdog [version 0]
Timeout: 60 seconds
Pre-timeout: 0 seconds
FLAG DESCRIPTION STATUS BOOT-STATUS
KEEPALIVEPING Keep alive ping reply 1 0
MAGICCLOSE Supports magic close char 0 0
PRETIMEOUT Pretimeout (in seconds) 0 0
SETTIMEOUT Set timeout (in seconds) 0 0
How do I get more of FLAG to use?

The macros(flags) you are seeing in the watchdog.h is the complete list. However, the application utility (here wdctl) is reading the driver capabilities implementation from the kernel.
Another flag you are seeing WDIOF_OVERHEAT and others should be supported by the kernel driver then and then only it will be available to the wdctl list.
Looking at the source code of the wdctl is working in the following way. It is calling the read_watchdog_from_device API to get the implemented flags(Environmental monitoring).
Please check for the flags in the corresponding driver from the i.MX8MM watchdog imx2_wdt.c.
References: https://github.com/karelzak/util-linux/blob/master/sys-utils/wdctl.c
https://www.kernel.org/doc/Documentation/watchdog/watchdog-api.txt

This is how I solve the issue above.
Find all file concert about imx2+ watchdog package.
Modified by adding more flags as watchdog.h file.
Access menuconfig in Yocto and turn on some options in Watchdog sections. This action makes sure that bitbake recognize the changing in driver.
Rebuild and generate OS image.

Related

STM32 HAL Lib,Can not clear TIM SR register by use __HAL_TIM_CLEAR_FLAG?

The TIM SR register value always be 0x1F, And Can not use to clear the reg.
HAL Lib Always runs into time interrupt really fast, and Can not clear SR register.
How to fix the promble?
Cubemx set
NVIC
`
void TIM3_IRQHandler(void)
{
/* USER CODE BEGIN TIM3_IRQn 0 */
/* USER CODE END TIM3_IRQn 0 */
HAL_TIM_IRQHandler(&htim3);
/* USER CODE BEGIN TIM3_IRQn 1 */
/* USER CODE END TIM3_IRQn 1 */
}
`
`
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if ( htim == &htim3){
__HAL_TIM_CLEAR_FLAG(&htim3,TIM_FLAG_UPDATE) ;
HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_13) ;
}
}
`
I will base my explanation on STM32F746's TIM3. Timers across STM32 that share number are usually identical or very similar.
TIM3->SR has 0x1F? That's 5 flags set! TIM3 is a general purpose STM32 timer. These 5 flags mean you have counter interrupt and four capture/compare interrupt status flags set at the same time. Something weird is going on. Are you sure you're supposed to have those flags set? Well, if their interrupts are not enabled, it doesn't matter.
You can clear these flags in TIM3->SR by writing zero to the specific position you want to clear and 1 everywhere else. As per reference manual, this register ignores if you write 1. It doesn't set bits when you do that. It only resets when you write zero. So,
TIM3->SR = 0; //clear all interrupt flags
TIM3->SR = ~TIM_SR_UIF; //clear update interrupt flag only
This works because the bits in the reference manual are marked rc_w0 - read, clear by writing zero. If bits in your SR register work differently, you may have to clear them differently. For example, sometimes status register is read-only and you clear it via write to flag clear register. Check reference manual of your MCU.

STM32 secure boot loader security enable fails consistently with "[SBOOT] Security issue : Execution stopped !"

I have my STM32F405RGT6 secure boot loader running with security flags disabled. So I try to introduce the security flags/options one by one. Independently of which flag I enable in app_sfu.h, the code fails in the first FLOW_CONTROL_CHECK in the SFU_BOOT_SM_VerifyUserFwSignature function in sfu_boot.c
I have added logging that shows exactly what happens:
/* Double security check :
- testing "static protections" twice will avoid basic hardware attack
- flow control reached : dynamic protections checked
- re-execute static then dynamic check
- errors caught by FLOW_CONTROL ==> infinite loop */
TRACE("= [SBOOT] FLOW_CONTROL_CHECK(%x, %x)\n", uFlowProtectValue, FLOW_CTRL_RUNTIME_PROTECT);
FLOW_CONTROL_CHECK(uFlowProtectValue, FLOW_CTRL_RUNTIME_PROTECT);
Output from the trace shows this:
= [SBOOT] FLOW_CONTROL_CHECK(1554b, 30f1)
The FLOW_CONTROL_CHECK macro compares the two values. If they differ, the program fails.
As I understand the code, the uFlowProtectValue contains the run time protection values that are active at the actual execution time, while FLOW_CTRL_RUNTIME_PROTECT is a compile time #define that should be the same as what we're running with.
The core of the problem is that the run time protection value is what I expect it to be, while the compile time #define never differs from 0x30f1.
The #define comes to be in ST-provided code that your mother might not approve of, not in the least because it doesn't seem to work:
/**
* #brief SFU_BOOT Flow Control : Control values static protections
*/
#define FLOW_CTRL_UBE (FLOW_CTRL_INIT_VALUE ^ FLOW_STEP_UBE)
#define FLOW_CTRL_WRP (FLOW_CTRL_UBE ^ FLOW_STEP_WRP)
#define FLOW_CTRL_PCROP (FLOW_CTRL_WRP ^ FLOW_STEP_PCROP)
#define FLOW_CTRL_SEC_MEM (FLOW_CTRL_PCROP ^ FLOW_STEP_SEC_MEM)
#define FLOW_CTRL_RDP (FLOW_CTRL_SEC_MEM ^ FLOW_STEP_RDP)
#define FLOW_CTRL_STATIC_PROTECT FLOW_CTRL_RDP
/**
* #brief SFU_BOOT Flow Control : Control values runtime protections
*/
#define FLOW_CTRL_TAMPER (FLOW_CTRL_STATIC_PROTECT ^ FLOW_STEP_TAMPER)
#define FLOW_CTRL_MPU (FLOW_CTRL_TAMPER ^ FLOW_STEP_MPU)
#define FLOW_CTRL_FWALL (FLOW_CTRL_MPU ^ FLOW_STEP_FWALL)
#define FLOW_CTRL_DMA (FLOW_CTRL_FWALL ^ FLOW_STEP_DMA)
#define FLOW_CTRL_IWDG (FLOW_CTRL_DMA ^ FLOW_STEP_IWDG)
#define FLOW_CTRL_DAP (FLOW_CTRL_IWDG ^ FLOW_STEP_DAP)
#define FLOW_CTRL_RUNTIME_PROTECT FLOW_CTRL_DAP
The hex numbers from my trace output above are from when I enable the internal watch dog, IWDG.
The values are XOR'ed from three involved bitmaps:
#define FLOW_CTRL_INIT_VALUE 0x00005776U /*!< Init value definition */
#define FLOW_STEP_UBE 0x00006787U /*!< Step UBE value */
#define FLOW_STEP_IWDG 0x000165baU /*!< Step IWDG value */
The XOR of the two first is 0x30f1, and if you add FLOW_STEP_IWDG to that, you get 0x1554b.
So the run time value with IWDG enabled is correct, while the compile time value is wrong.
How can that be?
Ok, so this is just too silly: All the involved code is supplied by ST Microelectronics.
The sfu_boot.h file which uses all the security definitions from app_sfu.h does not #include app_sfu.h and it has no built-in checks to verify that app_sfu.h has indeed been included somewhere in the include chains. So I added #include "app_sfu.h" to ST Microelectronic's provided sfu_boot.h and the problem goes away.
Sorry for the inconvenience :-)

How do I find out the size of the flash memory in the code itself?

I want to get the limiting address of the flash in the code itself, or at least the size of this flash.
I found only the start address of the flash in the stm32f302xc.h file, but did not find the end address.
/** #addtogroup Peripheral_memory_map
* #{
*/
#define FLASH_BASE 0x08000000UL /*!< FLASH base address in the alias region */
#define SRAM_BASE 0x20000000UL /*!< SRAM base address in the alias region */
#define PERIPH_BASE 0x40000000UL /*!< Peripheral base address in the alias region */
#define SRAM_BB_BASE 0x22000000UL /*!< SRAM base address in the bit-band region */
#define PERIPH_BB_BASE 0x42000000UL /*!< Peripheral base address in the bit-band region */
What defines are responsible for this, thanks.
What you want is described in the reference manual RM0366 in section 29.2 Memory size data register.
ST provide this functionaility but for some reason they don't always give an easy way to access it in the headers.
The address of this register is FLASHSIZE_BASE. You have to read it at run-time, eg:
uint16_t flash_size_kb = *(const uint16_t*)FLASHSIZE_BASE;
STM32 MCU families come in different flash sizes, that's why it's not defined in their header files. Although STM32CubeMX code generator could, in theory, add it when you select the exact model of your MCU. But this would mean code might not work if you flash it to variant with a different flash size.
However some STM32 MCUs come with a Flash size data register that contains information about the flash size. This address is often found in a header file and sometimes a macro is included. Note that it not a compile time constant, but a ROM constant that needs to be read at runtime.
stm32f3xx_hal_flash_ex.h contains the following register address:
#define FLASH_SIZE_DATA_REGISTER (0x1FFFF7CCU)
You can use it like this:
const size_t FLASH_SIZE = (*((uint16_t*)FLASH_SIZE_DATA_REGISTER)) << 10;
For the stm32g4xx there is a macro defined in stm32g4xx_hal_flash.h:
FLASH_SIZE
Be careful with writing your own macro for this as the flash size is not always linear with the value in the register. In the case of the stm32g4xx the value 0xFFFF means either 128kiB or 512kiB as seen below:
#define FLASH_SIZE_DATA_REGISTER FLASHSIZE_BASE
#if defined (FLASH_OPTR_DBANK)
#define FLASH_SIZE ((((*((uint16_t *)FLASH_SIZE_DATA_REGISTER)) == 0xFFFFU)) ? (0x200UL << 10U) : \
(((*((uint32_t *)FLASH_SIZE_DATA_REGISTER)) & 0xFFFFUL) << 10U))
#define FLASH_BANK_SIZE (FLASH_SIZE >> 1)
#define FLASH_PAGE_NB 128U
#define FLASH_PAGE_SIZE_128_BITS 0x1000U /* 4 KB */
#else
#define FLASH_SIZE ((((*((uint16_t *)FLASH_SIZE_DATA_REGISTER)) == 0xFFFFU)) ? (0x80UL << 10U) : \
(((*((uint32_t *)FLASH_SIZE_DATA_REGISTER)) & 0xFFFFUL) << 10U))
#define FLASH_BANK_SIZE (FLASH_SIZE)
#define FLASH_PAGE_NB ((FLASH_SIZE == 0x00080000U) ? 256U : 64U)
#endif
The same applies to flash page size. Page size depends on the family and sometimes on the flash size. Sometimes ST provides a macro for this too.

setsockopt SO_BROADCAST on TCP socket

In an existing networking library I've been tasked to work on there is a call to setsockopt which I don't understand
Here you can see a TCP socket begin created:
[socket] fd(11) domain(2:AF_INET) type(1:SOCK_STREAM) protocol(0:default)
Immediately afterward, a call to setsockopt is made for option SO_BROADCAST at the IPPROTO_TCP protocol level, with option value 5
[setsockopt] fd(11) level(6:IPPROTO_TCP) option(6:SO_BROADCAST) ret(0) option:
0 0500 0000 ....
According to Beej's guide to networking this "Does nothing—NOTHING!!—to TCP stream sockets! Hahaha!"
Questions:
What exactly are they doing here?
Does this make any sense?
If anything, surely it should be option_value=1, so what is the 5 about?
I think your setsockopt decoder is wrong. Are you sure it isn't one of these?
#define TCP_NODELAY 1 /* Don't delay send to coalesce packets */
#define TCP_MAXSEG 2 /* Set maximum segment size */
#define TCP_CORK 3 /* Control sending of partial frames */
#define TCP_KEEPIDLE 4 /* Start keeplives after this period */
#define TCP_KEEPINTVL 5 /* Interval between keepalives */
#define TCP_KEEPCNT 6 /* Number of keepalives before death */
That isn't a full list. See /usr/include/netinet/tcp.h for everything.

USB issue SAM3S-EK -> Custom card

I am developing my project with SAM3S-EK demo board. I used USB CDC and MSC Driver with example code and ASF and everything work fine. Now I want to put the code into my custom card (with a SAM3S1B).
But that is my problem. I have assigned the pin and changed the clock config but the device is not recognized by Windows. All of descriptors are equal to zero (according to USBLyser).
Can someone help me ?
That is my clock config file (I have a 16MHz crystal) :
// ===== System Clock (MCK) Source Options
#define CONFIG_SYSCLK_SOURCE SYSCLK_SRC_PLLACK
// ===== System Clock (MCK) Prescaler Options (Fmck = Fsys / (SYSCLK_PRES))
#define CONFIG_SYSCLK_PRES SYSCLK_PRES_4
// ===== PLL0 (A) Options (Fpll = (Fclk * PLL_mul) / PLL_div)
// Use mul and div effective values here.
#define CONFIG_PLL0_SOURCE PLL_SRC_MAINCK_XTAL
#define CONFIG_PLL0_MUL 32
#define CONFIG_PLL0_DIV 2
// ===== PLL1 (B) Options (Fpll = (Fclk * PLL_mul) / PLL_div)
// Use mul and div effective values here.
#define CONFIG_PLL1_SOURCE PLL_SRC_MAINCK_12M_RC
#define CONFIG_PLL1_MUL 16
#define CONFIG_PLL1_DIV 2
// ===== USB Clock Source Options (Fusb = FpllX / USB_div)
// Use div effective value here.
//#define CONFIG_USBCLK_SOURCE USBCLK_SRC_PLL0
#define CONFIG_USBCLK_SOURCE USBCLK_SRC_PLL1
#define CONFIG_USBCLK_DIV 2
// ===== Target frequency (System clock)
// - XTAL frequency: 16MHz
// - System clock source: PLLA
// - System clock prescaler: 4 (divided by 4)
// - PLLA source: XTAL
// - PLLA output: XTAL * 32 / 3
// - System clock is: 16 * 32 / 4 / 2 = 64MHz
// ===== Target frequency (USB Clock)
// - USB clock source: PLLB
// - USB clock divider: 2 (divided by 2)
// - PLLB output: XTAL * 12 / 2
// - USB clock: 16 * 12 / 2 / 2 = 48MHz
Like all USB devices used under Windows, you need to first install a Windows side USB driver that is specific to the device you are attaching.
When you install Atmel Studio 6.2 or newer, it installs a Windows side USB driver for the Atmel ASF USB driver you are using in your firmware. That Windows driver works with my SAM4E target processor. Be aware that it takes a long time to load the driver in Windows. It will appear to have hung. Just give it time, and it will eventually install the driver. You will probably have to respond to a pop-up warning to permit installation of an unsigned driver.
The Windows driver can also be downloaded and installed separately. Use this link:
https://gallery.atmel.com/Products/Details/6272a8fd-68fe-43d8-a990-741878cfe7b6?
Double check your clock rate. I am using the SAM4L part and it requires the PLL to run off of OSC0 to generate a 48 MHz clock. I had the same problem for a while because my ABDACB used the same clock and changed the rate. As I understand it, the plugging in of a USB device senses the single pull up resistor on the pin DP or DN depending on the speed. That is what tells windows (the host) to attempt to communicate. If the clock rate is wrong, the properties in windows all show 0s.