Undeclared identifiers (C-mex S-Functions) - matlab

I understand that this is a very common problem that a lot is facing. however I don't understand how to link to my program. It's a simple c = a+b program. I have the following as my C-Mex S-function:
#define S_FUNCTION_NAME Addition
#define S_FUNCTION_LEVEL 2
#include "simstruc.h"
static void mdlInitializeSizes(SimStruct *S)
{
int_T nInputPorts = 2; /* Set no. of input ports */
int_T nOutputPorts = 1; /* Set no. of output ports */
int_T needsInput = 1; /* Direct feed through = yes */
int_T inputPortIdx = 0;
int_T outputPortIdx = 0;
ssSetNumSFcnParams(S, 0);
if (ssGetNumSFcnParams(S) != ssGetSFcnParamsCount(S))
{
return; /* If no. of expected input parameters is not equal to no.
of parameters entered in dialog box, return. Simulink
to generate an error indicating parameter mismatched */
}
/* Configure input ports */
if (!ssSetNumInputPorts(S, 2)) return;
/* Configure first input ports */
ssSetInputPortWidth(S, 0, DYNAMICALLY_SIZED); /* Set dimensions of first input port */
ssSetInputPortDirectFeedThrough(S, 0, 1); /* Set direct feed through */
/* Configure second input ports */
ssSetInputPortWidth(S, 1, DYNAMICALLY_SIZED); /* Set dimensions of second input port */
ssSetInputPortDirectFeedThrough(S, 1, 1); /* Set direct feed through */
/* Configure output ports */
if (!ssSetNumOutputPorts(S,1)) return;
ssSetOutputPortWidth(S, 0, DYNAMICALLY_SIZED); /* Set dimensions of output ports */
ssSetNumSampleTimes(S, 1); /* Set no. of sample times */
ssSetSimStateCompliance(S, USE_DEFAULT_SIM_STATE);
ssSetOptions (S,0);
} /* End of mdlInitializeSizes */
static void mdlInitializeSampleTimes (SimStruc *S)
{
ssSetSampleTimes(S, 0, INHERITED_SAMPLE_TIME);
/* Inherited Sample time: S-function block executes whenever driving block executes */
ssSetOffsetTime(S, 0, 0.0); /* No offset required */
ssSetModelReferenceSampleTimeDefaultInheritance(S); /* */
} /* End of mdlInitializeSampleTime */
static void mdlOutputs (SimStruc *S, int_T tid)
{
int_T i;
InputRealPtrsType uPtrs = ssGetInputPortRealSignalPtrs(S,0);
real_T *y = ssGetOutputPortRealSignal(S,0);
int_T width = ssGetOutputPortWidth(S,0);
for (i=0; i<width; i++) /* i = location of memory. from 0 to 1. */
{
*y++ = (*uPtrs[i+1]) + (*uPtrs[i]); /* c = a + b */
}
} /* End of mdlOutputs */
static void mdlTerminate(SimStruct *S)
{
/* No task to be perform at end of simulation therefore no termination required.
But this is a compulsory function to have for C-mex S-function */
} /* End of mdlTerminate */
#ifdef MATLAB_MEX_FILE
#include "simulink.c"
#else
#include "cg_sfun.h"
#endif
however when compiling on matlab, i keep getting the following error:
Addition.c:47: error: expected ‘)’ before ‘*’ token
Addition.c:56: error: expected ‘)’ before ‘*’ token
In file included from Addition.c:82:
/DIST/it/sw/amd64/matlab/r2010b/simulink/include/simulink.c: In function ‘_ProcessMexSfunctionCmdLineCall’:
/DIST/it/sw/amd64/matlab/r2010b/simulink/include/simulink.c:2545: error: ‘mdlInitializeSampleTimes’ undeclared (first use in this function)
/DIST/it/sw/amd64/matlab/r2010b/simulink/include/simulink.c:2545: error: (Each undeclared identifier is reported only once
/DIST/it/sw/amd64/matlab/r2010b/simulink/include/simulink.c:2545: error: for each function it appears in.)
/DIST/it/sw/amd64/matlab/r2010b/simulink/include/simulink.c:2601: error: ‘mdlOutputs’ undeclared (first use in this function)
Any comments will be greatly appreciated!

You misspelled SimStruct in the two lines mentioned at the top of your error message. That error about the parentheses means that the compiler doesn't know that SimStruc is a type, so the * doesn't fit. After that, those two functions aren't defined, so the simulink interface gets upset that it can't find those two required functions in your file.

Related

What could be the cause of a constant voltage offset on the STM32L041G6 adc

I have been testing the ADC on my STM32L0 with 12-bit resolution and for some reason, every measurement I take has a 0.048 V offset. I've tried a different supply voltage (from 1.8 V to 3.3 V), but the offset stays there.
This offset starts at the first count, when I apply 0 V to the ADC input and read 130 counts (with 1.8 V Vdda) it stays for the whole range.
My voltage source is very stable and I've verified my ADC input voltage and the STM32 supply voltage with 3 different accurate pieces of measuring equipment.
The voltage is applied to the circuit through a bnc connector connected to a signal generator, in my case I use the Dc output option with high impedance on a normal signal generator. As for the code, I used stm32cubemx to generate some of the code but I didn't use any calibration function, so unless it is enabled by default, I dont do any calibration. As for the adc pin, I just used cubemx to set-up IN0 as an adc input and didn't touch anything else. Then to read the adc, I used 2 hal function "HAL_ADC_START()" and "HAL_ADC_PollForConversion()". Then I send the result to be read by uart.
The board I'm using is a custom PCB, but I only placed the STM32 and some passive components to get it to function (coupling capacitors and reset pull-up).
I also tested multiple boards with different configurations and I always get this offset voltage. I outputed Vrefint and measured it, and I got 1.225 V (specified is 1.224 V) so the ADC reference seems fine too.
I was wondering if someone has a suggestion on the possible cause of this offset error? I've been looking for a solution but I'm having no luck so far, so I would really appreciate the input of more experienced developers.
Here is a simplified version of the code I use :
/* USER CODE BEGIN Header */
/**
******************************************************************************
* #file adc.c
* #brief This file provides code for the configuration
* of the ADC instances.
******************************************************************************
* #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 "adc.h"
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
ADC_HandleTypeDef hadc;
/* ADC init function */
void MX_ADC_Init(void)
{
/* USER CODE BEGIN ADC_Init 0 */
/* USER CODE END ADC_Init 0 */
ADC_ChannelConfTypeDef sConfig = {0};
/* USER CODE BEGIN ADC_Init 1 */
/* USER CODE END ADC_Init 1 */
/** Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion)
*/
hadc.Instance = ADC1;
hadc.Init.OversamplingMode = DISABLE;
hadc.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV1;
hadc.Init.Resolution = ADC_RESOLUTION_12B;
hadc.Init.SamplingTime = ADC_SAMPLETIME_1CYCLE_5;
hadc.Init.ScanConvMode = ADC_SCAN_DIRECTION_FORWARD;
hadc.Init.DataAlign = ADC_DATAALIGN_RIGHT;
hadc.Init.ContinuousConvMode = DISABLE;
hadc.Init.DiscontinuousConvMode = DISABLE;
hadc.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
hadc.Init.ExternalTrigConv = ADC_SOFTWARE_START;
hadc.Init.DMAContinuousRequests = DISABLE;
hadc.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
hadc.Init.Overrun = ADC_OVR_DATA_PRESERVED;
hadc.Init.LowPowerAutoWait = DISABLE;
hadc.Init.LowPowerFrequencyMode = ENABLE;
hadc.Init.LowPowerAutoPowerOff = DISABLE;
if (HAL_ADC_Init(&hadc) != HAL_OK)
{
Error_Handler();
}
/** Configure for the selected ADC regular channel to be converted.
*/
sConfig.Channel = ADC_CHANNEL_0;
sConfig.Rank = ADC_RANK_CHANNEL_NUMBER;
if (HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN ADC_Init 2 */
/* USER CODE END ADC_Init 2 */
}
void HAL_ADC_MspInit(ADC_HandleTypeDef* adcHandle)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
if(adcHandle->Instance==ADC1)
{
/* USER CODE BEGIN ADC1_MspInit 0 */
/* USER CODE END ADC1_MspInit 0 */
/* ADC1 clock enable */
__HAL_RCC_ADC1_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
/**ADC GPIO Configuration
PA0-CK_IN ------> ADC_IN0
*/
GPIO_InitStruct.Pin = SENSOR_ANALOG_IN_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(SENSOR_ANALOG_IN_GPIO_Port, &GPIO_InitStruct);
/* USER CODE BEGIN ADC1_MspInit 1 */
/* USER CODE END ADC1_MspInit 1 */
}
}
void HAL_ADC_MspDeInit(ADC_HandleTypeDef* adcHandle)
{
if(adcHandle->Instance==ADC1)
{
/* USER CODE BEGIN ADC1_MspDeInit 0 */
/* USER CODE END ADC1_MspDeInit 0 */
/* Peripheral clock disable */
__HAL_RCC_ADC1_CLK_DISABLE();
/**ADC GPIO Configuration
PA0-CK_IN ------> ADC_IN0
*/
/* USER CODE BEGIN ADC1_MspDeInit 1 */
/* USER CODE END ADC1_MspDeInit 1 */
}
}
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
And here is the main file where I call the function to read the adc and send it to uart to be read :
#include "main.h"
#include "gpio.h"
#include "adc.h"
#include "usart.h"
#include <stdlib.h>
extern "C"
void execute(){
HAL_Delay(10);
HAL_ADC_Start(&hadc);
HAL_ADC_PollForConversion(&hadc, HAL_MAX_DELAY);
const auto value = HAL_ADC_GetValue(&hadc);
char buffer [5];
itoa(value, buffer, 10);
HAL_UART_Transmit(&huart2, reinterpret_cast<uint8_t*>(buffer), 5, HAL_MAX_DELAY);
}
Here is the schematic, as I said, the test circuit only had the mcu and some passive components : https://im.ge/i/FbQPIp

EEPROM emulator on STM32L053

I known that isn't normal to use EEPROM emulator on a STM32L053, because it has is own EEPROM, but nowadays with the chip shortage, i was forcedto use an alternative MCU (STM32L053R8T6) instead of the "original design" (STM32F030C8T6), so i want to use the same code for both MCU, so the EEPROM emulator on the STM32L053R8T6.
But i'm having some difficulty using the EEPROM emulator on the STM32L053, the compiler didn't give any error, and the code run normmally, but didn't save any value to the EEPROM.
Header File:
#define ADDR_FLASH_PAGE_60 ((uint32_t)0x0800F000) /* Base # of Page 60, 1 Kbytes */
#define ADDR_FLASH_PAGE_61 ((uint32_t)0x0800F400) /* Base # of Page 61, 1 Kbytes */
#define ADDR_FLASH_PAGE_62 ((uint32_t)0x0800F800) /* Base # of Page 62, 1 Kbytes */
/* Define the size of the sectors to be used */
#define PAGE_SIZE (uint32_t) FLASH_PAGE_SIZE /* Page size */
/* EEPROM start address in Flash */
#define EEPROM_START_ADDRESS ((uint32_t) ADDR_FLASH_PAGE_60) /* EEPROM emulation start address */
/* Pages 0 and 1 base and end addresses */
#define PAGE0_BASE_ADDRESS ((uint32_t)(EEPROM_START_ADDRESS + 0x0000))
#define PAGE0_END_ADDRESS ((uint32_t)(EEPROM_START_ADDRESS + (PAGE_SIZE - 1)))
#define PAGE1_BASE_ADDRESS ((uint32_t)(ADDR_FLASH_PAGE_61))
#define PAGE1_END_ADDRESS ((uint32_t)(ADDR_FLASH_PAGE_61 + PAGE_SIZE - 1))
/* Used Flash pages for EEPROM emulation */
#define PAGE0 ((uint16_t) 0x0000)
#define PAGE1 ((uint16_t)((PAGE1_BASE_ADDRESS-PAGE0_BASE_ADDRESS)/PAGE_SIZE)) /* Virtual page nb between PAGE0_BASE_ADDRESS & PAGE1_BASE_ADDRESS*/
/* No valid page define */
#define NO_VALID_PAGE ((uint16_t)0x00AB)
/* Page status definitions */
#define ERASED ((uint16_t)0xFFFF) /* Page is empty */
#define RECEIVE_DATA ((uint16_t)0xEEEE) /* Page is marked to receive data */
#define VALID_PAGE ((uint16_t)0x0000) /* Page containing valid data */
/* Valid pages in read and write defines */
#define READ_FROM_VALID_PAGE ((uint8_t)0x00)
#define WRITE_IN_VALID_PAGE ((uint8_t)0x01)
/* Page full define */
#define PAGE_FULL ((uint8_t)0x80)
void EE_ReadData(void);
uint16_t EE_Init(void);
uint16_t EE_ReadVariable(uint16_t VirtAddress, uint16_t* Data);
uint16_t EE_WriteVariable(uint16_t VirtAddress, uint16_t Data);
#endif /* __EEPROM_H */
EEPROM Write Variable Function:
uint16_t EE_WriteVariable(uint16_t VirtAddress, uint16_t Data)
{
uint16_t Status = 0;
/* Write the variable virtual address and value in the EEPROM */
Status = EE_VerifyPageFullWriteVariable(VirtAddress, Data);
/* In case the EEPROM active page is full */
if (Status == PAGE_FULL)
{
/* Perform Page transfer */
Status = EE_PageTransfer(VirtAddress, Data);
}
/* Return last operation status */
return Status;
}

