mbed os: using timer - stm32

I am using the board STM32F446RE to run [this project][1]. I am trying to set up and use timer 10 to count. The main.c file is below.
#include "radio.h"
#include <cstdio>
#if defined(SX128x_H)
#define BW_KHZ 200
#define SPREADING_FACTOR 7
#define CF_HZ 2487000000
#define TX_DBM 6
#else
#if defined(SX126x_H)
#define TX_DBM (Radio::chipType == CHIP_TYPE_SX1262 ? 20 : 14)
#else
#define TX_DBM 20
#endif
#define BW_KHZ 125
#define SPREADING_FACTOR 7
#define CF_HZ 915000000
#endif
/**********************************************************************/
EventQueue queue(4 * EVENTS_EVENT_SIZE);
TIM_HandleTypeDef htim10;
static void MX_TIM10_Init(void)
{
/* USER CODE BEGIN TIM10_Init 0 */
/* USER CODE END TIM10_Init 0 */
/* USER CODE BEGIN TIM10_Init 1 */
/* USER CODE END TIM10_Init 1 */
htim10.Instance = TIM10;
htim10.Init.Prescaler = 0;
htim10.Init.CounterMode = TIM_COUNTERMODE_UP;
htim10.Init.Period = 65535;
htim10.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
//htim10.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
if (HAL_TIM_Base_Init(&htim10) != HAL_OK)
{
printf("Error Error\r\n");
}
/* USER CODE BEGIN TIM10_Init 2 */
/* USER CODE END TIM10_Init 2 */
}
void tx_test()
{
static uint8_t seq = 0;
Radio::radio.tx_buf[0] = seq++; /* set payload */
Radio::Send(1, 0, 0, 0); /* begin transmission */
printf("sent\r\n");
/* {
mbed_stats_cpu_t stats;
mbed_stats_cpu_get(&stats);
printf("canDeep:%u ", sleep_manager_can_deep_sleep());
printf("Uptime: %llu ", stats.uptime / 1000);
printf("Sleep time: %llu ", stats.sleep_time / 1000);
printf("Deep Sleep: %llu\r\n", stats.deep_sleep_time / 1000);
}*/
}
void txDoneCB()
{
printf("got-tx-done\r\n");
queue.call_in(500, tx_test);
}
void rxDoneCB(uint8_t size, float rssi, float snr)
{
}
void radio_irq_callback()
{
queue.call(Radio::service);
}
const RadioEvents_t rev = {
/* DioPin_top_half */ radio_irq_callback,
/* TxDone_topHalf */ NULL,
/* TxDone_botHalf */ txDoneCB,
/* TxTimeout */ NULL,
/* RxDone */ rxDoneCB,
/* RxTimeout */ NULL,
/* RxError */ NULL,
/* FhssChangeChannel */NULL,
/* CadDone */ NULL
};
int main()
{
printf("\r\nreset-tx ");
Radio::Init(&rev);
Radio::Standby();
Radio::LoRaModemConfig(BW_KHZ, SPREADING_FACTOR, 1);
Radio::SetChannel(CF_HZ);
Radio::set_tx_dbm(TX_DBM);
// preambleLen, fixLen, crcOn, invIQ
Radio::LoRaPacketConfig(8, false, true, false);
MX_TIM10_Init();
HAL_TIM_Base_Start_IT(&htim10);
HAL_Delay(500);
__HAL_TIM_SET_COUNTER(&htim10, 15);
uint16_t timer_val = __HAL_TIM_GET_COUNTER(&htim10);
printf("timer value = %d", timer_val);
queue.call_in(500, tx_test);
queue.dispatch();
}
Basically, I used the initialisation code taken from STM32CubeMX and I configured the clock of timer 10 in the file system_clock.c (normally in STM32CubeMX, clocks are configured in Clock Configuration tab). Then I initialized and started the time before getting the counter from that function. However, all I get from __HAL_TIM_GET_COUNTER is 0.
I want to ask what I did wrong.
Thank you,
Huy Nguyen
[1]: https://os.mbed.com/users/dudmuck/code/simple_tx/

This is purely speculation, but maybe you've not enabled the clock for TIM10. I don't know if that would explain what you are seeing or not. You might need something like __HAL_RCC_TIM10_CLK_ENABLE();

