How can I flash the NXP S32K148 using J-Link? - cortex-m

I'm working on a S32K148 with VS Code and J-Link. This is part of NXP's S32Kxxx series of 32-bit ARM Cortex M4-based MCUs targeted for high-reliability automobile and industrial applications.
I want to flash the chip using JFlash (with J-Link), but it seems that flashing has been disabled.
My research suggests that I need to have a LinkScript file for the S32Kxxx device, but I cannot find such a file anywhere.
Is my assumption correct that a LinkScript file is needed? If so, where can I find this file?

First, you need to ensure that the MCU's reset pin is connected to the reset pin of the J-Link. Without this done properly, you will not be able to connect via J-Link.
Next, it must be noted that the design of the S32Kxxx series makes it impossible to attach to a debugging session via J-Link out of the box. The Segger wiki contains a more detailed description:
ECC protected internal RAM
The device series provide ECC protected internal RAM. By default, J-Link resets the MCU on connect and initializes the RAM contents to 0x00. This is done for the following reasons:
If a memory window in the debugger is open during the debug session and points to a non-initialized RAM region, on the next single step etc. a non-maskable ECC error interrupt would be thrown
J-Link temporarily uses some portions of the RAM during flash programming and accesses to non-initialized RAM areas would throw non maskable ECC error interrupts
Attach to debug session
For the reasons mentioned [above, in the section "ECC protected internal RAM"], no out of the box attach is possible. This is because there is no way to distinguish between an attach and a connect.
To attach to the device the following J-Link script file can be used:
File:NXP_Kinetis_S32_Attach.JLinkScript
Note:
This script file is only supposed to be used in case of an attach, as it skips the device specific connect.
So, your research is correct: in order to attach to the device, you must use a J-Link script, which can be downloaded here from Segger. The contents are reprinted below:
* (c) SEGGER Microcontroller GmbH & Co. KG *
* The Embedded Experts *
* www.segger.com *
**********************************************************************
-------------------------- END-OF-HEADER -----------------------------
File : NXP_Kinetis_S32_Attach.JLinkScript
Purpose : Script file to skip the device specific connect for the
NXP Kinetis S32 devices, to make an attach possible.
Literature:
[1] J-Link User Guide
*/
/*********************************************************************
*
* Constants (similar to defines)
*
**********************************************************************
*/
/*********************************************************************
*
* Global variables
*
**********************************************************************
*/
/*********************************************************************
*
* Local functions
*
**********************************************************************
*/
/*********************************************************************
*
* Global functions
*
**********************************************************************
*/
/*********************************************************************
*
* InitTarget()
*
* Function description
* If present, called right before performing generic connect sequence.
* Usually used for targets which need a special connect sequence.
* E.g.: TI devices with ICEPick TAP on them where core TAP needs to be enabled via specific ICEPick sequences first
*
* Return value
* >= 0: O.K.
* < 0: Error
*
* Notes
* (1) Must not use high-level API functions like JLINK_MEM_ etc.
* (2) For target interface JTAG, this device has to setup the JTAG chain + JTAG TAP Ids.
*/
int InitTarget(void) {
//
// As this script file is only used for attach purposes, no special handling is required.
// Therefore, we override the default connect handled by the J-Link DLL for this device.
// as it would trigger a reset.
//
return 0;
}
/*************************** end of file ****************************/

Related

Problem with Writing to the Flash Memory of the STM32L4R5 microcontroller

