Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Hardfault in library (Guessing Memory address fault) #47

Open
greenscreenflicker opened this issue Apr 9, 2024 · 2 comments
Open

Hardfault in library (Guessing Memory address fault) #47

greenscreenflicker opened this issue Apr 9, 2024 · 2 comments

Comments

@greenscreenflicker
Copy link

I'm porting nanoMODBUS to a microcontroller (CH32V003).

I have the issue that i get a hardfault To diaganose that error i wrote a fake_data function, that simulates a coil read, that gives always the same data.
char fakedata[8]={0x01, 0x01, 0x00, 0x00, 0x00, 0x08, 0x3D, 0xCC};
In the hardfault interrupt, i look where the hardfault happened by using a global variable. It takes several iterations until this happens, it doesn't happen strait away.

The code is based on the arduino slave example, but the error seems to be inside the library.

What do i see?
grafik
It crashes inside the routine (_hardfault_was_inside_readwrite==1) and it has always 2 chars left in the buffer. (mb_recievebuffer_index=2) So i gues it's before the checksum is there.

@debevv can you please help to investigate?

`
#include "unified.h"

/*
This example application sets up an RTU server and handles modbus requests

This server supports the following function codes:
FC 01 (0x01) Read Coils
FC 03 (0x03) Read Holding Registers
FC 15 (0x0F) Write Multiple Coils
FC 16 (0x10) Write Multiple registers
*/

nmbs_t nmbs;

// The data model of this sever will support coils addresses 0 to 100 and registers addresses from 0 to 32
#define COILS_ADDR_MAX 64
#define REGS_ADDR_MAX 32

// Our RTU address
#define RTU_SERVER_ADDRESS 1

// A single nmbs_bitfield variable can keep 2000 coils
nmbs_bitfield server_coils = {0};
uint16_t server_registers[REGS_ADDR_MAX] = {0};

#define MB_RECIEVEBUFFER_SIZE 100
uint8_t mb_recievebuffer[MB_RECIEVEBUFFER_SIZE];
uint32_t mb_recievebuffer_index=0;

void delay1msec(void){
uint32_t countdown=8000;
while(countdown--) asm("");
}

uint8_t _hardfault_was_inside_readwrite=0;

void fake_data(uint8_t* buf,uint16_t count){
_hardfault_was_inside_readwrite=5;
if((mb_recievebuffer_index+count)<=MB_RECIEVEBUFFER_SIZE){
memcpy(&mb_recievebuffer[mb_recievebuffer_index],buf,count);
mb_recievebuffer_index+=count;
}
_hardfault_was_inside_readwrite=1;
}

int32_t read_serial(uint8_t* buf, uint16_t count, int32_t byte_timeout_ms, void* arg) {
_hardfault_was_inside_readwrite=2;
while(byte_timeout_ms--){
// uint32_t recbytes=mcu_tracer_usart_recieved_bytes();
// if(recbytes>0){
// //copies the number of recieved bytes
// uint32_t datalen;
// uint8_t *data;
// data=mcu_tracer_rx_pingpong_buf(&datalen);
// if((mb_recievebuffer_index+datalen)>=MB_RECIEVEBUFFER_SIZE){
// datalen=MB_RECIEVEBUFFER_SIZE-mb_recievebuffer_index;
// }
// memcpy(&mb_recievebuffer[mb_recievebuffer_index],data,datalen);
// mb_recievebuffer_index+=datalen;
// }
if(count<=mb_recievebuffer_index){
_hardfault_was_inside_readwrite=3;
memcpy(buf,&mb_recievebuffer[0],count);
mb_recievebuffer_index=mb_recievebuffer_index-count;
if(mb_recievebuffer_index>0){
_hardfault_was_inside_readwrite=4;
memmove(&mb_recievebuffer[0],&mb_recievebuffer[count],mb_recievebuffer_index);
}
_hardfault_was_inside_readwrite=1;
return count;
}

// delay1msec();
// byte_timeout_ms--;
// if(byte_timeout_ms<1){
// memcpy(buf,&mb_recievebuffer[0],mb_recievebuffer_index);
// mb_recievebuffer_index=0;
// return mb_recievebuffer_index;
// }
_hardfault_was_inside_readwrite=1;
return -1;
}
}

int32_t write_serial(const uint8_t* buf, uint16_t count, int32_t byte_timeout_ms, void* arg) {
return count;
while(mcu_tracer_usart_send_busy()){
delay1msec();
byte_timeout_ms--;
if(byte_timeout_ms<1) break;
}
MBHW_dir_set_write();
//delay1msec();
mcu_tracer_usart_send(buf,count);
mcu_tracer_usart_txdone_wait();
//even when the transmission is done, one last byte is processing, therefore this delay!
uint32_t countdown=2000;
while(countdown--) asm("");
MBHW_dir_set_read();

return count;
}

void onError() {
// Set the led ON on error
}

nmbs_error handle_read_coils(uint16_t address, uint16_t quantity, nmbs_bitfield coils_out, uint8_t unit_id, void *arg) {
return NMBS_ERROR_NONE; //deactive funciton to avoid errors
if (address + quantity > COILS_ADDR_MAX + 1)
return NMBS_EXCEPTION_ILLEGAL_DATA_ADDRESS;

// Read our coils values into coils_out
for (int i = 0; i < quantity; i++) {
bool value = nmbs_bitfield_read(server_coils, address + i);
nmbs_bitfield_write(coils_out, i, value);
}

return NMBS_ERROR_NONE;
}

nmbs_error handle_write_multiple_coils(uint16_t address, uint16_t quantity, const nmbs_bitfield coils, uint8_t unit_id, void *arg) {
if (address + quantity > COILS_ADDR_MAX + 1)
return NMBS_EXCEPTION_ILLEGAL_DATA_ADDRESS;

// Write coils values to our server_coils
for (int i = 0; i < quantity; i++) {
nmbs_bitfield_write(server_coils, address + i, nmbs_bitfield_read(coils, i));
}

return NMBS_ERROR_NONE;
}

nmbs_error handler_read_holding_registers(uint16_t address, uint16_t quantity, uint16_t* registers_out, uint8_t unit_id, void *arg) {
if (address + quantity > REGS_ADDR_MAX + 1)
return NMBS_EXCEPTION_ILLEGAL_DATA_ADDRESS;

// Read our registers values into registers_out
for (int i = 0; i < quantity; i++)
registers_out[i] = server_registers[address + i];

return NMBS_ERROR_NONE;
}

nmbs_error handle_write_multiple_registers(uint16_t address, uint16_t quantity, const uint16_t* registers, uint8_t unit_id, void *arg) {
if (address + quantity > REGS_ADDR_MAX + 1)
return NMBS_EXCEPTION_ILLEGAL_DATA_ADDRESS;

// Write registers values to our server_registers
for (int i = 0; i < quantity; i++)
server_registers[address + i] = registers[i];

return NMBS_ERROR_NONE;
}

void Nanomb_init(void) {
nmbs_platform_conf platform_conf;
platform_conf.transport = NMBS_TRANSPORT_RTU;
platform_conf.read = read_serial;
platform_conf.write = write_serial;
platform_conf.arg = NULL;

nmbs_callbacks callbacks = {0};
callbacks.read_coils = handle_read_coils;
callbacks.write_multiple_coils = handle_write_multiple_coils;
callbacks.read_holding_registers = handler_read_holding_registers;
callbacks.write_multiple_registers = handle_write_multiple_registers;

// Create the modbus server

nmbs_error err = nmbs_server_create(&nmbs, RTU_SERVER_ADDRESS, &platform_conf, &callbacks);
if (err != NMBS_ERROR_NONE) {
onError();
}

nmbs_set_read_timeout(&nmbs, 1000);
nmbs_set_byte_timeout(&nmbs, 100);
}

void nanomb_task(void){
char fakedata[8]={0x01, 0x01, 0x00, 0x00, 0x00, 0x08, 0x3D, 0xCC};
fake_data(&fakedata[0],8);
nmbs_server_poll(&nmbs);
}
`

@greenscreenflicker
Copy link
Author

@debevv ping

@debevv
Copy link
Owner

debevv commented Apr 11, 2024

Hi, unfortunately I really don't have the time to inspect this... I see that your platform is RISC-V, so there may be a minuscule chance that the problem lies inside some non cross-platform code in the library, but first I would like to be 100% sure that it's not just a bug in your application.
Can you try to test the code on linux or on arduino, maybe with a debugger?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants