Uart close problem

Hi!
I have a problem in my project. I use FCM to communicate with external devices. Everything works well. But at the end of the program I can not close the port!!! After switching to AT MODE I get event ADL_FCM_EVENT_V24_AT_MODE. Then I call the function adl_fcmUnsubscribe (rs232_state.handle) and get event ADL_FCM_EVENT_FLOW_CLOSED. Next I close the port using the command “AT + WMFM = 0,0,1” and get error answer: “+ CME ERROR: 3.” Port stoped only when the application is stopped (AT+WOPEN=0). Module SL6087, FW: 7.46. How i can close port??? Help please!

Main:

#include "adl_global.h"
#include "generated.h"
#include "dr_rs232.h"

typedef struct{
	bool start;
	adl_tmr_t *rs232_poll_handle;
}Poll_str;

Poll_str poll_str;

s8 poll_start(void);
void poll_stop(void);

bool poll_answer_uart1_on(adl_atResponse_t *response);
bool poll_answer_uart2_on(adl_atResponse_t *response);
bool poll_answer_uart1_off(adl_atResponse_t *response);
bool poll_answer_uart2_off(adl_atResponse_t *response);

void rs232_poll_control(Trs232_event event){
	switch(event){
		case RS232_EVENT_START_OK:{
			adl_atSendResponse(ADL_AT_UNS,"\r\nPOLL: EVENT_START_OK");
			break;
		}
		case RS232_EVENT_START_ERR:{
			adl_atSendResponse(ADL_AT_UNS,"\r\nPOLL: EVENT_START_ERR");
			break;
		}
		case RS232_EVENT_STOP_OK:{
			adl_atSendResponse(ADL_AT_UNS,"\r\nPOLL: EVENT_STOP_OK");
			adl_atSendResponse(ADL_AT_UNS,"\r\nPOLL: START OFF UARTS");
			
			adl_atCmdCreate("at+wmfm=0,0,1",ADL_PORT_OPEN_AT_VIRTUAL_BASE,poll_answer_uart1_off,"OK",NULL);
			break;
		}
		case RS232_EVENT_STOP_ERR:{
			adl_atSendResponse(ADL_AT_UNS,"\r\nPOLL: EVENT_STOP_ERR");
			break;
		}
		case RS232_EVENT_DATA_TRANSMIT:{
			adl_atSendResponse(ADL_AT_UNS,"\r\nPOLL: EVENT_DATA_TRANSMIT");
			break;
		}
		default:{
			adl_atSendResponse(ADL_AT_UNS,"\r\nPOLL: EVENT_ERROR!!!");
			break;
		}
	}
}


void rs232_poll_data_come(u8 *buff, u16 length){
	ascii buffer[50];
	memset(buffer,'\0',sizeof(buffer));

	memcpy(buffer,buff,length);
	adl_atSendResponse(ADL_AT_UNS,"\r\nPOLL DATA COME: ");
	adl_atSendResponse(ADL_AT_UNS,buffer);
	if(length==9){
		if(strncmp(buffer,"POOL_STOP",9)==0){
			adl_atSendResponse(ADL_AT_UNS,"\r\nPOLL: STOP COMMAND COME!!!");
			poll_stop();
		}
	}
	else{
		rs232_send_data((u8*)buffer,strlen(buffer));
	}
}

s8 poll_start(void){
	if(poll_str.start) return ERROR;
	s32 err=dr_rs232_subscribe(rs232_poll_control,rs232_poll_data_come,ADL_PORT_UART1,19200,RS232_RTS_CTS_OFF,RS232_FORMAT_8D_1S,RS232_PARITY_NONE);
	if(err==ERROR){
		adl_atSendResponse(ADL_AT_UNS,"\r\nPOLL: dr_rs232_subscribe ERROR!!!");
		return ERROR;
	}
	else{
		adl_atSendResponse(ADL_AT_UNS,"\r\nPOLL: dr_rs232_subscribe OK");
		poll_str.start=TRUE;
		return OK;
	}
}

void  poll_stop(void){
	if(!poll_str.start) return;
	dr_rs232_unsubscribe();
	poll_str.start=FALSE;
}

void rs232_pool_timer(u8 ID,void *vv){
	adl_atSendResponse(ADL_AT_UNS,"\r\nPOLL: TIMER TICK");
}