I'm trying to write to the flash memory of STM32L4R5 in 'FLASH_TYPEPROGRAM_FAST' mode of the HAL_FLASH_Program().
The flash of the MCU is configured as Single Bank.
Writing to the flash only works when using 'FLASH_TYPEPROGRAM_DOUBLEWORD'. The flash reads as 0xFFFFFFFF when written in 'FLASH_TYPEPROGRAM_FAST' mode.
This is my test project:
// Page Erase Structure
static FLASH_EraseInitTypeDef EraseInitStruct;
// Page Erase Status
uint32_t eraseStatus;
// Data Buffer
uint64_t pDataBuf[32] =
{
0x1111111122222222, 0x3333333344444444,
0x5555555566666666, 0x7777777788888888,
0x12345678ABC12345, 0x23456789DEF01234,
0x34567890AAABBB12, 0x4567890FABCDDD34,
0x1111111122222222, 0x3333333344444444,
0x5555555566666666, 0x7777777788888888,
0x12345678ABC12345, 0x23456789DEF01234,
0x34567890AAABBB12, 0x4567890FABCDDD34,
0x1111111122222222, 0x3333333344444444,
0x5555555566666666, 0x7777777788888888,
0x12345678ABC12345, 0x23456789DEF01234,
0x34567890AAABBB12, 0x4567890FABCDDD34,
0x1111111122222222, 0x3333333344444444,
0x5555555566666666, 0x7777777788888888,
0x12345678ABC12345, 0x23456789DEF01234,
0x34567890AAABBB12, 0x4567890FABCDDD34
};
// Flash Page Start Address
uint32_t pageAddr = 0x081FE000;
// Fill Erase Init Structure
EraseInitStruct.TypeErase = FLASH_TYPEERASE_PAGES;
EraseInitStruct.Banks = FLASH_BANK_1;
EraseInitStruct.Page = 255;
EraseInitStruct.NbPages = 1;
// Unlocking the FLASH Control Register
HAL_FLASH_Unlock();
// Clear OPTVERR Bit Set on Virgin Samples
__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_OPTVERR);
// Erasing the Flash Page
HAL_FLASHEx_Erase(&EraseInitStruct, &Error);
#if 0
// Wriring a Doubled Word to Flash. pDataBuf[0] is the 64-bit Word
HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, pageAddr, pDataBuf[0]);
#else
// Wriring 32 Double Words. pDataBuf is the Starting Address of the 64-bit Array
HAL_FLASH_Program(FLASH_TYPEPROGRAM_FAST_AND_LAST, pageAddr, pDataBuf);
#endif
// Locking the FLASH Control Register
HAL_FLASH_Lock();
Am I doing anything wrong?
Thank you,
Ivan
Document RM0932, Reference manual for STM32L4+, section FLASH. It covers reading and writing from/to flash, for both single-bank and double-bank configurations and different MCU models of this line. It seems, most differences are about reading from Flash (64-bit for dual bank, 128-bit for single bank). As for writing, page 128:
Flash is very picky about data width, and every STM32 has different data width for its flash, it seems. Very recently I stumbled upon one, which accepted only 16-bit writes and reads. This one likes double words. There is no universal function to read and write flash to any STM32, so it seems one of your commands doesn't respect this MCU's Flash data width rules. You can check if any error flags appear as per reference manual, although, as you can see, it doesn't say anything about trying to write 32-bit piece of data. I would expect that write to fail, but we can't make any conclusions about error flags from the screenshot provided. If you're curious enough, you can look at what data width every mode/function of yours utilizes and see what happens. 64-bit writes have to work.

DFU bootloader immediately jumping to application in STM32F405RG