Related

Access to register of unclocked peripheral at 0x40000000 cause BUS_FAULT [U2_CM3CORE]

I'm working with STM32F103C6, HCSR-04 Ultrasonic sensor and LCD display.
I simulate that in Proteus Professional 8, when I activate Timer 2 in STM32, there are big problems with frequency, frequency of LCD display = 250kHz, frequency of STM32 = 36MHz. In this state, program will eject this message "Access to register of unclocked peripheral at 0x40000000 cause BUS_FAULT [U2_CM3CORE]" more than 1000 times, and then program will crash.
If I increase frequency of STM32 in Proteus then LCD display shows nothing. Does anyone has idea how to fix this problem.
/* USER CODE BEGIN Header */
/**
******************************************************************************
* #file : main.c
* #brief : Main program body
******************************************************************************
* #attention
*
* Copyright (c) 2022 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "lcd_txt.h"
#include "stdio.h"
#include "HCSR04.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#define HCSR04_SENSOR1 8
uint16_t TRIG_Ticks = 0;
uint16_t LCD_Ticks = 0;
float Distance = 0.0;
char TEXT[16] = {0};
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
#define usTIM TIM1
/* USER CODE END PTD */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
/* USER CODE END PM */
/* Private variables ---------------------------------------------------------*/
I2C_HandleTypeDef hi2c1;
TIM_HandleTypeDef htim2;
UART_HandleTypeDef huart2;
/* USER CODE BEGIN PV */
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_I2C1_Init(void);
static void MX_USART2_UART_Init(void);
static void MX_TIM2_Init(void);
/* USER CODE BEGIN PFP */
void usDelay(uint32_t uSec);
/* USER CODE END PFP */
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
/**
* #brief The application entry point.
* #retval int
*/
int main(void)
{
/* USER CODE BEGIN 1 */
uint32_t numTicks = 0;
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_I2C1_Init();
MX_USART2_UART_Init();
MX_TIM2_Init();
/* USER CODE BEGIN 2 */
lcd_init();
lcd_puts(1,0, (int8_t*)"test");
/* USER CODE END 2 */
HCSR04_Init(HCSR04_SENSOR1, &htim2);
lcd_puts(0,0, (int8_t*)"test");
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
Distance = HCSR04_Read(HCSR04_SENSOR1);
sprintf(TEXT, "Dist= %.2f cm", Distance);
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
/**
* #brief System Clock Configuration
* #retval None
*/
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
HCSR04_TMR_IC_ISR(htim);
}
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef* htim)
{
HCSR04_TMR_OVF_ISR(htim);
}
void SysTick_CallBack(void)
{
TRIG_Ticks++;
LCD_Ticks++;
if(TRIG_Ticks >= 15) // Each 15msec
{
HCSR04_Trigger(HCSR04_SENSOR1);
TRIG_Ticks = 0;
}
if(LCD_Ticks >= 200) // Each 200msec
{
lcd_clear();
lcd_puts(0,0, (int8_t*)TEXT);
LCD_Ticks = 0;
}
}
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
/** Initializes the RCC Oscillators according to the specified parameters
* in the RCC_OscInitTypeDef structure.
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI_DIV2;
RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/** Initializes the CPU, AHB and APB buses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1) != HAL_OK)
{
Error_Handler();
}
}
/**
* #brief I2C1 Initialization Function
* #param None
* #retval None
*/
static void MX_I2C1_Init(void)
{
/* USER CODE BEGIN I2C1_Init 0 */
/* USER CODE END I2C1_Init 0 */
/* USER CODE BEGIN I2C1_Init 1 */
/* USER CODE END I2C1_Init 1 */
hi2c1.Instance = I2C1;
hi2c1.Init.ClockSpeed = 100000;
hi2c1.Init.DutyCycle = I2C_DUTYCYCLE_2;
hi2c1.Init.OwnAddress1 = 0;
hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
hi2c1.Init.OwnAddress2 = 0;
hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
if (HAL_I2C_Init(&hi2c1) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN I2C1_Init 2 */
/* USER CODE END I2C1_Init 2 */
}
/**
* #brief TIM2 Initialization Function
* #param None
* #retval None
*/
static void MX_TIM2_Init(void)
{
/* USER CODE BEGIN TIM2_Init 0 */
/* USER CODE END TIM2_Init 0 */
TIM_ClockConfigTypeDef sClockSourceConfig = {0};
TIM_MasterConfigTypeDef sMasterConfig = {0};
TIM_IC_InitTypeDef sConfigIC = {0};
/* USER CODE BEGIN TIM2_Init 1 */
/* USER CODE END TIM2_Init 1 */
htim2.Instance = TIM2;
htim2.Init.Prescaler = 0;
htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
htim2.Init.Period = 0;
htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
if (HAL_TIM_Base_Init(&htim2) != HAL_OK)
{
Error_Handler();
}
sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
if (HAL_TIM_ConfigClockSource(&htim2, &sClockSourceConfig) != HAL_OK)
{
Error_Handler();
}
if (HAL_TIM_IC_Init(&htim2) != HAL_OK)
{
Error_Handler();
}
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK)
{
Error_Handler();
}
sConfigIC.ICPolarity = TIM_INPUTCHANNELPOLARITY_RISING;
sConfigIC.ICSelection = TIM_ICSELECTION_DIRECTTI;
sConfigIC.ICPrescaler = TIM_ICPSC_DIV1;
sConfigIC.ICFilter = 0;
if (HAL_TIM_IC_ConfigChannel(&htim2, &sConfigIC, TIM_CHANNEL_1) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN TIM2_Init 2 */
/* USER CODE END TIM2_Init 2 */
}
/**
* #brief USART2 Initialization Function
* #param None
* #retval None
*/
static void MX_USART2_UART_Init(void)
{
/* USER CODE BEGIN USART2_Init 0 */
/* USER CODE END USART2_Init 0 */
/* USER CODE BEGIN USART2_Init 1 */
/* USER CODE END USART2_Init 1 */
huart2.Instance = USART2;
huart2.Init.BaudRate = 115200;
huart2.Init.WordLength = UART_WORDLENGTH_8B;
huart2.Init.StopBits = UART_STOPBITS_1;
huart2.Init.Parity = UART_PARITY_NONE;
huart2.Init.Mode = UART_MODE_TX_RX;
huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart2.Init.OverSampling = UART_OVERSAMPLING_16;
if (HAL_UART_Init(&huart2) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN USART2_Init 2 */
/* USER CODE END USART2_Init 2 */
}
/**
* #brief GPIO Initialization Function
* #param None
* #retval None
*/
static void MX_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOD_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_10|GPIO_PIN_11|GPIO_PIN_12|GPIO_PIN_13
|GPIO_PIN_14|GPIO_PIN_15, GPIO_PIN_RESET);
/*Configure GPIO pins : PB10 PB11 PB12 PB13
PB14 PB15 */
GPIO_InitStruct.Pin = GPIO_PIN_10|GPIO_PIN_11|GPIO_PIN_12|GPIO_PIN_13
|GPIO_PIN_14|GPIO_PIN_15;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
}
/* USER CODE BEGIN 4 */
void usDelay(uint32_t uSec)
{
if(uSec < 2) uSec = 2;
usTIM->ARR = uSec - 1; /*sets the value in the auto-reload register*/
usTIM->EGR = 1; /*Re-initialises the timer*/
usTIM->SR &= ~1; //Resets the flag
usTIM->CR1 |= 1; //Enables the counter
while((usTIM->SR&0x0001) != 1);
usTIM->SR &= ~(0x0001);
}
/* USER CODE END 4 */
/**
* #brief This function is executed in case of error occurrence.
* #retval None
*/
void Error_Handler(void)
{
/* USER CODE BEGIN Error_Handler_Debug */
/* User can add his own implementation to report the HAL error return state */
__disable_irq();
while (1)
{
}
/* USER CODE END Error_Handler_Debug */
}
#ifdef USE_FULL_ASSERT
/**
* #brief Reports the name of the source file and the source line number
* where the assert_param error has occurred.
* #param file: pointer to the source file name
* #param line: assert_param error line source number
* #retval None
*/
void assert_failed(uint8_t *file, uint32_t line)
{
/* USER CODE BEGIN 6 */
/* User can add his own implementation to report the file name and line number,
ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
/* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */

Reading an array structure with open62541 OPCUA

I am trying to read my Omron NX102 PLC OPCUA Server. I have a Data Structure
in the PLC with fields as STRING and an DOUBLE array of length 4.
I can read all the information correctly from UA Expert and my code as well.
typedef struct {
UA_String describe;
size_t arSize;
UA_Double* arguments;
} dArgument;
static UA_DataTypeMember dArgument_members[2] = {
{
UA_TYPENAME("describe") /* .memberName */
& UA_TYPES[UA_TYPES_STRING], /* .memberType */
0, /* .padding */
false, /* .isArray */
false /* .isOptional */
},
{
UA_TYPENAME("arguments") /* .memberName */
& UA_TYPES[UA_TYPES_DOUBLE], /* .memberType */
0, /* .padding */
true, /* .isArray */
false /* .isOptional */
}
};
static const UA_DataType dArgumentType = {
UA_TYPENAME("dArgument") /* .typeName */
{4, UA_NODEIDTYPE_NUMERIC, {5001}}, /* .typeId */
{4, UA_NODEIDTYPE_NUMERIC, {5002}}, /* .binaryEncodingId, the numeric
identifier used on the wire (the
namespaceindex is from .typeId) */
sizeof(dArgument), /* .memSize */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable (depends on endianness and
the absence of padding) */
2, /* .membersSize */
dArgument_members
};
And printing the information from the main() as:
UA_ReadRequest request;
UA_ReadRequest_init(&request);
UA_ReadValueId ids[3];
UA_ReadValueId_init(&ids[0]);
ids[0].attributeId = UA_ATTRIBUTEID_VALUE;
ids[0].nodeId = UA_NODEID_STRING(4, (char*)"moveAbsoluteArgument");
request.nodesToRead = ids;
request.nodesToReadSize = 1;
UA_DataValue reading[3];
UA_ReadResponse response = UA_Client_Service_read(client, request);
reading[0] = *response.results;
dArgument* arg = (dArgument*)reading[0].value.data;
for (int i = 0; i < arg->arSize; i++)
printf(" args[%d]: %f Describe: %.*s\n\n\n\n\n\n", i, arg->arguments[i],
arg>describe.data, arg->describe.data);
The moment I change the Type of describe from UA_String to UA_UInt16, it does not populate the arSize and I can not read the extension object. Somehow UA_UInt16 is messing up my Extension Object. The Structure is as below:
UAExpert can read the data correctly as shown below but not the code I am trying (below).
Could someone please help with what I am doing wrong?
The code I am trying is:
typedef struct {
UA_UInt16 describe;
size_t arSize;
UA_Double* arguments;
} dArgument;
static UA_DataTypeMember dArgument_members[2] = {
{
UA_TYPENAME("describe") /* .memberName */
& UA_TYPES[UA_TYPES_UINT16], /* .memberType */
0, /* .padding */
false, /* .isArray */
false /* .isOptional */
},
{
UA_TYPENAME("arguments") /* .memberName */
& UA_TYPES[UA_TYPES_DOUBLE], /* .memberType */
0, /* .padding */
true, /* .isArray */
false /* .isOptional */
}
};
static const UA_DataType dArgumentType = {
UA_TYPENAME("dArgument") /* .typeName */
{4, UA_NODEIDTYPE_NUMERIC, {5001}}, /* .typeId */
{4, UA_NODEIDTYPE_NUMERIC, {5002}}, /* .binaryEncodingId, the numeric
identifier used on the wire (the
namespaceindex is from .typeId) */
sizeof(dArgument), /* .memSize */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
false, /* .pointerFree */
false, /* .overlayable (depends on endianness and
the absence of padding) */
2, /* .membersSize */
dArgument_members
};
And the main()
UA_ReadRequest request;
UA_ReadRequest_init(&request);
UA_ReadValueId ids[3];
UA_ReadValueId_init(&ids[0]);
ids[0].attributeId = UA_ATTRIBUTEID_VALUE;
ids[0].nodeId = UA_NODEID_STRING(4, (char*)"moveAbsoluteArgument");
// set here the nodes you want to read
request.nodesToRead = ids;
request.nodesToReadSize = 1;
UA_DataValue reading[3];
UA_ReadResponse response = UA_Client_Service_read(client, request);
reading[0] = *response.results;
dArgument* arg = (dArgument*)reading[0].value.data;
for (int i = 0; i < arg->arSize; i++)
printf(" args[%d]: %f Describe: %d\n\n\n\n\n\n", i, arg->arguments[i], arg->describe);

CMSIS_driver I2C problem, status stuck in busy

I tried to learn the CMSIS driver in I2C. I have STM32F407VGT6 and EEPROM at24c256 as test hardware. First, create the I2C environment with CubeMX to config the I2C.
https://imgur.com/CbroTeo
https://imgur.com/nCP5eFt
then I followed the arm example from the arm-cmsis driver website.
https://arm-software.github.io/CMSIS_5/Driver/html/group__i2c__interface__gr.html
#include "Driver_I2C.h"
#define EEPROM_I2C_ADDR 0xA0 /* EEPROM I2C address */
/* I2C driver instance */
extern ARM_DRIVER_I2C Driver_I2C1;
static ARM_DRIVER_I2C *I2Cdrv = &Driver_I2C1;
static volatile uint32_t I2C_Event;
/* I2C Signal Event function callback */
void I2C_SignalEvent (uint32_t event) {
/* Save received events */
I2C_Event |= event;
/* Optionally, user can define specific actions for an event */
if (event & ARM_I2C_EVENT_TRANSFER_INCOMPLETE) {
/* Less data was transferred than requested */
}
if (event & ARM_I2C_EVENT_TRANSFER_DONE) {
/* Transfer or receive is finished */
}
if (event & ARM_I2C_EVENT_ADDRESS_NACK) {
/* Slave address was not acknowledged */
}
if (event & ARM_I2C_EVENT_ARBITRATION_LOST) {
/* Master lost bus arbitration */
}
if (event & ARM_I2C_EVENT_BUS_ERROR) {
/* Invalid start/stop position detected */
}
if (event & ARM_I2C_EVENT_BUS_CLEAR) {
/* Bus clear operation completed */
}
if (event & ARM_I2C_EVENT_GENERAL_CALL) {
/* Slave was addressed with a general call address */
}
if (event & ARM_I2C_EVENT_SLAVE_RECEIVE) {
/* Slave addressed as receiver but SlaveReceive operation is not started */
}
if (event & ARM_I2C_EVENT_SLAVE_TRANSMIT) {
/* Slave addressed as transmitter but SlaveTransmit operation is not started */
}
}
/* Read I2C connected EEPROM (event driven example) */
int32_t EEPROM_Read_Event (uint16_t addr, uint8_t *buf, uint32_t len) {
uint8_t a[2];
a[0] = (uint8_t)(addr >> 8);
a[1] = (uint8_t)(addr & 0xFF);
/* Clear event flags before new transfer */
I2C_Event = 0U;
I2Cdrv->MasterTransmit (EEPROM_I2C_ADDR, a, 2, true);
/* Wait until transfer completed */
while ((I2C_Event & ARM_I2C_EVENT_TRANSFER_DONE) == 0U);
/* Check if all data transferred */
if ((I2C_Event & ARM_I2C_EVENT_TRANSFER_INCOMPLETE) != 0U) return -1;
/* Clear event flags before new transfer */
I2C_Event = 0U;
I2Cdrv->MasterReceive (EEPROM_I2C_ADDR, buf, len, false);
/* Wait until transfer completed */
while ((I2C_Event & ARM_I2C_EVENT_TRANSFER_DONE) == 0U);
/* Check if all data transferred */
if ((I2C_Event & ARM_I2C_EVENT_TRANSFER_INCOMPLETE) != 0U) return -1;
return 0;
}
/* Read I2C connected EEPROM (pooling example) */
int32_t EEPROM_Read_Pool (uint16_t addr, uint8_t *buf, uint32_t len) {
uint8_t a[2];
a[0] = (uint8_t)(addr >> 8);
a[1] = (uint8_t)(addr & 0xFF);
I2Cdrv->MasterTransmit (EEPROM_I2C_ADDR, a, 2, true);
/* Wait until transfer completed */
while (I2Cdrv->GetStatus().busy);
/* Check if all data transferred */
if (I2Cdrv->GetDataCount () != len) return -1;
I2Cdrv->MasterReceive (EEPROM_I2C_ADDR, buf, len, false);
/* Wait until transfer completed */
while (I2Cdrv->GetStatus().busy);
/* Check if all data transferred */
if (I2Cdrv->GetDataCount () != len) return -1;
return 0;
}
/* Initialize I2C connected EEPROM */
int32_t EEPROM_Initialize (bool pooling) {
int32_t status;
uint8_t val;
if (pooling == true) {
I2Cdrv->Initialize (NULL);
} else {
I2Cdrv->Initialize (I2C_SignalEvent);
}
I2Cdrv->PowerControl (ARM_POWER_FULL);
I2Cdrv->Control (ARM_I2C_BUS_SPEED, ARM_I2C_BUS_SPEED_FAST);
I2Cdrv->Control (ARM_I2C_BUS_CLEAR, 0);
/* Check if EEPROM can be accessed */
if (pooling == true) {
status = EEPROM_Read_Pool (0x00, &val, 1);
} else {
status = EEPROM_Read_Event (0x00, &val, 1);
}
return (status);
}
above was the code example from cmsis-driver website. I have modified the EEPROM_I2C_ADDR to 0xA0(for AT24C256 EEPROM).
then I try to run main() with function
EEPROM_Initialize(true)
then this function will get into EEPROM_Read_Pool()
but the test always stuck in
while (I2Cdrv->GetStatus().busy);
after I2Cdrv->MasterTransmit (EEPROM_I2C_ADDR, a, 2, true);。
I have tried
use HAL library to run MEM_Write, MEM_Read with the EEPROM, and make sure the EEPROM could work.
HAL_I2C_Mem_Write(&hi2c1, EEPROM_ADDRESS, 0, 0xff, &data_to_write, 1,10);
HAL_Delay(10);
uint8_t data_read = 60;
HAL_I2C_Mem_Read(&hi2c1,EEPROM_ADDRESS,0,0xff,&data_to_read,1,1);
I have checked the return value of all below
I2Cdrv->PowerControl (ARM_POWER_FULL);
I2Cdrv->Control (ARM_I2C_BUS_SPEED, ARM_I2C_BUS_SPEED_FAST);
I2Cdrv->Control (ARM_I2C_BUS_CLEAR, 0);
I2Cdrv->MasterTransmit (EEPROM_I2C_ADDR, a, 2, true);
all the return value are 0x00000000(seems running ok).But still have no idea why the status is always busy.
I have checked that it has no chance to get into the
I2C_EV_IRQHandler or I2C_ER_IRQHandlerin debug mode to change the status or increase the TX count.

Same S-Function used twice, one works one doesn't

I have a simulink model and I made a simple s-function block to add to my model and it works.
The catch if if I copy or use that same s-function twice in my model, when I run it only the last s-function called will do what it's supposed to do, the other will output a 0.
#define S_FUNCTION_NAME DivByZero
#define S_FUNCTION_LEVEL 2
#define NUMBER_OF_INPUTS 1
#define NUMBER_OF_OUTPUTS 1
#include "DivByZero.h"
#include "mex.h"
#if !defined(MATLAB_MEX_FILE)
/*
* This file cannot be used directly
*/
# error This_file_can_be_used_only_during_simulation_inside_Simulink
#endif
float32 DivByZeroInput;
float32 DivByZeroOutput;
const void * inputPorts[NUMBER_OF_INPUTS];
const void * outputPorts[NUMBER_OF_OUTPUTS];
static void mdlInitializeSizes(SimStruct *S)
{
uint8 i;
ssSetNumSFcnParams(S, 0);
if (ssGetNumSFcnParams(S) != ssGetSFcnParamsCount(S))
{
return; /* Parameter mismatch reported by the Simulink engine */
}
if (!ssSetNumInputPorts(S, NUMBER_OF_INPUTS)) return;
ssSetInputPortWidth(S, 0, 1);
ssSetInputPortDataType(S, 0, SS_SINGLE);
for (i = 0; i < NUMBER_OF_INPUTS; i++)
{
ssSetInputPortDirectFeedThrough(S, i, 1); /* Set direct feedthrough flag */
ssSetInputPortRequiredContiguous(S, i, 1); /*direct input signal access*/
}
if (!ssSetNumOutputPorts(S, NUMBER_OF_OUTPUTS)) return;
ssSetOutputPortWidth(S, 0, 1);
ssSetOutputPortDataType(S, 0, SS_SINGLE);
/* Set Sample Time */
ssSetNumSampleTimes(S, 1);
/* Specify the sim state compliance to be same as a built-in block */
ssSetSimStateCompliance(S, USE_DEFAULT_SIM_STATE);
ssSetOptions(S, SS_OPTION_ALLOW_PORT_SAMPLE_TIME_IN_TRIGSS);
ssSupportsMultipleExecInstances(S, true); //set so the s-function can be used in a for each subsystem block
}
static void mdlInitializeSampleTimes(SimStruct *S)
{
/* Inherits sample time from the driving block */
ssSetSampleTime(S, 0, INHERITED_SAMPLE_TIME);
ssSetOffsetTime(S, 0, 0.0);
ssSetModelReferenceSampleTimeDefaultInheritance(S);
}
#define MDL_START
#if defined(MDL_START)
static void mdlStart(SimStruct *S)
{
uint8 i;
/* Save Input ports */
for (i = 0; i < NUMBER_OF_INPUTS; i++)
{
inputPorts[i] = ssGetInputPortSignal(S, i);
}
/* Save Output ports */
for (i = 0; i < NUMBER_OF_OUTPUTS; i++)
{
outputPorts[i] = ssGetOutputPortRealSignal(S, i);
}
}
#endif
static void mdlOutputs(SimStruct *S, int_T tid)
{
memcpy(&DivByZeroInput, inputPorts[0], sizeof(DivByZeroInput));//gets the input port info
if (fabs(DivByZeroInput) > 0.00001f)
{
DivByZeroOutput = DivByZeroInput;
}
else
{
if (DivByZeroInput >= 0.0f)
{
DivByZeroOutput = 0.00001f;
}
else
{
DivByZeroOutput= -0.00001f;
}
}
memcpy(outputPorts[0], &DivByZeroOutput, sizeof(DivByZeroOutput));//sets the output port
}
static void mdlTerminate(SimStruct *S)
{
/* MODEL TERMINATE */
}
/* END OF TEMPLATE */
#ifdef MATLAB_MEX_FILE /* Is this file being compiled as a MEX-file? */
#include "simulink.c" /* MEX-file interface mechanism */
#else
#include "cg_sfun.h" /* Code generation registration function */
#endif
The s-function is supposed to provide a simple division by zero protection as you can see from the code.
In the image below, if I delete S-Function1, S-Function will then work as intended.
I tried putting it in a library block and just put 2 library blocks and I got the same result
You are defining these variables:
float32 DivByZeroInput;
float32 DivByZeroOutput;
const void * inputPorts[NUMBER_OF_INPUTS];
const void * outputPorts[NUMBER_OF_OUTPUTS];
These variables are shared across both instances, which means both S-Functions write to the same output addresses.
Side note: Do you really have to use an S-Function? Creating the same from a few native simulink blocks is probably much easier.

Matlab S-Function crashing when set to dynamically sized

i have following problem. I have created a S-Function which should read a matrix from a text file, where the output size of the output port is not known and therefore set as dynamically sized. Matlab is then crashing. When setting for fixed size, there is no problem. I hope someone could help me out
#define S_FUNCTION_NAME Data_Input
#define S_FUNCTION_LEVEL 2
/*---- Define size of input ports ---------------------------------------------------*/
#define OUTPUTSIZE 50
/*-----------------------------------------------------------------------------------*/
#include <stdio.h>
#include "simstruc.h"
int_T in;
/*---- Define data types ------------------------------------------------------------*/
typedef struct SBufferData
{
real32_T data[50];
int32_T number;
} SBuffer;
/*==== mdlCheckParameters ===========================================================*/
#undef MDL_CHECK_PARAMETERS /* Change to #undef to remove function */
#if defined(MDL_CHECK_PARAMETERS) && defined(MATLAB_MEX_FILE)
static void mdlCheckParameters(SimStruct *S)
{
}
#endif /* MDL_CHECK_PARAMETERS */
/*===================================================================================*/
/*=== mdlInitializeSizes ============================================================*/
static void mdlInitializeSizes(SimStruct *S)
{
ssSetNumSFcnParams(S,1); /* number of expected parameters */
ssSetSFcnParamTunable(S, 0, 0); /* sets parameter 1 to be non-tunable */
ssSetSFcnParamTunable(S, 1, 0); /* sets parameter 2 to be non-tunable */
ssSetNumContStates(S,0); /* number of continuous states */
ssSetNumDiscStates(S,0); /* number of discrete states */
ssSetNumInputPorts(S,0); /* number of input ports */
ssSetNumOutputPorts(S,1); /* number of output ports */
ssSetOutputPortWidth(S,0,DYNAMICALLY_SIZED); /* first output port width */
ssSetOutputPortDataType(S,0,SS_SINGLE); /* first output port data type */
ssSetNumSampleTimes(S,0); /* number of sample times */
ssSetNumRWork(S,0); /* number real work vector elements */
ssSetNumIWork(S,0); /* number int_T work vector elements */
ssSetNumPWork(S,1); /* number ptr work vector elements */
ssSetNumModes(S,0); /* number mode work vector elements */
ssSetNumNonsampledZCs(S,0); /* number of nonsampled zero crossing */
if (ssGetNumSFcnParams(S) != ssGetSFcnParamsCount(S)) {
return; /* Parameter mismatch reported by the Simulink engine*/
}
}
/*===================================================================================*/
/*==== mdlInitializeSampleTimes =====================================================*/
static void mdlInitializeSampleTimes(SimStruct *S)
{
real_T dSampleTime=(mxGetPr(ssGetSFcnParam(S,0))[0]);
ssSetSampleTime(S, 0, dSampleTime);
ssSetOffsetTime(S, 0, 0.0);
}
/*===================================================================================*/
/*==== mdlStart =====================================================================*/
#define MDL_START /* Change to #undef to remove function */
#if defined(MDL_START)
static void mdlStart(SimStruct *S)
{
FILE *fp;
int_T i, index=0;
SBuffer *buffer;
float temp;
/*---- Retrieve pointer to pointers work vector -------------------------------------*/
void **PWork = ssGetPWork(S);
buffer = (SBuffer *)malloc(OUTPUTSIZE * sizeof(SBuffer));
PWork[0] = (void *)buffer;
/*---- Read from text-file ----------------------------------------------------------*/
fp = fopen("myfile.txt", "r");
while(feof(fp)==0)
{
fscanf(fp,"%f",&temp);
buffer -> data[index] = temp;
index++;
}
buffer -> number = (int32_T) index;
fclose(fp);
}
#endif /* MDL_START */
/*===================================================================================*/
/*==== mdlOutputs ===================================================================*/
static void mdlOutputs(SimStruct *S, int_T tid)
{
/*---- Get input ports --------------------------------------------------------------*/
real_T *y1=(real_T *)ssGetOutputPortSignal(S,0);
int_T i;
SBuffer *buffer;
/*---- Retrieve pointer to pointers work vector -------------------------------------*/
void **PWork = ssGetPWork(S);
buffer = PWork[0];
for (i = 0; i < buffer->number; i++)
{
y1[i] = buffer->data[i];
}
}
/*===================================================================================*/
/*==== mdlTerminate =================================================================*/
static void mdlTerminate(SimStruct *S)
{
SBuffer *buffer;
/*---- Retrieve pointer to pointers work vector -------------------------------------*/
void **PWork = ssGetPWork(S);
buffer = PWork[0];
/*---- Deallocate structure 'info' and 'buffer' -------------------------------------*/
free(buffer);
}
/*===================================================================================*/
/*==== Required S-function trailer ==================================================*/
#ifdef MATLAB_MEX_FILE /* Is this file being compiled as a MEX-file? */
#include "simulink.c" /* MEX-file interface mechanism */
#else
#include "cg_sfun.h" /* Code generation registration function */
#endif
/*===================================================================================*/