bool poll_answer_uart1_on(adl_atResponse_t *response){
	adl_atSendResponse(ADL_AT_UNS,"\r\nPOLL: UART1 ON");
	return FALSE;
}
bool poll_answer_uart2_on(adl_atResponse_t *response){
	adl_atSendResponse(ADL_AT_UNS,"\r\nPOLL: UART2 ON");
	return FALSE;
}

bool poll_answer_uart1_off(adl_atResponse_t *response){
	adl_atSendResponse(ADL_AT_UNS,"\r\nPOLL:UART1 OFF OK");
	adl_atCmdCreate("at+wmfm=0,0,2",ADL_PORT_OPEN_AT_VIRTUAL_BASE,poll_answer_uart1_off,"OK",NULL);
	return TRUE;
}

bool poll_answer_uart2_off(adl_atResponse_t *response){
	adl_atSendResponse(ADL_AT_UNS,"\r\nPOLL:UART2 OFF OK");
	return TRUE;
}

void main_task ( void )
{
	adl_atCmdCreate("at+wmfm=0,1,1",ADL_PORT_OPEN_AT_VIRTUAL_BASE,poll_answer_uart1_on,"*",NULL);
	adl_atCmdCreate("at+wmfm=0,1,2",ADL_PORT_OPEN_AT_VIRTUAL_BASE,poll_answer_uart2_on,"*",NULL);

	if(poll_start()==ERROR){
		adl_atSendResponse(ADL_AT_UNS,"\r\nPOLL: poll_start ERROR");
	}
	if(!poll_str.rs232_poll_handle){
		poll_str.rs232_poll_handle=adl_tmrSubscribe(TRUE,50,ADL_TMR_TYPE_100MS,rs232_pool_timer);
	}
}

rs232_driver:

#include "adl_global.h"
#include "dr_rs232.h"
#include "wm_uart.h"

#define RS232_EVENT_TIME 20

s32 rs232_power_handle=0;

void rs232_event_start(Trs232_event event);
void rs232_event_stop(void);
void rs232_event(u8 ID,void *vv);
adl_tmr_t *rs232_handle_event=NULL;
adl_tmr_t *rs232_handle_packet=NULL;

bool rs232_answer_uart1_ipr(adl_atResponse_t *response);
bool rs232_answer_uart1_ifc(adl_atResponse_t *response);
bool rs232_answer_uart1_icf(adl_atResponse_t *response);

Trs232_ctrl_hdlr rs232_ctrl_hdlr;
Trs232_data_hdlr rs232_data_hdlr;

bool rs232_control_uart1(adl_fcmEvent_e Event);
bool rs232_data_uart1(u16 DataLen, u8 * Data);

typedef struct TRS232_STATE
{
	bool start;
	u32 rate;
	s8 handle;
	Trs232_mode mode;
	Trs232_format format;
	Trs232_parity parity;
	Trs232_event event;
}Trs232_state;

Trs232_state rs232_state;

int32_t dr_rs232_subscribe(Trs232_ctrl_hdlr ctrl_handler,Trs232_data_hdlr data_handler,adl_port_e port,u32 rate,Trs232_mode mode,Trs232_format format,Trs232_parity parity)
{
	if(rs232_state.start) return ERROR;
	adl_ioDefs_t gpio_rs232_power[1]={(ADL_IO_GPIO|RS232_GPIO_POWER|ADL_IO_DIR_OUT)};
	rs232_state.start=TRUE;;
	if(RS232_DEBUG_FLAG) adl_atSendResponse(ADL_AT_UNS,"\r\nRS232:START");
	rs232_power_handle=adl_ioSubscribe(1,gpio_rs232_power,0,0,0);
	if(adl_ioWriteSingle ( rs232_power_handle,gpio_rs232_power, TRUE )<0) return ERROR; //on rs232 chip
	rs232_state.rate=rate;
	rs232_state.mode=mode;
	rs232_state.format=format;
	rs232_state.parity=parity;
	rs232_state.handle=adl_fcmSubscribe(port,rs232_control_uart1,rs232_data_uart1);
	if(rs232_state.handle<0)	adl_atSendResponse(ADL_AT_UNS,"\r\nUART adl_fcmSubscribe error!");
	else	adl_atSendResponse(ADL_AT_UNS,"\r\nUART adl_fcmSubscribe OK!");
	rs232_ctrl_hdlr=ctrl_handler;
	rs232_data_hdlr=data_handler;
	if((rs232_power_handle<0)||(rs232_state.handle<0))return ERROR;
	return OK;
}