I am trying to immediately jump to the DFU bootloader via software on the STM32F405RG, but instead it is doing a software reset and the RCC_FLAG_SFTRST flag is thrown. The program continues to repeatedly execute the code for jumping to bootloader and finally stays in bootloader mode after multiple seconds. I experienced success with entering bootloader mode on the first try if interrupts are disabled. However, I cannot upload code while in DFU mode since it requires interrupts to be enabled. I am unsure what is causing the bootloader to jump back to the application and was hoping to get assistance on this. Below is the code for jumping to bootloader, which is called immediately after Init_HAL() under main.
void JumpToBootloader(void) {
void (*SysMemBootJump)(void);
volatile uint32_t addr = 0x1FFF0000;
HAL_RCC_DeInit();
HAL_DeInit();
/**
* Step: Disable systick timer and reset it to default values
*/
SysTick->CTRL = 0;
SysTick->LOAD = 0;
SysTick->VAL = 0;
/**
* Step: Interrupts are not disabled since they are needed for DFU mode
*/
// __disable_irq();
/**
* Step: Remap system memory to address 0x0000 0000 in address space
* For each family registers may be different.
* Check reference manual for each family.
*
* For STM32F4xx, MEMRMP register in SYSCFG is used (bits[1:0])
* For STM32F0xx, CFGR1 register in SYSCFG is used (bits[1:0])
* For others, check family reference manual
*/
__HAL_SYSCFG_REMAPMEMORY_SYSTEMFLASH(); //Call HAL macro to do this for you
/**
* Step: Set jump memory location for system memory
* Use address with 4 bytes offset which specifies jump location where program starts
*/
SysMemBootJump = (void (*)(void)) (*((uint32_t *)(addr + 4)));
/**
* Step: Set main stack pointer.
* This step must be done last otherwise local variables in this function
* don't have proper value since stack pointer is located on different position
*
* Set direct address location which specifies stack pointer in SRAM location
*/
__set_MSP(*(uint32_t *)addr);
/**
* Step: Actually call our function to jump to set location
* This will start system memory execution
*/
SysMemBootJump();
}
Taking a look at the Application Note AN2606, Rev.55, chapter 28 STM32F40xxx/41xxx devices bootloader, page 127, one can see that the first step is called "System Reset".
The DFU is not designed to be executed from your application, but to be called according to the bootloader selection after a system reset. Before you are even entering the main function of your application, a few steps are already executed to prepare the device. These steps may be different for the DFU. Calling the DFU from an unexpected system state can lead to undefined behaviour.
The best way to enter the DFU is to latch the BOOT0 pin high and then perform a system reset either by software reset, or by IWDG.
Another potential problem can arise from the HSE, which has to be provided externally, however since you stated that the DFU does eventually work, this seems unlikely.

How to enable Long Range for BLE Mesh in Zephyr OS

I’m working on Bluetooth mesh network solution and I have requirement to increase range.
I’m using nrf52840 DK and nrf52840 dongles, nrf5SDKforMeshv310.
In Nordic Devzone
I found solution which, enables BLE long range mode in NRF SDK for mesh.
NOTE! I'm aware solution doesn't comply with Bluetooth Mesh standard.
Following changes were applied to nrf5 SDK for Mesh v310:
In advertise.c, set_default_broadcast_configuration() changed radio_mode to use RADIO_MODE_NRF_62K5BIT instead of RADIO_MODE_BLE_1MBIT.
In scanner.c, scanner_config_reset() changed scanner_config_radio_mode_set() to use RADIO_MODE_NRF_62K5BIT instead of RADIO_MODE_BLE_1MBIT.
In radio_config.c, radio_config_config() added the following code at the end:
if (p_config->radio_mode==RADIO_MODE_NRF_62K5BIT ){
NRF_RADIO->PCNF0 |=(
((RADIO_PCNF0_PLEN_LongRange << RADIO_PCNF0_PLEN_Pos) & RADIO_PCNF0_PLEN_Msk) |
((2 << RADIO_PCNF0_CILEN_Pos) & RADIO_PCNF0_CILEN_Msk) |
((3 << RADIO_PCNF0_TERMLEN_Pos) & RADIO_PCNF0_TERMLEN_Msk) );
}
In broadcast.c, time_required_to_send_us() added:
if (radio_mode == RADIO_MODE_NRF_62K5BIT)
{
packet_length_in_bytes +=RADIO_PREAMBLE_LENGTH_LR_EXTRA_BYTES;
}
Defined RADIO_PREAMBLE_LENGTH_LR_EXTRA_BYTES = 9 in same file
Changed 5th element in radio_mode_to_us_per_byte[] from 128 to 64.
NOTE. that the long-range mode is mislabeled. It is called RADIO_MODE_NRF_62K5BIT in the header file but corresponds to the 125kbps BLE long range mode instead.
Unfortunately for relays I’m pushed to use Zephyr to support friend feature and Zephyr is not relaying messages after applying changes to NRF SDK. I did brief investigation on Zephyr side and found that code bits for BLE long range described above for NRF SDK are in place and can be enabled using following Kconfig settings:
CONFIG_BT_AUTO_PHY_UPDATE=y
CONFIG_BT_PHY_UPDATE=y
CONFIG_BT_HCI_MESH_EXT=y
CONFIG_BT_CTLR_PHY=y
CONFIG_BT_CTLR_ADV_EXT=y
CONFIG_BT_CTLR_ADVANCED_FEATURES=y
CONFIG_BT_CTLR_PHY_2M=y
CONFIG_BT_CTLR_PHY_CODED=y
But still I don’t see that messages are being relayed on Zephyr side (using J-Link RTT Viewer). I also tried to increase log level for Bluetooth and Mesh to DEBUG, but I don’t see any signs that messages are malformed or rejected.
May be someone has ideas in which direction I should dig in on Zephyr side?

How do I programatically remove a flash drive based on its device node name?

I have a Linux system with multiple USB flash drives plugged in, as /dev/sda1, /dev/sdb1, etc. I need to eject one of these from within my program -- something like EjectDrive("/dev/sdb1"); I then may need to programmatically re-insert the drive.
I know I can do this from the command line if I know the USB bus, port and device number. e.g. echo '2-1.3' > /sys/bus/usb/drivers/usb/unbind and then echo '2-1.3' > /sys/bus/usb/drivers/usb/bind
I'm not sure how to do this from C++, and be 100% sure I am using the correct bus, port and device for the specified drive.
This is an embedded platform with BusyBox v1.22.1, so udev is not available to me, and lsusb returns minimal information.
Yes it can be done using libusb (follow this link for libusb usage with C++). Now a few things to keep in mind -
1 - What is the device address? (You can get this using libusb API)
libusb_get_device_list (libusb_context *ctx, libusb_device ***list)
libusb_get_device_address (libusb_device *dev)
libusb_get_port_number (libusb_device *dev)
2 - Is the device connected to the root hub port or to a hub port? (This can be done by reading the parent device of the /dev/sdb1 or sda1)
libusb_get_parent (libusb_device *dev)
3 - If its connected to a hub, then do a control transfer to "clear" PORT_POWER feature of that port. That will turn off the port and the device will be disconnected. You can "set" PORT_POWER feature to turn on the port and the device will be connected again. Remember that you will not get any disconnect event which is as per the spec. (EHCI or XHCI)
int libusb_control_transfer ( libusb_device_handle * dev_handle,
uint8_t bmRequestType,
uint8_t bRequest,
uint16_t wValue,
uint16_t wIndex,
unsigned char * data,
uint16_t wLength,
unsigned int timeout
)
4 - If the device is connected to the root hub port directly, then please check if libusb supports clearing root hub port power. I am not sure about this. This also depends on the Host controller driver stack.
Please follow the link I mentioned at the top for example usage of these API's.

How to read file from USB mass storage Device using Visual C++?

I developed an MFC Dialog application in C++ in MS VS 2013 Ultimate under Windows 7 Maximal. As a progenitor of source code I use CodeProject paper in Detecting Hardware Insertion or Removal.
My application is a user-mode application. It is intended for detection of adding or removing hardware from/to computer. For this purpose I handle WM_DEVICECHANGE message and call RegisterDeviceNotification() function in my application. So, schematically, my aplication does the following:
Calls SetupDiGetClassDevs() to get a handle of device info set HDEVINFO.
Calls SetupDiEnumDeviceInfo() to enumerate all the device in the info set. Upon each iteration, we will get a SP_DEVINFO_DATA.
During the enumeration, SetupDiGetDeviceInstanceId() is called to read the instance ID for each device. The instance ID is in the form of "USB\Vid_04e8&Pid_503b\0002F9A9828E0F06".
If the instance ID match the DEV_BROADCAST_DEVICEINTERFACE.dbcc_name, then SetupDiGetDeviceRegistryProperty() is called to retrieve the description or friendly name.
But now I'm in need of reading of file from USB mass storage device when this device is pluged in (when the DBT_DEVICEARRIVAL device event has place). How can I do it programmatically in Visual C++?
The parameter of DBT_DEVICEARRIVAL is a DEV_BROADCAST_VOLUME which includes a mask of the drive letter assinged. So since you are only after mass storage devices the following works.
DEV_BROADCAST_VOLUME *pj = (DEV_BROADCAST_VOLUME*) lParam;
if (pj->dbcv_devicetype == DBT_DEVTYPE_VOLUME) {
long um = pj->dbcv_unitmask;
for ( int i=0; i < 26; i++ ) {
if (um&1) break;
um = um >> 1;
}
if ( i < 26 ) {
char Drive = 'A' + i;
}
}
In practice, some drives are ready to read instantly, others need few seconds.