How does a receiving process actually receive a process from a sender process via message queues?

I'm working on a project with a sender and receiver process using shared memory and a message queue. For the life of me, I cannot get the receiver process to receive the file, but i can't figure out what's actually going wrong. It seems like it's actually not getting the file or it's just stuck in an infinite loop.
So I understand that using a message queue, you need to attach to the message queue, using the message queue id. Then when you send a message, it goes to the message queue, and the receiver can receive it from that message queue. However that's what i'm doing (i think) in my code, but as mentioned before the receiver process doesn't seem to get the file. So am I wrong in how a process receives a message and thus implementing the code wrong? Any help would be greatly appreciated, as my professor just kinda threw us into this with no explanation on how to do this, so i've been trying to teach myself. This is what i have for my code:
message.h:
#include <stdio.h>
/* The information type */
#define SENDER_DATA_TYPE 1
/* The done message */
#define RECV_DONE_TYPE 2
/**
* The message structure
*/
struct message
{
/* The message type */
long mtype;
/* How many bytes in the message */
int size;
/**
* Prints the structure
* #param fp - the file stream to print to
*/
void print(FILE *fp)
{
fprintf(fp, "%ld %d", mtype, size);
}
};
Sender.cpp:
#include <iostream>
#include <sys/shm.h>
#include <sys/msg.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "msg.h" /* For the message struct */
/* The size of the shared memory chunk */
#define SHARED_MEMORY_CHUNK_SIZE 1000
/* The ids for the shared memory segment and the message queue */
int shmid, msqid;
/* The pointer to the shared memory */
void* sharedMemPtr;
/**
* Sets up the shared memory segment and message queue
* #param shmid - the id of the allocated shared memory
* #param msqid - the id of the shared memory
*/
void init(int& shmid, int& msqid, void*& sharedMemPtr)
{
std::cout<<"Creating key"<<std::endl;
key_t key = ftok("keyfile.txt", 'a');
std::cout<<"Key created"<<std::endl;
shmid =shmget(key,SHARED_MEMORY_CHUNK_SIZE, 0644|IPC_CREAT);
std::cout<<"allocated shared memory"<<std::endl;
sharedMemPtr = shmat(shmid,NULL,0);
std::cout<<"Attached to shared memory"<<std::endl;
msqid = msgget(key,0644|IPC_CREAT);
std::cout<<"Attahed to message queue"<<std::endl;
}
void cleanUp(const int& shmid, const int& msqid, void* sharedMemPtr)
{
/* TODO: Detach from shared memory */
shmdt(sharedMemPtr);
}
/**
* The main send function
* #param fileName - the name of the file
*/
void send(const char* fileName)
{
/* Open the file for reading */
FILE* fp = fopen(fileName, "r");
/* A buffer to store message we will send to the receiver. */
message sndMsg;
/* A buffer to store message received from the receiver. */
message rcvMsg;
/* Was the file open? */
if(!fp)
{
perror("fopen");
exit(-1);
}
/* Read the whole file */
while(!feof(fp))
{
if((sndMsg.size = fread(sharedMemPtr, sizeof(char), SHARED_MEMORY_CHUNK_SIZE, fp)) < 0)
{
perror("fread");
exit(-1);
}
/* TODO: Send a message to the receiver telling him that the data is ready
* (message of type SENDER_DATA_TYPE)
*/
sndMsg.mtype = SENDER_DATA_TYPE;
sndMsg.size = 0;
msgsnd(msqid,&sndMsg,sizeof(sndMsg),0);
std::cout<<"Sent data ready message"<<std::endl;
/* TODO: Wait until the receiver sends us a message of type RECV_DONE_TYPE telling us
* that he finished saving the memory chunk.
*/
std::cout<<"Waiting for reciever message"<<std::endl;
msgrcv(msqid,&rcvMsg,0,RECV_DONE_TYPE,0);
std::cout<<"Message received"<<std::endl;
}
/** TODO: once we are out of the above loop, we have finished sending the file.
* Lets tell the receiver that we have nothing more to send. We will do this by
* sending a message of type SENDER_DATA_TYPE with size field set to 0.
*/
sndMsg.size =0;
sndMsg.mtype = SENDER_DATA_TYPE;
std::cout<<"Sending empty message"<<std::endl;
msgsnd(msqid,&sndMsg,sizeof(sndMsg),0);
std::cout<<"Empty message sent"<<std::endl;
/* Close the file */
fclose(fp);
}
int main(int argc, char** argv)
{
/* Check the command line arguments */
if(argc < 2)
{
fprintf(stderr, "USAGE: %s <FILE NAME>\n", argv[0]);
exit(-1);
}
/* Connect to shared memory and the message queue */
init(shmid, msqid, sharedMemPtr);
/* Send the file */
send(argv[1]);
/* Cleanup */
cleanUp(shmid, msqid, sharedMemPtr);
return 0;
}
Receiver.cpp:
#include <iostream>
#include <sys/shm.h>
#include <sys/msg.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "msg.h" /* For the message struct */
/* The size of the shared memory chunk */
#define SHARED_MEMORY_CHUNK_SIZE 1000
/* The ids for the shared memory segment and the message queue */
int shmid, msqid;
/* The pointer to the shared memory */
void *sharedMemPtr;
/* The name of the received file */
const char recvFileName[] = "recvfile";
/**
* Sets up the shared memory segment and message queue
* #param shmid - the id of the allocated shared memory
* #param msqid - the id of the shared memory
* #param sharedMemPtr - the pointer to the shared memory
*/
void init(int& shmid, int& msqid, void*& sharedMemPtr)
{
std::cout<<"Creating key"<<std::endl;
key_t key = ftok("keyfile.txt", 'a');
shmid =shmget(key,SHARED_MEMORY_CHUNK_SIZE, 0644 | IPC_CREAT);
std::cout<<"allocated shared memory"<<std::endl;
sharedMemPtr = shmat(shmid,NULL,0);
std::cout<<"Attached to shared memory"<<std::endl;
msqid = msgget(key,0644 | IPC_CREAT);
std::cout<<"Attahed to message queue"<<std::endl;
}
void mainLoop()
{
/* The size of the mesage */
int msgSize =0;
/* Open the file for writing */
FILE* fp = fopen(recvFileName, "w");
/* Error checks */
if(!fp)
{
perror("fopen");
exit(-1);
}
std::cout<<"Waiting for message"<<std::endl;
/* TODO: Receive the message and get the message size. The message will
* contain regular information. The message will be of SENDER_DATA_TYPE
* (the macro SENDER_DATA_TYPE is defined in msg.h). If the size field
* of the message is not 0, then we copy that many bytes from the shared
* memory region to the file. Otherwise, if 0, then we close the file and
* exit.
* Keep receiving until the sender set the size to 0, indicating that
* there is no more data to send
*/
while(msgSize != 0){
message recvdMsg;
msgrcv(msqid,&recvdMsg,sizeof(recvdMsg),SENDER_DATA_TYPE,0);
msgSize = recvdMsg.size;
std::cout<<"Entering main loop"<<std::endl;
/* If the sender is not telling us that we are done, then get to work */
if(msgSize != 0)
{
/* Save the shared memory to file */
if(fwrite(sharedMemPtr, sizeof(char), msgSize, fp) < 0)
{
perror("fwrite");
}
/* TODO: Tell the sender that we are ready for the next file chunk.
* I.e. send a message of type RECV_DONE_TYPE (the value of size field
* does not matter in this case).
*/
message sentMsg;
sentMsg.mtype = RECV_DONE_TYPE;
std::cout<<"Ready for next file chunk"<<std::endl;
msgsnd(msqid,&sentMsg,0,0);
std::cout<<"Ready message sent"<<std::endl;
}
/* We are done */
else
{
/* Close the file */
fclose(fp);
}
}
}
void cleanUp(const int& shmid, const int& msqid, void* sharedMemPtr)
{
printf("Detaching from shared memory\n");
shmdt(sharedMemPtr);
printf("Deallocating shared memory chunk\n");
shmctl(shmid,IPC_RMID,NULL);
printf("deallocating message queue\n");
msgctl(msqid,IPC_RMID,NULL);
}
void ctrlCSignal(int signal)
{
/* Free system V resources */
cleanUp(shmid, msqid, sharedMemPtr);
}
int main(int argc, char** argv)
{
/* TODO: Install a signal handler
* In a case user presses Ctrl-c your program should delete message
* queues and shared memory before exiting. You may add the cleaning functionality
* in ctrlCSignal().
*/
signal(SIGINT, ctrlCSignal);
/* Initialize */
init(shmid, msqid, sharedMemPtr);
/* Go to the main loop */
mainLoop();
/** TODO: Detach from shared memory segment, and deallocate shared memory and message queue (i.e. call cleanup) **/
std::cout<<"Cleaning up"<<std::endl;
cleanUp(shmid, msqid, sharedMemPtr);
std::cout<<"Finished"<<std::endl;
return 0;
}

How to convert a python 2 C extension module to python 3

I am trying to compile an extension module where I define a custom type. However, I got hold of some python 2 code for this purpose, but I cannot for the life of me convert it into a python 3 module.
So far, I have tweaked the original code I found in the book 'Python in a nutshell' in order to attempt to compile it for python 3, by merging some bits from https://docs.python.org/3/extending/newtypes_tutorial.html,but I am still getting nowhere. I know the 3rd edition of this book has a python 3 version of the code I am trying to compile but I don't have access to that edition of the book.
So, here is the module source code test.c:
#include "Python.h"
#include "structmember.h"
/* per-instance data structure */
typedef struct {
PyObject_HEAD
int first, second;
} intpair;
static int
intpair_init(PyObject *self, PyObject *args, PyObject *kwds)
{
static char* nams[] = {"first","second",NULL};
int first, second;
if(!PyArg_ParseTupleAndKeywords(args, kwds, "ii", nams, &first, &second))
return -1;
((intpair*)self)->first = first;
((intpair*)self)->second = second;
return 0;
}
static void
intpair_dealloc(PyObject *self)
{
self->ob_type->tp_free(self);
}
static PyObject* nothing_method(PyObject* self, PyObject* args)
{
printf("This does literally nothing!\n");
Py_RETURN_NONE;
}
static PyMemberDef intpair_members[] = {
{"first", T_INT, offsetof(intpair, first), 0, "first item" },
{"second", T_INT, offsetof(intpair, second), 0, "second item" },
{NULL}
};
static PyTypeObject t_intpair = {
PyObject_HEAD_INIT(0) /* tp_head */
0, /* tp_internal */
"test.intpair", /* tp_name */
sizeof(intpair), /* tp_basicsize */
0, /* tp_itemsize */
intpair_dealloc, /* tp_dealloc */
0, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_compare */
0, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
0, /* tp_hash */
0, /* tp_call */
0, /* tp_str */
PyObject_GenericGetAttr, /* tp_getattro */
PyObject_GenericSetAttr, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT,
"two ints (first,second)",
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
0, /* tp_methods */
intpair_members, /* tp_members */
0, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
intpair_init, /* tp_init */
PyType_GenericAlloc, /* tp_alloc */
PyType_GenericNew, /* tp_new */
PyObject_Del, /* tp_free */
};
static PyMemberDef Noddy_members[] = {
{"PI", T_INT, 3, 0, "noddy number"},
{NULL, NULL, 0, NULL}
};
static PyMethodDef CosMethods[] =
{
{"does_nothing", nothing_method, METH_VARARGS, "This really does nothing"},
{NULL, NULL, 0, NULL}
};
static PyModuleDef testmodule = {
PyModuleDef_HEAD_INIT,
.m_name = "test",
.m_doc = "Example module that creates an extension type.",
.m_size = -1,
CosMethods,
};
PyMODINIT_FUNC
PyInit_test(void)
{
PyObject *m;
if (PyType_Ready(&t_intpair) < 0)
return NULL;
m = PyModule_Create(&testmodule);
if (m == NULL)
return NULL;
Py_INCREF(&t_intpair);
PyModule_AddObject(m, "Custom", (PyObject *) &t_intpair);
return m;
}
And the file setup.py:
from distutils.core import setup, Extension
setup(name="test", version="1.0",
ext_modules=[
Extension("test", ["test.c"]),
])
I can successfully compile this module using python3 setup.py build_ext --inplace, however, when I import this module in python 3 I get the following error:
Python 3.7.2 (default, Jan 10 2019, 23:51:51)
[GCC 8.2.1 20181127] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import test
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
SystemError: Type does not define the tp_name field.
I do not understand this error message, since there is a tp_name field "test.intpair" defined in PyTypeObject. What am I missing here?
Also, what is necessary to change in this code to make it compile for python 3?
Thanks!
I'm pretty sure the flaw is the line 0, /* tp_internal */ in:
PyObject_HEAD_INIT(0) /* tp_head */
0, /* tp_internal */
"test.intpair", /* tp_name */
If you search for this line the only references to it on the internet are this question and the book you're using - it's completely non-standard and I have no idea where it's come from. I half suspect that the Python 2 code uses PyVarObject and then uses tp_internal to fill in the size rather than PyVarObject_HEAD_INIT, but I can't see the relevant page of the book...
The current documentation recommends using C99 initialization like
static PyTypeObject t_intpair = {
PyObject_HEAD_INIT(0)
.tp_name = "test.intpair",
// etc
};
so that getting the order of the attributes right no longer matters (anything you don't specify is 0 initialized).
Building your code provides some pretty clear warnings about mismatched types:
warning: initialization of ‘long int’ from ‘char *’ makes integer from pointer without a cast [-Wint-conversion]
"test_mod.intpair", /* tp_name */`
You should pay attention to these
Not a direct answer to your question, so posting this is probably against site rules. I hit this page when looking for advice about how to do a similar thing, converting a python2 - C extension module to python3 - C.
This is generally not a trivial endeavor, as the interface changed significantly. I think you will find the resources at this link helpful:
https://docs.python.org/3/howto/cporting.html

TMS320F2812 FatFs f_write returns FR_DISK_ERR

I have problem with an SD card. I'm using the FatFs library ver R0.10b to access the SD card.
My code:
// .... //
FATFS fatfs;
FIL plik;
FRESULT fresult,res1,res2,res3,res4,res5;
UINT zapisanych_bajtow = 0 , br;
UINT zapianie_bajtow = 0;
char * buffor = "123456789abcdef\r\n";
unsigned short int i;
void main(void) {
// ... //
res1 = f_mount(0,&fatfs); // returns FA_OK
res2 = f_open( &plik, "f721.txt", FA_OPEN_ALWAYS | FA_WRITE ); // returns FA_OK
if( res2 == FR_OK )
{
res3 = f_write( &plik, ( const void * ) buffor, 17, &zapisanych_bajtow ); // returns FR_DISK_ERR
}
res4 = f_close( &plik );// returns FR_DISK_ERR
for(;;)
{
}
}
Any idea what might be wrong?
I had similar error with just one difference. I tried to write 4096bytes with f_write function at once. And it always returned FR_DISK_ERR.
And this was caused because I tried to write more then is size of IO buffer in FIL structure in FatFS (defined in ff.h).
typedef struct {
FATFS* fs; /* Pointer to the related file system object (**do not change order**) */
WORD id; /* Owner file system mount ID (**do not change order**) */
BYTE flag; /* Status flags */
BYTE err; /* Abort flag (error code) */
DWORD fptr; /* File read/write pointer (Zeroed on file open) */
DWORD fsize; /* File size */
DWORD sclust; /* File start cluster (0:no cluster chain, always 0 when fsize is 0) */
DWORD clust; /* Current cluster of fpter (not valid when fprt is 0) */
DWORD dsect; /* Sector number appearing in buf[] (0:invalid) */
DWORD dir_sect; /* Sector number containing the directory entry */
BYTE* dir_ptr; /* Pointer to the directory entry in the win[] */
DWORD* cltbl; /* Pointer to the cluster link map table (Nulled on file open) */
UINT lockid; /* File lock ID origin from 1 (index of file semaphore table Files[]) */
BYTE buf[_MAX_SS]; /* File private data read/write window */
} FIL;
The last array buf[_MAX_SS] is the file IO buffer. But _MAX_SS is user defined parameter (defined in ff.h) so you can decrease the amount of bytes written at once or eventually change the _MAX_SS value.
I know this is not your case because you only write 17 bytes at once, but this can be helpful for others.
It's few years when I finished with TMS but maybe it will help you:
FA_OPEN_ALWAYS Opens the file if it is existing. If not, a new file is created.
To append data to the file, use f_lseek() function after file open in this method.
If file does not exists use:
FA_CREATE_NEW Creates a new file. The function fails
with FR_EXIST if the file is existing.
I had the same issue with implementation of Chan FatFs on MSP430- always received FR_DISK_ERR result on calling disk_write().
My reason of the issue was the following:
operation failed on xmit_datablock() call, it returned 0.
xmit_datablock() failed because of xmit_spi_multi() failed.
xmit_spi_multi() failed because it was not enough to just transmit bytes from buffer.
It was necessary to read from RXBUF after every write.
Here it is how it looks after the issue was fixed:
/* Block SPI transfers */
static void xmit_spi_multi (
const BYTE* buff, /* Data to be sent */
UINT cnt /* Number of bytes to send */
)
{
do {
volatile char x;
UCA1TXBUF= *buff++; while(! (UCA1IFG & UCRXIFG)) ; x = UCA1RXBUF;
UCA1TXBUF= *buff++; while(! (UCA1IFG & UCRXIFG)) ; x = UCA1RXBUF;
} while (cnt -= 2);
}
Before fixing the issue there was no read from UCA1RXBUF following every write to UCA1TXBUF.
After fixing xmit_spi_multi() my issue with FR_DISK_ERR in disk_write() was solved.