void dr_rs232_unsubscribe(void)
{
	if(!rs232_state.start) return;
	adl_ioDefs_t gpio_write[1]={(ADL_IO_GPIO|RS232_GPIO_POWER)};
	rs232_state.start=FALSE;
	if(RS232_DEBUG_FLAG) adl_atSendResponse(ADL_AT_UNS,"\r\nRS232:STOP");
	adl_ioWriteSingle ( rs232_power_handle,gpio_write, FALSE );// off rs232 chip
	adl_ioUnsubscribe(rs232_power_handle);
	adl_fcmSwitchV24State(rs232_state.handle,ADL_FCM_V24_STATE_AT);// switch to at mode
}

bool rs232_control_uart1(adl_fcmEvent_e Event)
{
	switch(Event)
	{
		case ADL_FCM_EVENT_FLOW_OPENNED:{
			if(RS232_DEBUG_FLAG)	adl_atSendResponse(ADL_AT_UNS,"\r\nRS232:ADL_FCM_EVENT_FLOW_OPENNED");
			ascii command_buff[15]="\0";
			wm_sprintf(command_buff,"at+ipr=%ld",rs232_state.rate);
			adl_atCmdCreate(command_buff,ADL_AT_PORT_TYPE(ADL_PORT_UART1, FALSE),rs232_answer_uart1_ipr,NULL);
			if(rs232_state.mode==RS232_RTS_CTS_OFF)adl_atCmdCreate("at+ifc=0,0",ADL_AT_PORT_TYPE(ADL_PORT_UART1, FALSE),rs232_answer_uart1_ifc,NULL);
			else adl_atCmdCreate("at+ifc=2,2",ADL_AT_PORT_TYPE(ADL_PORT_UART1, FALSE),rs232_answer_uart1_ifc,NULL);
			wm_sprintf(command_buff,"at+icf=%d,%d",rs232_state.format,rs232_state.parity);
			adl_atCmdCreate(command_buff,ADL_AT_PORT_TYPE(ADL_PORT_UART1, FALSE),rs232_answer_uart1_icf,NULL);
			adl_fcmSwitchV24State(rs232_state.handle,ADL_FCM_V24_STATE_DATA);
			break;
		}
		case ADL_FCM_EVENT_V24_DATA_MODE:{
			if(RS232_DEBUG_FLAG)	adl_atSendResponse(ADL_AT_UNS,"\r\nRS232:ADL_FCM_EVENT_V24_DATA_MODE");
			rs232_event_start(RS232_EVENT_START_OK);
			break;
		}
		case ADL_FCM_EVENT_V24_AT_MODE:{
			if(RS232_DEBUG_FLAG)	adl_atSendResponse(ADL_AT_UNS,"\r\nRS232:ADL_FCM_EVENT_V24_AT_MODE");
			adl_fcmUnsubscribe(rs232_state.handle);
			rs232_event_start(RS232_EVENT_STOP_OK);
			break;
		}
		case ADL_FCM_EVENT_V24_AT_MODE_EXT:{
			if(RS232_DEBUG_FLAG)	adl_atSendResponse(ADL_AT_UNS,"\r\nRS232:ADL_FCM_EVENT_V24_AT_MODE_EXT");
			break;
		}
		case ADL_FCM_EVENT_V24_DATA_MODE_EXT:{
			if(RS232_DEBUG_FLAG)	adl_atSendResponse(ADL_AT_UNS,"\r\nRS232:ADL_FCM_EVENT_V24_DATA_MODE_EXT");
			break;
		}
		case ADL_FCM_EVENT_FLOW_CLOSED:{
			if(RS232_DEBUG_FLAG)	adl_atSendResponse(ADL_AT_UNS,"\r\nRS232:ADL_FCM_EVENT_FLOW_CLOSED!!!");
			break;
		}
		case ADL_FCM_EVENT_MEM_RELEASE:{
			if(RS232_DEBUG_FLAG)	adl_atSendResponse(ADL_AT_UNS,"\r\nRS232:ADL_FCM_EVENT_MEM_RELEASE");
			rs232_ctrl_hdlr(RS232_EVENT_DATA_TRANSMIT);
			break;
		}
		default:return TRUE;
	}
	return TRUE;
}

