I have my embedded linux box with 2 serial ports application, which tests all serial ports with wrap cable (only Rx connected to Tx, no other pins).
The second (non-console) port works fine.
The first (console) port sometimes works, but sometimes does inexplainable things.
To test the first channel I kill running 'getty' before opening it. The respawn is also forbidden.
Then I do the following:
system("killall getty");
Sleep(1000);
if ((fd = open(Name, O_RDWR | O_NOCTTY | O_NONBLOCK)) <= 0)
MsgFatal("Serial '%s' open error %d.", Name, errno);
BRN = B115200;
tcgetattr(fd, &Opts);
cfsetispeed(&Opts, BRN);
cfsetospeed(&Opts, BRN);
cfmakeraw(&Opts);
Opts.c_cflag |= PARENB;
Opts.c_cflag |= PARODD;
Opts.c_cflag &= ~CSTOPB;
Opts.c_cflag &= ~CRTSCTS; /* no HW flow control */
Opts.c_cflag |= CLOCAL | CREAD;
tcsetattr(fd,TCSANOW,&Opts));
After this, SOMETIMES (I mean on some run of the application) the next write operation blocks!
Any advice will be highly appreciated.
First off, the death of a getty process should immediately be reaped by its parent, either init or an aspect of BusyBox, and relaunched. How long it takes can vary, but it is usually pretty quick. But that shouldn't affect writing to the port.
How do you know the write is blocking? Please show that code.
Related
I have several ATMEGA328 based custom boards: I recently found that the standard Arduino bootloader does not handle watchdog timeouts correctly (it keeps resetting, so the device is effectively bricked until the next power cycle) so I am switching to the Optiboot bootloader.
I want to add something to my app that tells me whether the bootloader is Arduino or Optiboot. As Optiboot is a lot smaller, the reset vector is different, so printing that out would be a good indication.
Serial.println (pgm_read_word_near(0), HEX);
The above line of code prints out 940C, and I was expecting something like 7E00. How can I print out the address from the reset vector?
The actual address of the start of the boot flash section is determined by the BOOTSZ fuses.
This reads the size of the bootloader for classic ATmega:
uint32_t bootloaderSize;
cli();
uint8_t highBits = boot_lock_fuse_bits_get(GET_HIGH_FUSE_BITS);
sei();
if (!(highBits & bit(FUSE_BOOTRST))) {
uint8_t v = (highBits & ((~FUSE_BOOTSZ1 ) + (~FUSE_BOOTSZ0 )));
bootloaderSize = MIN_BOOTSZ << ((v >> 1) ^ 3);
}
use #include <avr/boot.h>
I am using the following python script to write AT+CSQ on serial port ttyUSB1.
But I cannot read anything.
However, when I fire AT+CSQ on minicom, I get the required results.
What may be the issue with this script?
Logs:
Manual Script
root#imx6slzbha:~# python se.py
Serial is open
Serial is open in try block also
write data: AT+CSQ
read data:
read data:
read data:
read data:
Logs:
Minicom console
1. ate
OK
2. at+csq
+CSQ: 20,99
3. at+csq=?
OKSQ: (0-31,99),(99)
How can I receive these results in the following python script?
import serial, time
#initialization and open the port
#possible timeout values:
# 1. None: wait forever, block call
# 2. 0: non-blocking mode, return immediately
# 3. x, x is bigger than 0, float allowed, timeout block call
ser = serial.Serial()
ser.port = "/dev/ttyUSB1"
ser.baudrate = 115200
ser.bytesize = serial.EIGHTBITS #number of bits per bytes
ser.parity = serial.PARITY_NONE #set parity check: no parity
ser.stopbits = serial.STOPBITS_ONE #number of stop bits
ser.timeout = None #block read
#ser.timeout = 0 #non-block read
ser.timeout = 3 #timeout block read
ser.xonxoff = False #disable software flow control
ser.rtscts = False #disable hardware (RTS/CTS) flow control
ser.dsrdtr = False #disable hardware (DSR/DTR) flow control
ser.writeTimeout = 2 #timeout for write
try:
ser.open()
print("Serial is open")
except Exception, e:
print "error open serial port: " + str(e)
exit()
if ser.isOpen():
try:
print("Serial is open in try block also")
ser.flushInput() #flush input buffer, discarding all its contents
ser.flushOutput()#flush output buffer, aborting current output
#and discard all that is in buffer
#write data
ser.write("AT+CSQ")
time.sleep(1)
# ser.write("AT+CSQ=?x0D")
print("write data: AT+CSQ")
# print("write data: AT+CSQ=?x0D")
time.sleep(2) #give the serial port sometime to receive the data
numOfLines = 1
while True:
response = ser.readline()
print("read data: " + response)
numOfLines = numOfLines + 1
if (numOfLines >= 5):
break
ser.close()
except Exception, e1:
print "error communicating...: " + str(e1)
else:
print "cannot open serial port "
You have two very fundamental flaws in your AT command handling:
time.sleep(1)
and
if (numOfLines >= 5):
How bad are they? Nothing will ever work until you fix those, and by that I mean completely change the way you send and receive command and responses.
Sending AT commands to a modem is a communication protocol like any other protocols, where certain parts and behaviours are required and not optional. Just like you would not write a HTTP client that completely ignores the responses it gets back from the HTTP server, you must never write a program that sends AT commands to a modem and completely ignores the responses the modem sends back.
AT commands are a link layer protocol, with with a window size of 1 - one. Therefore after sending a command line, the sender MUST wait until has received a response from the modem that it is finished with processing the command line, and that kind of response is called Final result code.
If the modem uses 70ms before it responds with a final result code you have to wait at least 70ms before continuing, if it uses 4 seconds you have to wait at least 4 seconds before continuing, if it uses several minutes (and yes, there exists AT commands that can take minutes to complete) you have to wait for several minutes. If the modem has not responded in an hour, your only options are 1) continue waiting, 2) just give up or 3) disconnect, reconnect and start all over again.
This is why sleep is such a horrible approach that in the very best case is a time wasting ticking bomb. It is as useful as kicking dogs that stand in your way in order to get them to move. Yes it might actually work some times, but at some point you will be sorry for taking that approach...
And regarding numOfLines there is no way anyone in advance can know exactly how many lines a modem will respond with. What if your modem just responds with a single line with the ERROR final result code? The code will deadlock.
So this line number counting has to go completely away, and instead your code should be sending a command line and then wait for the final result code by reading and parsing the response lines from the modem.
But before diving too deep into that answer, start by reading the V.250 specification, at least all of chapter 5. This is the standard that defines the basics of AT command, and will for instance teach you the difference between a command and a command line. And how to correctly terminate a command line which you are not doing, so the modem will never start processing the commands you send.
I've wrote my very first MSP-EXP430F5529LP LED on/off program.
and I wanted to analyze my program. but I had problem at my first step.
I extracted my LED program from board and I've got unclear data. (3)
that's my first question. what is that file format? I mean I want to know file format for my memory dump file. (3)
my second question is that why CCS 6 doesn't indicate memory address properly?
I know that MSP430 is 16 bit MCU. so every memory address should be 16 bit-width. but my assembly code(2) which is copied from CCS6 Disassembly View show me address just like 01XXXX format.
relative data dereference and execution flow branches work well. but why CSS6 make me confused? I mean I want to know that why CCS6 display memory addresse 24 bit-width??
anyone who know where is TI document which explain what I want to know, please let me know. please just don't mention MSP430xxxx User's Guide.
sorry for my english :(
1.c code
#include <msp430f5529.h>
volatile unsigned int i;
void main(void) {
WDTCTL = WDTPW | WDTHOLD;
P1DIR |= 0x01;
while(1){
P1OUT ^= 0x01;
for(i = 20000;i > 0; i--);
}
}
2.assembly code
0100c2: 40B2 5A80 015C MOV.W #0x5a80,&Watchdog_Timer_WDTCTL
0100c8: D3D2 0204 BIS.B #1,&Port_A_PADIR
0100cc: E3D2 0202 XOR.B #1,&Port_A_PAOUT
0100d0: 40B2 4E20 2400 MOV.W #0x4e20,&i
0100d6: 3C02 JMP (0x00dc)
0100d8: 8392 2400 DEC.W &i
0100dc: 9382 2400 TST.W &i
0100e0: 27F5 JEQ (0x00cc)
0100e2: 3FFA JMP (0x00d8)
0100e4: 4303 NOP
0100e6: D032 0010 BIS.W #0x0010,SR
0100ea: 3FFD JMP (0x00e6)
0100ec: 431C MOV.W #1,R12
0100ee: 0110 RETA
0100f0: 4303 NOP
0100f2: 3FFF JMP (0x00f2)
3.memory dump (MAIN)
:1044000031400044b113ec000c930224b1130000be
:104410000c43b113c200b113f00000000200000011
:10442000840001001a44000000240000ffffffff89
:10443000ffffffffffffffffffffffffffffffff8c
:10444000ffffffffffffffffffffffffffffffff7c
...
...
If one reads the User Guide (which is why they exist) then one is informed that the Program Counter is 20-bit. So, now you know why you see an address in the 20-bit range.
Link to the MSP430 User Guide: http://www.ti.com/lit/ug/slau208n/slau208n.pdf
The 20-bit PC (PC/R0) points to the next instruction to be executed.
Each instruction uses an even number of bytes (2, 4, 6, or 8 bytes),
and the PC is incremented accordingly. Instruction accesses are
performed on word boundaries, and the PC is aligned to even addresses.
Figure 6-3 shows the PC.
The above is an excerpt from the User Guide. I cannot emphasis this enough - but you really need to read the User Guide. Not doing so and attempting to program microcontrollers is perlious to your mental health.
The memory dump seems to be in the Intel hex file format https://en.wikipedia.org/wiki/Intel_HEX
I am an electrical student and want to use arduino due to generate pulses for driving MOSFETs. I am making a inverter and want to generate pulses. I have arduino due with me. My main aims are :
1) one software interrupt for sampling the next time period (this will be changing..). After three cycles I will analogRead() new value of time period and same continues .
2) During one time period,set by RC count of Timer channel TC0, I want to load RA0 and RB0 with appropriate counts to get output pulses with different duty ratios(depending on RA0 and RB0 values).
I wrote a program which gives software interrupts with TC3 which is working fine. i.e. I am able to load new values into RA0 and RB0 automatically for every new sampled value( every 3 cycles new values comes else same values will be loaded).
Now I also used TC0 (i used Olavi Kamppari's library) for stopping, loading new values and starting the timer.
when i checked PIO_PB25B_TIOA0 and PIO_PB27B_TIOB0 in the serial monitor i am getting 33554432,134217728 .
I am really confused.I expected a 1 and 0 output. I just want two pulses from TC0 without interrupt.I set the ACPA value to 3 (Toggle) and I enabled the clock to the timer as well.Still I am not getting the output.
So if possible please provide me a sample program that can output pulses from PB25 and PB27 (TIOA0 and TIOB0). Any help will be greatly appreciated.
Thanks for reading my question.
Thank you.
The following sketch outputs a 3 MHz signal on TIOA6 (Pin 5 from memory)
I am about to post a question regarding the same code - I want to get to 8 (and a little bit) MHz but have hit a conceptual brick wall!
Note that this is under development - the IRQ handler is not used - and the PMC_Enable_Periph should be referring to ID_TC6 (I believe) - then the IRQ handler can be placed in the dust bin of history!
void TC6_Handler()
{
TC_GetStatus(TC2, 0);
}
void startTimer(Tc *tc, uint32_t channel, IRQn_Type irq) {
pmc_set_writeprotect(false);
pmc_enable_periph_clk((uint32_t)irq);
TC_Configure(tc, channel,
TC_CMR_WAVE |
TC_CMR_WAVSEL_UP_RC |
TC_CMR_TCCLKS_TIMER_CLOCK1|
TC_CMR_ACPA_TOGGLE ); // RC compare TOGGLES TIOA)smiley-wink;
TC_SetRA(tc, channel, 1); //50% high, 50% low
TC_SetRC(tc, channel, 1);
PIO_Configure(PIOC,
PIO_PERIPH_B,
PIO_PC25B_TIOA6,
PIO_DEFAULT);
TC_Start(tc, channel);
}
void setup(){
startTimer(TC2, 0, TC6_IRQn);
}
void loop(){
}
I am using MSP430F5418 with IAR EW 5.10.
I am trying to output the RTCCLK signal from MSP's 29th pin with a frequency of 1Hz.
When I output the signal it is coming through the port.
But after I re-writing the RTC time, the signal stopped.
I tried to re-enable it, but it didn't worked.
Can anybody tell me what the reason is??
I am using the Work-around code provided by TI for setting RTC time.
My RTC configuration is:
RTCCTL01 |= RTCHOLD;
RTCCTL01 |= RTCMODE + RTCTEV_0 + RTCRDYIE + RTCTEVIE;
P2DIR |= BIT4; P2SEL |= BIT4;
RTCCTL23 = RTCCALF1 | RTCCAL0;
RTCCTL01 &= ~(RTCHOLD);
The RTC Calibration depends on the output of Pre-scalar timer