Skip to content

Commit b29811f

Browse files
committed
hm2_pktuart: Support changes in Rx and Tx modules V2
Higher-resolution timers for better low-frequency performance and better robustness to popping data which is not there. Adds two new setup functions and a dedicated reset function. The original hm2_pktuart_setup is left for compatibility but is now deprecated. (It will work with the V2 uarts but can't set the filter for slow baudrates) Signed-off-by: andypugh <andy@bodgesoc.org>
1 parent a2e6c34 commit b29811f

3 files changed

Lines changed: 190 additions & 15 deletions

File tree

src/hal/drivers/mesa-hostmot2/hostmot2-serial.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,10 @@ int hm2_uart_setup(char *name, int bitrate, rtapi_s32 tx_mode, rtapi_s32 rx_mode
2727
int hm2_uart_send(char *name, unsigned char data[], int count);
2828
int hm2_uart_read(char *name, unsigned char data[]);
2929

30-
int hm2_pktuart_setup(char *name, int bitrate, rtapi_s32 tx_mode, rtapi_s32 rx_mode, int txclear, int rxclear);
30+
int hm2_pktuart_setup(char *name, int bitrate, rtapi_s32 tx_mode, rtapi_s32 rx_mode, int txclear, int rxclear); // deprecated after v2
31+
int hm2_pktuart_setup_rx(char *name, unsigned int bitrate, unsigned int filter_hz, unsigned int parity, int frame_delay, bool rx_enable, bool rx_mask);
32+
int hm2_pktuart_setup_tx(char *name, unsigned int bitrate, unsigned int parity, int frame_delay, bool drive_enable, bool drive_auto, int enable_delay);
33+
void hm2_pktuart_reset(char *name);
3134
int hm2_pktuart_send(char *name, unsigned char data[], rtapi_u8 *num_frames, rtapi_u16 frame_sizes[]);
3235
int hm2_pktuart_read(char *name, unsigned char data[], rtapi_u8 *num_frames, rtapi_u16 *max_frame_length, rtapi_u16 frame_sizes[]);
3336
int hm2_pktuart_queue_get_frame_sizes(char *name, rtapi_u32 fsizes[]);

src/hal/drivers/mesa-hostmot2/hostmot2.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1311,7 +1311,8 @@ typedef struct {
13111311

13121312
typedef struct {
13131313
rtapi_u32 clock_freq;
1314-
rtapi_u32 bitrate;
1314+
rtapi_u32 tx_bitrate;
1315+
rtapi_u32 rx_bitrate;
13151316
rtapi_u32 tx_fifo_count_addr;
13161317
rtapi_u32 tx_bitrate_addr;
13171318
rtapi_u32 tx_addr;
@@ -1888,6 +1889,9 @@ void hm2_pktuart_force_write(hostmot2_t *hm2); // ??
18881889
void hm2_pktuart_prepare_tram_write(hostmot2_t *hm2, long period); //??
18891890
void hm2_pktuart_process_tram_read(hostmot2_t *hm2, long period); // ??
18901891
int hm2_pktuart_setup(char *name, unsigned int bitrate, rtapi_s32 tx_mode, rtapi_s32 rx_mode, int txclear, int rxclear);
1892+
int hm2_pktuart_setup_rx(char *name, unsigned int bitrate, unsigned int filter_hz, unsigned int parity, int frame_delay, bool rx_enable, bool rx_mask);
1893+
int hm2_pktuart_setup_tx(char *name, unsigned int bitrate, unsigned int parity, int frame_delay, bool drive_enable, bool drive_auto, int enable_delay);
1894+
void hm2_pktuart_reset(char *name);
18911895
int hm2_pktuart_send(char *name, unsigned char data[], rtapi_u8 *num_frames, rtapi_u16 frame_sizes[]);
18921896
int hm2_pktuart_read(char *name, unsigned char data[], rtapi_u8 *num_frames, rtapi_u16 *max_frame_length, rtapi_u16 frame_sizes[]);
18931897

src/hal/drivers/mesa-hostmot2/pktuart.c

Lines changed: 181 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -48,14 +48,19 @@ int hm2_pktuart_parse_md(hostmot2_t *hm2, int md_index)
4848
//The PktUART declares a TX and RX module separately
4949
//And Rx can currently be v1 or v2
5050
if (md->gtag == HM2_GTAG_PKTUART_TX
51-
&& !hm2_md_is_consistent_or_complain(hm2,md_index, 0, 4, 4, 0x000F)) {
52-
HM2_ERR("inconsistent Module Descriptor!\n");
51+
&& !hm2_md_is_consistent(hm2,md_index, 0, 4, 4, 0x000F)
52+
&& !hm2_md_is_consistent(hm2,md_index, 1, 4, 4, 0x000F)
53+
&& !hm2_md_is_consistent(hm2,md_index, 2, 4, 4, 0x000F)) {
54+
HM2_ERR("Unsupported or inconsistent PktUART TX module (version %i)"
55+
"not loading driver \n", md->version);
5356
return -EINVAL;
5457
}
5558
if (md->gtag == HM2_GTAG_PKTUART_RX
56-
&& !hm2_md_is_consistent_or_complain(hm2, md_index, 0, 4, 4, 0x000F)
57-
&& !hm2_md_is_consistent_or_complain(hm2, md_index, 1, 4, 4, 0x000F)) {
58-
HM2_ERR("inconsistent Module Descriptor!\n");
59+
&& !hm2_md_is_consistent(hm2, md_index, 0, 4, 4, 0x000F)
60+
&& !hm2_md_is_consistent(hm2, md_index, 1, 4, 4, 0x000F)
61+
&& !hm2_md_is_consistent(hm2, md_index, 2, 4, 4, 0x000F)) {
62+
HM2_ERR("Unsupported or inconsistent PktUART RX module (version %i)"
63+
"not loading driver \n", md->version);
5964
return -EINVAL;
6065
}
6166

@@ -167,6 +172,157 @@ int hm2_pktuart_parse_md(hostmot2_t *hm2, int md_index)
167172
return r;
168173
}
169174

175+
EXPORT_SYMBOL_GPL(hm2_pktuart_setup_rx);
176+
int hm2_pktuart_setup_rx(char *name, unsigned int bitrate, unsigned int filter_hz, unsigned int parity, int frame_delay, bool rx_enable, bool rx_mask){
177+
hostmot2_t *hm2;
178+
hm2_pktuart_instance_t *inst = 0;
179+
rtapi_u32 buff1, buff2;
180+
int i;
181+
int r = 0;
182+
rtapi_u32 filter;
183+
184+
i = hm2_get_pktuart(&hm2, name);
185+
if (i < 0){
186+
HM2_ERR_NO_LL("Can not find PktUART instance %s.\n", name);
187+
return -EINVAL;
188+
}
189+
190+
inst = &hm2->pktuart.instance[i];
191+
192+
/*
193+
PktUART V2+ RX regmap
194+
Bit 30 BadPop Error (read data FIFO with no data) RO
195+
Bits 29..22 RX data digital filter bits (7..0) (in ClockLow periods)
196+
Should be set to 1/2 bit time
197+
(or max=65535 if it cannot be set long enough)
198+
Bit 21 FrameBuffer has data RO
199+
Bits 20..16 Frames received RO
200+
Bit 17 Parity enable WO
201+
Bit 18 Odd Parity WO (1=odd, 0=even)
202+
Bits 15..8 InterFrame delay in bit times RW
203+
Bit 7 RXBusy (serial state machine busy)
204+
Bit 6 RXMask RO
205+
Bit 5 Parity Error RW
206+
Bit 4 RCFIFO Error RW
207+
Bit 3 RXEnable (must be set to receive packets) RW
208+
Bit 2 RXMask Enable (enables input data masking when transmitting) RW
209+
Bit 1 Overrun error (no stop bit when expected) (sticky) RW
210+
Bit 0 False Start bit error (sticky) RW*/
211+
212+
filter = inst->clock_freq / filter_hz;
213+
if (hm2->pktuart.rx_version >= 2){
214+
if (filter > 0xFFFF) filter = 0xFFFF;
215+
buff1 = (rtapi_u32)((bitrate * 16777216.0)/inst->clock_freq); //24 bits in v2+
216+
buff1 |= (rtapi_u32)((filter & 0xFF00) << 16);
217+
} else {
218+
if (filter > 0xFF) filter = 0xFF;
219+
buff1 = (rtapi_u32)((bitrate * 1048576.0)/inst->clock_freq); //20 bits in v0 & v1
220+
}
221+
buff2 = (rtapi_u32)((filter & 0xFF) << 22);
222+
buff2 |= (rtapi_u32)(rx_mask << 2);
223+
buff2 |= (rtapi_u32)(rx_enable << 3);
224+
buff2 |= (rtapi_u32)((frame_delay & 0xFF) << 8);
225+
if (parity > 0) buff2 |= 0x20000;
226+
if (parity == 1) buff2 |= 0x40000;
227+
228+
if (buff1 != inst->rx_bitrate){
229+
inst->rx_bitrate = buff1;
230+
r += hm2->llio->write(hm2->llio, inst->rx_bitrate_addr, &buff1, sizeof(rtapi_u32));
231+
}
232+
if (buff2 != inst->rx_mode){
233+
inst->rx_mode = buff2;
234+
r += hm2->llio->write(hm2->llio, inst->rx_mode_addr, &buff2, sizeof(rtapi_u32));
235+
}
236+
237+
if (r < 0) {
238+
HM2_ERR("PktUART: hm2->llio->write failure %s setting up RX\n", name);
239+
return -1;
240+
}
241+
242+
return 0;
243+
}
244+
245+
EXPORT_SYMBOL_GPL(hm2_pktuart_setup_tx);
246+
int hm2_pktuart_setup_tx(char *name, unsigned int bitrate, unsigned int parity, int frame_delay, bool drive_enable, bool drive_auto, int enable_delay){
247+
hostmot2_t *hm2;
248+
hm2_pktuart_instance_t *inst = 0;
249+
rtapi_u32 buff1, buff2;
250+
int i;
251+
int r = 0;
252+
253+
i = hm2_get_pktuart(&hm2, name);
254+
if (i < 0){
255+
HM2_ERR_NO_LL("Can not find PktUART instance %s.\n", name);
256+
return -EINVAL;
257+
}
258+
inst = &hm2->pktuart.instance[i];
259+
260+
/*
261+
PktUART V2+ TX regmap
262+
Bit 21 FrameBuffer Has Data RO
263+
Bits 20..16 Frames to send RO
264+
Bit 17 Parity enable WO
265+
Bit 18 Odd Parity WO (1=odd, 0=even)
266+
Bits 15..8 InterFrame delay in bit times RW
267+
Bit 7 Send busy RO
268+
Bit 6 Drive Enable bit (enables external RS-422/485 Driver when set) RW
269+
Bit 5 Drive enable Auto (Automatic external drive enable) RW
270+
Drive Enable Auto has priority over Drive Enable (bit 6 is a no-op if bit 5 is set)
271+
Bit 4 SCFIFO Error RO
272+
Bits 3..0 Drive enable delay (delay from asserting drive enable
273+
to start of data transmit. In CLock Low periods RW
274+
Drive enable delay is important to avoid start bit timing errors
275+
at high baud rates in RS-485 (half duplex) modes
276+
*/
277+
278+
if (hm2->pktuart.tx_version >= 2){
279+
buff1 = (rtapi_u32)((bitrate * 16777216.0)/inst->clock_freq); //24 bits in v2+
280+
} else {
281+
buff1 = (rtapi_u32)((bitrate * 1048576.0)/inst->clock_freq); //20 bits in v0 & v1
282+
}
283+
284+
buff2 = (rtapi_u32)(enable_delay & 0x0F);
285+
if (drive_auto) buff2 |= 0x00020;
286+
if (drive_enable) buff2 |= 0x00040;
287+
if (parity > 0) buff2 |= 0x20000;
288+
if (parity == 1) buff2 |= 0x40000;
289+
buff2 |= (rtapi_u32)((frame_delay & 0xFF) << 8);
290+
291+
if (buff1 != inst->tx_bitrate){
292+
inst->tx_bitrate = buff1;
293+
r += hm2->llio->write(hm2->llio, inst->tx_bitrate_addr, &buff1, sizeof(rtapi_u32));
294+
}
295+
if (buff2 != inst->tx_mode){
296+
inst->tx_mode = buff2;
297+
r += hm2->llio->write(hm2->llio, inst->tx_mode_addr, &buff2, sizeof(rtapi_u32));
298+
}
299+
300+
if (r < 0) {
301+
HM2_ERR("PktUART: hm2->llio->write failure %s setting up TX\n", name);
302+
return -1;
303+
}
304+
305+
return 0;
306+
}
307+
308+
EXPORT_SYMBOL_GPL(hm2_pktuart_reset);
309+
void hm2_pktuart_reset(char *name){
310+
hostmot2_t *hm2;
311+
hm2_pktuart_instance_t *inst = 0;
312+
rtapi_u32 buff;
313+
int i;
314+
i = hm2_get_pktuart(&hm2, name);
315+
if (i < 0){
316+
HM2_ERR_NO_LL("Can not find PktUART instance %s.\n", name);
317+
return;
318+
}
319+
inst = &hm2->pktuart.instance[i];
320+
buff = 0x80010000;
321+
hm2->llio->write(hm2->llio, inst->tx_mode_addr, &buff, sizeof(rtapi_u32)); // clear sends, data FIFO and count register
322+
hm2->llio->write(hm2->llio, inst->rx_mode_addr, &buff, sizeof(rtapi_u32)); // clear receives, data FIFO and count register
323+
}
324+
325+
170326
EXPORT_SYMBOL_GPL(hm2_pktuart_setup);
171327
// use -1 for bitrate, tx_mode and rx_mode to leave the mode unchanged
172328
// use 1 for txclear or rxclear to issue a clear command for Tx or Rx registers
@@ -185,12 +341,24 @@ int hm2_pktuart_setup(char *name, unsigned int bitrate, rtapi_s32 tx_mode, rtapi
185341
inst = &hm2->pktuart.instance[i];
186342

187343
if (bitrate > 0){
188-
buff = (rtapi_u32)((bitrate * 1048576.0)/inst->clock_freq); //20 bits in this version
189-
if (buff != inst->bitrate){
190-
inst->bitrate = buff;
191-
r += hm2->llio->write(hm2->llio, inst->rx_bitrate_addr, &buff, sizeof(rtapi_u32));
344+
if (hm2->pktuart.tx_version >= 2){
345+
buff = (rtapi_u32)((bitrate * 16777216.0)/inst->clock_freq); //24 bits in v2+
346+
} else {
347+
buff = (rtapi_u32)((bitrate * 1048576.0)/inst->clock_freq); //20 bits in v0 & v1
348+
}
349+
if (buff != inst->tx_bitrate){
350+
inst->tx_bitrate = buff;
192351
r += hm2->llio->write(hm2->llio, inst->tx_bitrate_addr, &buff, sizeof(rtapi_u32));
193352
}
353+
if (hm2->pktuart.rx_version >= 2){
354+
buff = (rtapi_u32)((bitrate * 16777216.0)/inst->clock_freq); //24 bits in v2+
355+
} else {
356+
buff = (rtapi_u32)((bitrate * 1048576.0)/inst->clock_freq); //20 bits in v0 & v1
357+
}
358+
if (buff != inst->rx_bitrate){
359+
inst->rx_bitrate = buff;
360+
r += hm2->llio->write(hm2->llio, inst->rx_bitrate_addr, &buff, sizeof(rtapi_u32));
361+
}
194362
}
195363

196364
/* http://freeby.mesanet.com/regmap
@@ -280,7 +448,7 @@ int hm2_pktuart_send(char *name, unsigned char data[], rtapi_u8 *num_frames, rt
280448
HM2_ERR_NO_LL("Can not find PktUART instance %s.\n", name);
281449
return -EINVAL;
282450
}
283-
if (hm2->pktuart.instance[inst].bitrate == 0){
451+
if (hm2->pktuart.instance[inst].tx_bitrate == 0){
284452
HM2_ERR("%s has not been configured.\n", name);
285453
return -EINVAL;
286454
}
@@ -403,7 +571,7 @@ int hm2_pktuart_read(char *name, unsigned char data[], rtapi_u8 *num_frames, rta
403571
*num_frames=0;
404572
return -EINVAL;
405573
}
406-
if (hm2->pktuart.instance[inst].bitrate == 0 ) {
574+
if (hm2->pktuart.instance[inst].rx_bitrate == 0 ) {
407575
HM2_ERR("%s has not been configured.\n", name);
408576
*num_frames=0;
409577
return -EINVAL;
@@ -573,7 +741,7 @@ int hm2_pktuart_queue_get_frame_sizes(char *name, rtapi_u32 fsizes[]){
573741
return -EINVAL;
574742
}
575743

576-
if (hm2->pktuart.instance[inst].bitrate == 0 ) {
744+
if (hm2->pktuart.instance[inst].rx_bitrate == 0 ) {
577745
HM2_ERR("%s has not been configured.\n", name);
578746
return -EINVAL;
579747
}
@@ -612,7 +780,7 @@ int hm2_pktuart_queue_read_data(char *name, rtapi_u32 data[], int bytes) {
612780
HM2_ERR_NO_LL("Can not find PktUART instance %s.\n", name);
613781
return -EINVAL;
614782
}
615-
if (hm2->pktuart.instance[inst].bitrate == 0 ) {
783+
if (hm2->pktuart.instance[inst].rx_bitrate == 0 ) {
616784
HM2_ERR("%s has not been configured.\n", name);
617785
return -EINVAL;
618786
}

0 commit comments

Comments
 (0)