bool rs232_data_uart1(u16 DataLen, u8 * Data)
{
	ascii rs232_temp_buff[50]="\0";
	u16 rs232_i;
	wm_sprintf(rs232_temp_buff,"\r\nRS232 DATA COME: ");
	adl_atSendResponse(ADL_AT_UNS,rs232_temp_buff);
	for(rs232_i=0;rs232_i<DataLen;rs232_i++)
	{
		wm_sprintf(rs232_temp_buff,"%02X ",Data[rs232_i]);
		adl_atSendResponse(ADL_AT_UNS,rs232_temp_buff);
	}
	rs232_data_hdlr(Data,DataLen);
	adl_fcmReleaseCredits(rs232_state.handle,0xFF);
	return TRUE;
}

int32_t rs232_send_data(u8 *buff, u16 length)
{

	ascii rs232_temp_buff[50]="\0";
	u16 rs232_i=0;
	if(!rs232_state.start)return ERROR;
	wm_sprintf(rs232_temp_buff,"\r\nRS232 DATA SEND: ");
	adl_atSendResponse(ADL_AT_UNS,rs232_temp_buff);
	for(rs232_i=0;rs232_i<length;rs232_i++)
	{
		wm_sprintf(rs232_temp_buff,"%02X ",buff[rs232_i]);
		adl_atSendResponse(ADL_AT_UNS,rs232_temp_buff);
	}
	return adl_fcmSendData(rs232_state.handle,buff,length);
}

bool rs232_answer_uart1_ipr(adl_atResponse_t *response){
	return FALSE;
}
bool rs232_answer_uart1_ifc(adl_atResponse_t *response){
	return FALSE;
}
bool rs232_answer_uart1_icf(adl_atResponse_t *response){
	return FALSE;
}

void rs232_event_start(Trs232_event event)
{
	if(!rs232_handle_event)
	{
		if(RS232_DEBUG_FLAG)	adl_atSendResponse(ADL_AT_UNS,"\r\nRS232:TIMER EVENT START");
		rs232_state.event=event;
		rs232_handle_event=adl_tmrSubscribe(FALSE,RS232_EVENT_TIME,ADL_TMR_TYPE_TICK,rs232_event);
	}
}

void rs232_event_stop(void)
{
	if(rs232_handle_event)
	{
		if(RS232_DEBUG_FLAG)	adl_atSendResponse(ADL_AT_UNS,"\r\nRS232:TIMER EVENT STOP");
		adl_tmrUnSubscribe(rs232_handle_event,rs232_event,ADL_TMR_TYPE_TICK);
		rs232_handle_event=0;
	}
}

void rs232_event(u8 ID,void *vv)
{
	rs232_handle_event=0;
	if(RS232_DEBUG_FLAG)	adl_atSendResponse(ADL_AT_UNS,"\r\nRS232:TIMER EVENT OK");
	rs232_ctrl_hdlr(rs232_state.event);
}

one question here…

where are you issuing AT+WMFM command??

Is it thru application or thru hyperterminal?

After switching to the AT MODE I call a function adl_fcmUnsubscribe. Then in application I execute command:

adl_atCmdCreate("at+wmfm=0,0,1",ADL_PORT_OPEN_AT_VIRTUAL_BASE,poll_answer_uart1_off,"OK",NULL);

It returns OK, but poll_answer_uart1_off not called (((. After that in hyperterminal through USB i execute a command AT+WMFM=0,0,1 and get “+ CME ERROR: 3”. UART1 is not closed. But UART2 closed successfully. If i use UART2 in my application, UART1 closed successfully, UART2 - unsuccessfully. I twink, problem in using FCM. If a program does not run FCM, ports are opened and closed successfully.

I have a new problem. I do not understand why, but when executing:

adl_atCmdCreate("at+wmfm=0,0,1",ADL_PORT_OPEN_AT_VIRTUAL_BASE,poll_answer_uart1_off,"OK",NULL);

, the controller restarts (even function does not return a result. none at all). why the controller may reboot when the standard command called from the application??? (Sorry for bad english :stuck_out_tongue: )

Ok… i’ll run the FCM appplication at my end and will check it…
you said giving AT+WMFM=0,0,1 give CMEE error -3
Just before executing this command can you check the response of AT+WMFM?

Just a guess… i think it’s already closed may be… and you are trying to close it again…

Regarding the reset… are you getting any backtraces?

also, try with some latest FW 7.52…

7.46 is pretty old…

Thanks