2. 3.8 Bộ định thời
4.2.3.2 Quá trình truyền và nhận dữ liệu của cổng COM của PC
Truyền dữ liệu là quá trình đưa dữ liệu ra cổng nối tiếp từ máy tính. Khi máy tính muốn truyền một byte dữ liệu ra cổng để truyền ra cáp bên ngoài, máy tính sẽ
gửi byte này trên bus dữ liệu bên trong máy tính. ra tới địa chỉ vào ra của cổng COM. Cổng COM sẽ giữ byte này, và gửi nó ra ngoài từng bit một (dòng truyền bit dữ liệu) qua chân truyển của cổng. Byte này được đưa vào một thanh ghi dịch bên trong cổng. Các bit trên thanh ghi cổng này được lấy từng byte một và được truyền từng bit một trên đường truyền nối tiếp. Khi bit cuối cùng được truyền đi thì thanh ghi dịch cần byte khác để truyền thì nó có thể yêu cầu CPU gửi cho nó một byte khác. Công việc có vể như đơn giản, song nó yêu cầu phải có thời gian trễ bởi vì CPU không thể đưa ra byte ngay lập tức do nó còn phải làm mốt số công việc khác không thể chỉ có việc quản lý cổng COM. Có một cách để giải quyết việc trễ thời gian này đó là sắp xếp lại mọi thứ để cho CPU gửi byte vào bộ đệm của cổng COM(trong phần cứng) trước khi thanh ghi dịch cần nó. Nhờ vậy khi thanh ghi dịch truyền byte của nó ra ngoài và đang cần một byte mới thì phần cứng của cổng COM chuyển byte tiếp theo từ bộ đệm của nó cho thanh ghi dịch mà không cần gọi CPU phát lệnh truyền một byte mới.
Kích thước của bộ đệm (phần cứng) của cổng COM trước đây chỉ là một byte, nhưng hiện nay thông thường có 16 byte. Hiện này vẫn tồn tại vấn đề về giữ bộ đệm cung cấp đầy đủ byte để khi thanh ghi dịch cần byte để truyền nó sẽ luôn tìm thấy (trừ khi không có byte nào để gửi đi nữa). Điều này được thực hiện bằng việc kết nối với CPU bằng việc sử dụng “ngắt”. Ngắt ở đây có thể hiểu là sự dừng công việc đang thực hiện để thực hiện một công việc ở vị trí khác, và sẽ trở lại làm công việc này sau khi hoàn thành công việc ở ngắt. Ở đây có thể xem công việc của ngắt là quá trình cung cấp dữ liệu cho bộ đệm của cổng COM. CPU khi có ngắt gọi sẽ tạm dừng công việc mà nó đang làm để cung cấp dữ liệu cho bộ đệm cổng COM. Sau khi cung câp xong dữ liệu thì nó sẽ trở lại công việc của nó.
Với trường hợp của cổng COM cũ với 8 bit trong bộ đệm. Khi thanh ghi dịch lấy byte ra khỏi bộ đệm và nó yêu cầu một byte khác. Lúc này nó sẽ gửi ngắt tới CPU bằng cách đưa một điện áp lên dây chức năng chuyên dụng lên bus của máy tính. Trừ khi CPU đang làm một công việc gì cực kỳ quan trọng mà không cho phép ngắt này được thực hiện, còn trong các trường hợp còn lại thì ngắt sẽ tác động đến
CPU để nó dừng công việc đang thực hiện và bắt đầu thực hiện một chương trình dùng để cung cấp một byte khác cho bộ đệm của cổng COM. Mục đích của bộ đệm này là dữ một byte dự trữ trong hàng đợi (trờ để truyền) trong phần cứng để không bị trống trong quá trình truyền các byte dữ liệu ra cáp của cổng COM.
Đối với CPU, một khi nhận được ngắt, nó sẽ biết ai đã gửi ngắt cho nó vì có một dây ngắt đặc thù cho mỗi cổng COM (trừ khi các ngắt bị chia sẻ). Tiếp đó CPU sẽ chạy thiết bị nối tiếp để kiểm tra địa chỉ của cổng gửi ngắt. Nó sẽ thấy bộ đệm của cổng này bị trống và đang đợi một byte gửi vào. Vì vậy nếu có byte để gửi thì nó sẽ chuyển byte kế tiếp để truyền vào trong bộ đệm. Byte sẽ được kế tiếp có thể được đưa vào bộ đệm trong khi byte trước nó đang ở trong thanh ghi dịch truyền dữ liệu và đang trong quá trình truyền dữ liệu từng bit một.
Tóm lại khi một byte đã truyền hoàn toàn ra đường truyền của cổng COM và thanh ghi dịch đang trống thì sẽ có 3 vấn đề xảy ra gần như là đồng thời:
Byte kế tiếp sẽ được chuyển từ bộ đệm truyền của cổng COM vào thanh ghi dịch truyền dữ liệu.Quá trình truyền dữ liệu từng bit một của byte mới bắt đầu Một ngắt khác được phát ra để báo cho cho thiết bị biết để gửi một byte khác tới bộ đệm hiện thời đang trống.
Vì vậy có thể coi cổng COM là một thiết bị hoạt động có ngắt. Mỗi khi cổng COM phát ra một ngắt thì CPU sẽ truyền cho nó một byte khác. Một khi một byte được gửi tới bộ đệm bởi CPU, CPU sẽ tiếp tục tự do để thực hiện hàng động khác cho tới khi nó nhận được một ngắt khác. Cổng COM sẽ truyền dữ liệu các bit với tốc độ thích hợp với tốc độ được chọn bởi người sử dụng (hoặc một trình ứng dụng nào đó). Tốc độ này được gọi là baudrate. Ngoài ra cổng COM cũng thêm các bit như bit start, stop, đôi khi cả parity vì vậy thường có tới 1 bit được gửi trong mỗi byte dữ liệu. Ở tốc độ 19200 bps sẽ có 1920 byte/sec (và cùng có tới 1920 ngắt/sec). Để thực hiện tất cả các công việc này thì CPU phải làm rất nhiều việc. Đầu tiên là gửi 8 byte 8 bit trong một lần trong khi bus dữ liệu của máy tính là 32 bit (hoặc có thể lên tới 64 bit). Việc này đã không sử dụng hiệu quả độ rộng của bit dữ liệu. Tiếp đó là có quá nhiều các ngắt cần xử lý và việc xử lý các ngắt cũng yêu cầu
nhiều việc. Khi một ngắt được nhận vào, thiết bị điều khiển chỉ biết là có ngắt ở cổng mà không biết đó là ngắt yêu cầu thêm ký tự vào chỗ ký tự đã được truyền đi. Thiết bị điều khiển phải làm rất nhiều sự kiểm tra để phát hiện ra cái gì đã xảy ra dẫn đến ngắt. Bởi khi một ký tự được nhận cũng có cùng ngắt như vậy cộng thêm đường điều khiển thay đổi trạng thái…Với tốc độ truyền chậm thì việc có bộ đệm nhận 1 byte không là vấn để gì nhưng khi tốc độ cao hơn thì sẽ có thể đẫn đển việc CPU không thể thực hiện công việc của UART đúng lúc gây ra sự ghi đè dữ liệu (trong khi nhận dữ liệu) gây ra các lỗi “overrun” hay “overflow”.
Một sự tiến bộ lớn đó là tăng dung lượng bộ đệm của cổng COM từ 1 byte lên tới 16 byte. Điều này nghĩa là khi CPU nhận được ngắt nó có thể đưa vào bộ đệm tới 16 byte tiếp để truyền. Nó làm cho ngắt ít hơn để làm các công việc khác trong khi dữ liệu vẫn được gửi từng byte trên một độ rộng bit. Với 16 byte không những bộ đệm có thể đợi nhiều byte hơn mà có thể nhận tới 16 byte một lúc. Bộ đệm 16 byte thực sự là một hàng đợi kiểu FIFO (First In First Out)- vào trước ra trước.
application 8k-byte 16-byte 1k-byte tele- BROWSER --- MEMORY --- FIFO --- MODEM --- phone program buffer buffer buffer line
Quá trình nhận dữ liệu từ các byte bởi cổng COM cũng giống như việc truyền chúng chỉ khác là có chiều ngược lại. Nó cũng cần gọi ngắt. Với loại cổng COM kiểu cũ, khi một byte được nhận đầy đủ. từ cáp bên ngoài nó được được chuyển vào bộ đệm nhận 1 byte. Tiếp đó cổng sẽ đưa cho CPU một ngắt để báo rằng nó nhận được một byte yêu cầu lấy byte đó đi để nó có thể có chỗ trống cho byte tiếp theo đang được nhận về. Với cổng COM mới thì ngắt sẽ đươc đưa ra khi có tới 14 byte được nhận vào trong bộ đệm. Khi đó CPU sẽ thực hiện việc lấy 14 hoặc 16 byte ra khỏi bộ đệm. Trong quá trình thực hiện ngắt có thể có thêm 2 byte nữa được nhận vào trong bộ đệm. Nếu như có tới 3 byte được đưa vào trong thời gian này thì sẽ gây ra lỗi Overrun. Để chắc chắn không xảy ra lỗi này, có thể phát tín hiệu gọi ngắt khi bộ đệm có ít hơn 14 byte. Việc đặt bao nhiêu phần trăm bộ
đệm thì phát tín hiệu ngắt cho CPU lấy dữ liệu ra tùy thuộc vào người phần mềm bên trong. Nếu đặt 1 byte thì nó sẽ hoạt động như cổng COM kiểu cũ (trừ trường hợp trong bộ đệm đã có 15 byte đầy).
Tại sao bộ đệm FIFO lại nhỏ như vậy, tại sao không làm nó lớn. Lý do có phải là do giá làm bộ nhớ đắt hay không? Đây chắc chắn sẽ là thắc mắc đối với người biết về cấu trúc của bộ đêm FIFO. Câu trả lời đó là không phải bởi vì giá bộ nhớ rất rẻ nên không có vấn đề gì về giá khi tăng bộ đệm này lên kilobyte. Vấn đề ở đây chính là do việc điều khiển đường truyền trong quá trình truyền nhận dữ liệu. Chế độ điều khiển đường truyền có thể làm dừng lại dòng chảy của dữ liệu trên đường truyền nối tiếp khi thấy cần thiết. Nếu một tín hiệu stop được ra cổng COM, tiếp đó việc yêu cầu dừng lại được giữ bởi chế độ Software phần cứng của cổng COM không biết về điều khiển đường truyền. Nếu bộ đệm của cổng COM chứa 64 byte sẵn sàng để truyền đi khi nó nhận tín hiệu điều khiển đường truyền để dừng quá trình truyền lại, nó sẽ gửi 64 byte ra một cách lộn xộn trong khi bị bắt dừng lại. Sẽ không có sự dừng lại quá trình gửi vì nó không biết về chế độ điều khiển này. Nếu như bộ đệm lớn hơn thì sẽ có nhiều byte hơn bị gửi trong khi bị yêu cầu bắt buộc dừng của chế độ điều khiển đường truyền.
Mặc dù không để cho bộ đệm truyền ở phần cứng lớn nhưng trong chế độ truyền thông nối tiếp cũng có các bộ đệm nối tiếp lớn hơn 16 byte. Đó là các bộ đệm được lấy trong bộ nhớ chính. Chúng được sử dụng như sau:
Khi CPU lấy được các byte từ bộ đệm 16 byte nó đặt các byte này vào bộ đệm lớn hơn lấy trong bộ nhớ chính (Khoản 8k-byte). Tiếp đó chương trình lấy dữ liệu từ cổng COM sẽ lấy dữ liệu từ bộ đệm lớn hơn này. Đối với truyền dữ liệu cũng tương tự. Khi CPU cần phải nạp một số byte để truyền nó lấy chúng ra khỏi một bộ đệm truyền lớn (8k-byte) trong bộ nhớ chính và đưa chúng vào trong bộ đệm truyền 16 byte trong phần cứng.